|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
' {' Y: A2 A/ i3 ~) c7 d+ x
一、指令和伪指令; v4 k0 T2 v* X+ n1 [7 }
. `7 g+ l- p# A
汇编指令是CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以
& s* [! ~5 Q9 F5 L. [) [( |# X9 f
5 M8 V9 ]9 C' X9 s9 Z! S 由CPU读取执行。. S" `$ q! N( O% B
( d5 {! k0 `4 s* M3 |0 Z 汇编伪指令本质上不是指令(只是和指令一起写在代码中),它是编译器环境提供
: f" w k! q: X' ?/ I2 G& k! ?, m) U2 F* h: S" V2 `2 @9 E$ y9 ^
的,目的是用来指导编译过程,经过编译后伪指令不会生成机器码。 g/ H, m; L' Y. @; y& d9 Q
$ _6 d! B$ z1 a+ s
二、两种不同风格的ARM指令
. v" c$ U, E/ \. V& I/ J, `8 m& T6 U2 y; _ g
1、ARM官方的ARM汇编风格:指令一般用的小、windows中IDE开发环境如:LDR
7 c( C$ [4 P. {% r
" o* L* _4 E. M6 k7 u* F4 A o R0,[R1]
+ @; f1 z) z5 @
3 H# J0 R: k" ]0 k 2、GNU风格的ARM汇编:指令一般用小写字母、linux中常用。如:ldr r0,[r1]2 O- c5 f) k' M7 _8 \0 Q
: d/ a7 b# a1 Q. _4 m" ^# Y
三、ARM汇编的特点. B+ M# n2 D; t, j, K% \3 w
9 D. l6 L1 Z- V) X% e: J! `
1、LDR/STR架构$ N0 Z/ Q# V$ J) o ~
+ _- l1 w$ N" L1 \ (1)、ARM采用RISC架构,CPU本身不能直接读取内存,需要将内存中的值加载. m5 m1 h7 c5 M$ d! x
- `. ~% ~. `; S1 F/ u8 H; z 到通用寄存器中才能被CPU处理。
+ k5 \$ I& H- r) A3 E. B- `
" }- Q$ b- k% M% N& R! P5 U+ L (2)、ldr指令将内存内容加载入通用寄存器。
5 L) u. E" h' W' P1 ~1 I S+ m. j& l& A
(3)、str指令将寄存器中的值加载到内存空间中。
+ d' f9 w! q5 W1 E% i6 u. _
& z) N# P7 {( w. m0 | (4)、ldr/str组合用来实现ARM CPU和内存数据交换。# _& Y. w4 c3 \" n
7 `. L* j& H9 M3 Y$ k6 Q7 _ 2、ARM汇编特点:多级流水线( ^+ D- Q% z2 L7 n1 w
8 G" Y v8 D" z1 ?
-
. w& z! i$ d% U
3 s0 g) C( B: s4 _. H" k 3、8中寻址方式) q. \9 R8 @. U6 i9 v% w% ^; P
4 Q$ x8 |) S9 b* C- Z
寄存器寻址 mov r1,r2
- s. i9 c' T. s7 x$ G
: G" C; B1 n& _, B v* }( {2 c 立即寻址 mov r0,#0xFF00 ) k% ^0 F+ I6 J
% z% x9 T1 q. B' a5 S: q
寄存器移位寻址 mov r0,r1,lsl#3
8 [% ~) K M7 a/ {& i
- o, o) y) r N/ j, v1 C C) n8 W 寄存器间接寻址 ldr r1,[r2]
8 V9 \1 z' ?+ Z3 C. e* ^8 C: T+ u! x$ J2 @* @, Y# O. h7 X$ K: j
基址变址寻址 ldr r1,[r2,#4] r$ ]3 q2 l2 U
2 E* o) ~4 G1 Q
多寄存器寻址 ldmia r1!,{r2-r7,r12}
- z: |7 Z: [ B4 g
" m8 i5 H% h% [" L0 _9 y% V+ O 堆栈寻址 stmfd sp!,{r2-r7,lr}
) |9 p- ?* ] S& x: S" m1 k$ p7 @2 I& T# m( a
相对寻址 beq flag( Q6 S8 q( F; G* P: I# v" d
& u" k* I5 ? y0 Z; b
flag:
' n. |# h A, L' ^! m+ c% {% g) h* q
3 v2 X8 y) U- Z+ z四、ARM常用的汇编指令:; t. a! R y$ Y# i, T5 |4 D" b
. l* M4 k& X9 L5 E! K 数据传输指令:mov mvn
* q- @) D" D7 ~* G- g: v2 K: n) r/ f3 R* B g! v* D7 v
算术指令: add sub rsb adc sbc rsc
' Y& O3 A+ J: c! _$ a
: q+ N/ n. X0 k$ p) D: K% i% ]! Y 逻辑指令: and orr eor bic% _1 N1 f+ I. i# L0 k9 N1 \" `
' A* L5 G( |3 ~4 A 比较指令: cmp cmn tst teq
m5 E( h; Q% s
1 |0 |3 a& U6 i3 t+ ]* K0 z3 n$ ` 乘法指令: mvl mla umull umlal smull smlal# F/ ^8 }/ } `7 b' T5 |. [
# s. J* ~! h# |# b7 h2 k+ u 前导零计数器 :clz }, @* g. d U( I0 O
+ r; g# f3 p: t# Z8 {* V9 X! J# Y CPSR寄存器比较特殊,需要专门的指令访问:这就是mrs和msr
% w7 |/ q, S& ~- C* t5 i
3 C3 ~9 g, q8 Z) x mrs用来读取CPSR的值,msr用来写CPSR6 Q. a: X. o% X8 D
+ m. N+ U U3 F& D# O; m
协处理器cp15操作指令3 g( ~- U9 p/ G" {# d9 B% ~$ d% V
" Q: x6 s" b" v. m
mrc用来读取cp15中的寄存器,mcr用来写入cp15中的寄存器
& k& e+ R; t5 F/ {7 o/ A v
7 L" l0 O1 d# j; p. K1 }7 X, u ^的作用:在目标寄存器有pc时,会同时将spsr写入到cpsr中,一般用于从异常模式返回。
: j2 J7 K6 D4 ?" i: P& i4 \
1 i5 M" p2 S2 Q 例如 ldmfd sp!,{r0-r6,pc}^
% O6 m0 f" ~ m5 z- ?" {( R2 t
/ V/ ?3 e/ F' c: ?/ B) H# w五、伪指令4 R& Q# G b- n: \% E
y) o% I5 o1 v+ K7 @& Z3 ^
1、伪指令不是指令,伪指令和指令的根本区别是经过编译后会不会生成机器码。6 F0 x9 y6 S: O1 U" ]) Q: i
( I' {0 y% p. W8 Z
2、伪指令的意义在于指导编译过程。+ R% d1 }% r; o+ I# A( H
- W( Z8 _! s8 u1 }8 L+ j$ {4 {
3、伪指令是和具体的编译器相关的,我们使用gnu工具链,因此学习gnu环境下的汇编伪指令。4 e# W( f. X5 a$ ?0 J7 c
. c/ J5 p6 X4 D. M* f h' E- X4 h3 ^ 4、@用来做注释。和C语言中的//是相同的。% E+ d! W' t3 { n, T" x0 ?
4 b0 |$ g- {/ s( I& A# `& u 5、#做注释,一般放在行首,表示这一行都是注释而不是代码$ {+ Y2 |- @0 P* h
' q* ~0 H, r ] 6、:以冒号结尾的是标号( {( H4 X; i: J# p' x% X
" |; B. |2 T- C3 h8 T: g, v5 E; P1 s 6、.点号在gnu汇编中表示当前指令的地址2 R1 E z7 r( g' I& V
7 z' T6 Q4 O8 B9 x 7、#立即数,前面要加#或者$
0 v5 M6 X& u2 D" w# A- i$ c) P' ~/ P# `" N6 S: z& S& U
8、 重要的几个伪指令:
; g( `9 w; q# e$ x" _, A+ l M9 }. E; O; W$ a/ Y8 i
ldr 大范围的地址加载指令9 i x! _3 u* [; D) F' q! H+ I1 o, r Y+ j
0 R8 L/ z9 D+ G& q9 E% R, h
adr 小范围的地址加载指令/ l* Y7 ?8 G$ L9 _+ W
8 H$ p1 y2 l; M+ I) | adrl 中等范围的地址加载指令* L4 ]# n v: F- _" @
: R a* K" T& h2 v0 o
nop 空操作
; h: u( K% ^# t2 V# P# U$ X* H, C2 e/ C6 o1 X F$ K& p& t, W# G
9、adr和ldr
0 P, f: G. I% n+ Z' g- \. k" `- C3 j. ^
adr编译时会被1条sub或者add指令替代,而ldr编译时会被一条mov指令替代或者文字池处理。
0 ]/ ?2 q L! a X5 @4 ?; ]6 S, ~3 l- S0 i& L
adr总是以pc为基准来表示地址,因此指令本身和运行地址有关,可以用来检测当前运行地址在
5 i8 S& J M% y1 [7 ^5 d* H4 @, P2 T7 v
哪里。6 H J( t8 o5 ]* E
2 f1 l, s' p" v3 m: d6 C
ldr加载的地址和链接时给定的地址有关,由链接脚本决定。
* f8 f- G& q9 {; }* H: H: K3 _) }
- |2 \0 w) D7 u 欢迎各位指出不足之处
6 O w+ ^$ |9 n* {! v& \7 Y5 Q: \, s D
|
|