|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
B T8 ]& r% m2 i* M2 C/ ^
一、指令和伪指令8 t) a& L# b: z$ j0 [! ?/ T- V+ H! o
6 H4 z/ r2 p0 `* C$ I+ n 汇编指令是CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以) u2 ~* D( U: Y$ }3 b
, d. z! b4 Z9 Y, R- Y6 u# b. b& \) z
由CPU读取执行。
% F& ^9 G/ f! N9 d1 r6 ^7 \) D7 H7 G- \4 b; D) e$ [0 n+ B, }3 w
汇编伪指令本质上不是指令(只是和指令一起写在代码中),它是编译器环境提供& m( J/ [! ~7 c4 R% q& j
1 @' `1 {! t. n5 m
的,目的是用来指导编译过程,经过编译后伪指令不会生成机器码。
: \0 i" P4 L6 L% [: z! {9 a7 a: [: R. T! \- Z) g. S
二、两种不同风格的ARM指令. ?' w u+ {7 \. U( a; P
) p7 J1 o! N. k
1、ARM官方的ARM汇编风格:指令一般用的小、windows中IDE开发环境如:LDR' M5 |' J5 e/ g2 u( M; m
2 o% F3 e J$ l R0,[R1]0 R, V5 I' J3 k$ L- F( j6 i
9 M& F+ z o3 ?9 d* [4 t* g 2、GNU风格的ARM汇编:指令一般用小写字母、linux中常用。如:ldr r0,[r1]
/ p& a* w2 }; {, U2 e9 t. v4 e6 ?6 I1 R0 ^# v$ A6 ?/ C: W9 S
三、ARM汇编的特点* e4 Z- C0 x4 A# Y8 K. ^/ y
; W6 F" J+ A3 U6 q A4 z( z2 N5 O0 F
1、LDR/STR架构$ U" v" P( v: z# K
6 h0 W$ I. j% f' a (1)、ARM采用RISC架构,CPU本身不能直接读取内存,需要将内存中的值加载6 ` }' w4 A4 R7 K
7 t. I! h4 U9 C/ X5 C; P 到通用寄存器中才能被CPU处理。: X7 u7 ]/ M% I2 D! R
+ G' u$ L+ ]/ K( ^$ M (2)、ldr指令将内存内容加载入通用寄存器。
3 S4 t2 }+ C) L
! k2 ]4 C j6 l! ^7 D) j (3)、str指令将寄存器中的值加载到内存空间中。8 u8 H8 e, A% N2 Z5 ?
! S8 N; u9 v5 G8 {( J
(4)、ldr/str组合用来实现ARM CPU和内存数据交换。
/ x% ]& D$ e) N' a# Y% I
* A* Y) c* J- _% y0 m1 H 2、ARM汇编特点:多级流水线
8 X, ~. d' b' U0 n
' y; U. T. e; P -
, u6 n" w; z2 f: a
: R5 j7 M/ Q6 H$ m( ]7 F, D' ]
3、8中寻址方式- V4 G' W$ ]3 v! l
; s U( u' v/ Y! T% W
寄存器寻址 mov r1,r2' S8 O& N9 _! ~% A* _$ z4 s) y
6 i' o7 g3 {, y0 w7 Z! C Q: y8 h 立即寻址 mov r0,#0xFF00
4 r( Q! L* x3 ^+ G' w7 n7 w% }3 ^6 e' ^
寄存器移位寻址 mov r0,r1,lsl#3$ r. f2 u6 ?7 [+ C; A7 P2 L5 x- d7 h
. a, E4 [/ _ h' p- a! i' U$ P 寄存器间接寻址 ldr r1,[r2]" C6 v) s% W0 U$ ?" U2 C" W& G
% n5 f: O+ I5 s- { 基址变址寻址 ldr r1,[r2,#4]% F) a4 K' `) @% Z
L5 n! ~% t5 q
多寄存器寻址 ldmia r1!,{r2-r7,r12}
3 N- g5 B& A3 k6 |0 p3 L, T: x% S5 c* [6 ^: A O: I
堆栈寻址 stmfd sp!,{r2-r7,lr}
2 O/ ^4 y; Y/ @- \% i% |
! o) f: @2 H T' Z9 n 相对寻址 beq flag
4 H/ K" U* ^; U! C5 Z, L! ]9 j
4 U O# ~3 Q# B flag:. l3 n# f4 s: U% U; [# j
/ a3 X5 E- m0 f6 |6 V四、ARM常用的汇编指令:# P2 f# K6 a4 x
2 x; v8 d0 o) l- F+ h8 q" y5 B 数据传输指令:mov mvn7 M; i* u* I3 z! q6 Z. t4 b% f5 x
* U4 ~- @' f& p- ~" O
算术指令: add sub rsb adc sbc rsc$ _7 k# ?! g. C3 ~+ V( D) |4 M
2 u$ i4 c! j! M3 T. W+ W
逻辑指令: and orr eor bic
8 q6 g/ C7 H4 B; D6 j0 `" Y9 a6 }
& K- E( z2 U7 L" _ 比较指令: cmp cmn tst teq+ d+ ^( [9 x) S" r+ a4 Q8 a0 @
( v8 W1 E8 `8 K6 b
乘法指令: mvl mla umull umlal smull smlal# ~7 r) L" T3 J# V, \
_, }: ~3 @+ H t, D1 N* i/ j 前导零计数器 :clz
! Q% X/ W1 b* {3 X
( O; P6 j1 ?5 i8 s8 o' }0 G CPSR寄存器比较特殊,需要专门的指令访问:这就是mrs和msr
* F$ }% t& ~$ i) O# L$ C3 ?3 B4 z# O. g& x% S* [- [4 q6 E) f
mrs用来读取CPSR的值,msr用来写CPSR
: i' A, \& f- `6 p7 o$ N$ `$ _0 t2 D0 V: U& _( x2 n3 T: }
协处理器cp15操作指令
6 m) M) K8 A0 D( v" {# Y
( M( ^5 S! J! k# }) m mrc用来读取cp15中的寄存器,mcr用来写入cp15中的寄存器
) q, M ` w* X* ?8 ~7 O# x% k' b( V' {; u+ p
^的作用:在目标寄存器有pc时,会同时将spsr写入到cpsr中,一般用于从异常模式返回。
* c, `1 ^8 I) y' q
9 ?+ w$ S! a. E+ B 例如 ldmfd sp!,{r0-r6,pc}^
% }4 l/ A! _( ?5 r# Y$ T$ f7 y( M/ \7 }7 ^( ^! G" t7 U- R
五、伪指令
2 i& \' r B4 h& C* l( q9 f0 ?9 |. |2 }* {, h) N3 Q
1、伪指令不是指令,伪指令和指令的根本区别是经过编译后会不会生成机器码。5 Y* X) V6 f: h# W6 `, o* o
) {3 e; D1 F7 k3 X 2、伪指令的意义在于指导编译过程。" _$ K# H3 n# v
V* k' z7 a, O 3、伪指令是和具体的编译器相关的,我们使用gnu工具链,因此学习gnu环境下的汇编伪指令。' I2 [% ~2 X* `
8 t3 K) a8 B7 B9 Q: h. l4 [ 4、@用来做注释。和C语言中的//是相同的。- f0 P2 X8 ]7 R8 q+ w
# r0 }4 c- R4 A) _ 5、#做注释,一般放在行首,表示这一行都是注释而不是代码# u: ^* n- m( S0 O2 r
) H B8 @/ o2 y( w 6、:以冒号结尾的是标号
& N( {" ^4 l# p4 p& X3 G2 y# e% p* a9 R
6、.点号在gnu汇编中表示当前指令的地址, e0 `8 B6 T7 i @# H$ ^4 } G
/ P! \. B4 k% \0 ^( A) C5 [" f, R 7、#立即数,前面要加#或者$
l1 y h9 [# k7 K" g9 L N. K2 o' l1 a6 B7 E4 D1 _
8、 重要的几个伪指令:
6 o; u% ^4 g; h$ G% E D- W
7 D) v# A; A/ N" V0 ^4 k, Y- K/ B ldr 大范围的地址加载指令
- h S) X& z& \7 s" V+ Z/ F: e
; a' E7 ]8 J2 n adr 小范围的地址加载指令% G( h" ?1 D( n9 O
. P* r; P' D/ m& a7 }) `3 V
adrl 中等范围的地址加载指令
2 s0 ~ D p. v E2 u5 o* v* x& _7 k
nop 空操作/ Q, v) r5 Y. R: O7 U" d9 o6 |
+ B. o& r' W1 ^% y 9、adr和ldr " A! O% x4 y. d+ R
7 R1 R1 b: u0 ]" ]- F adr编译时会被1条sub或者add指令替代,而ldr编译时会被一条mov指令替代或者文字池处理。
, C5 d( l& _* G: w; U
* h0 W; @6 Q z$ w$ P adr总是以pc为基准来表示地址,因此指令本身和运行地址有关,可以用来检测当前运行地址在
/ Z3 r1 U5 y7 ^' `6 U
6 o9 q. a3 W, l* S 哪里。; B6 x9 Y6 W, p$ Y2 Q, p
/ J7 M( m$ u" W# N* P8 ~9 ` ldr加载的地址和链接时给定的地址有关,由链接脚本决定。
; ?; c2 K7 v% d- h! R$ `& r! [( t
欢迎各位指出不足之处
. J: M' h; e7 {6 i4 I. `8 \% b# d# N% e. y0 I8 F2 t
|
|