|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
% ]2 G+ B" N8 X6 [
一、指令和伪指令
5 `3 d, L3 ~' T# ~4 I5 b( z# t- b D" P9 R- p+ d
汇编指令是CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以6 B8 |) j# ^% |) c6 r5 q2 o8 w
$ S8 s2 R' B5 J* c: F 由CPU读取执行。
; Q8 Q5 U+ l: {2 y* D* z( V) i7 g% A/ ^1 y8 S
汇编伪指令本质上不是指令(只是和指令一起写在代码中),它是编译器环境提供6 |: P2 J; k9 J) j, ]
& P# b# h" J( ?1 N; p* a. J 的,目的是用来指导编译过程,经过编译后伪指令不会生成机器码。4 Z7 Q; ]2 U9 v/ {+ ]) U
# L( @0 S8 a( ^& w/ @7 T二、两种不同风格的ARM指令
! t+ Q/ B+ `8 v# ^' h
! s" b, L: d. z' W 1、ARM官方的ARM汇编风格:指令一般用的小、windows中IDE开发环境如:LDR
6 y( G! n5 R3 x* E0 Q1 t$ |2 S; e
# l7 X1 t" V& B R0,[R1]0 d+ B$ X+ s& o2 J# [$ |5 X( S
% Z5 \2 {" i5 g0 U6 p
2、GNU风格的ARM汇编:指令一般用小写字母、linux中常用。如:ldr r0,[r1]: B! p* M9 c) Z4 l# b7 Z' N
% i* _0 q, J# }0 ` h三、ARM汇编的特点
# q# b8 r& `/ Y( o) W
! _1 J* Z# ?2 h0 r 1、LDR/STR架构
1 X: u% u+ K! X1 A" O" J! T7 E1 `) o& F. n) Y- ~8 Y6 p
(1)、ARM采用RISC架构,CPU本身不能直接读取内存,需要将内存中的值加载
$ R/ j+ f) t& d& C* L: [1 }& ~% B8 R
. r& t; Y( U% X& S: O1 ] R/ x' @ 到通用寄存器中才能被CPU处理。
8 V6 {2 D ~0 ^- Q# X
. \0 q* W9 O2 E) v (2)、ldr指令将内存内容加载入通用寄存器。# e& W6 G6 c' x- U7 c1 a! p: k1 w
6 \/ v( J' {/ w& P" U
(3)、str指令将寄存器中的值加载到内存空间中。
) r* X; S! b; R `! n2 C; K( W+ }' P+ a6 C
(4)、ldr/str组合用来实现ARM CPU和内存数据交换。
9 c- q' U0 K4 \- l0 B& b; K
1 _8 W/ B+ [1 o' R" v 2、ARM汇编特点:多级流水线
, i8 Z8 m8 l+ y* D- ^2 {
) Y6 ~# E( _1 w0 j -
; [, T6 A7 s0 Z* ~" Y5 q8 S: x; K3 l& g, ~
3、8中寻址方式
2 \1 x4 c* `" G5 Z' \
# R% w. S! }+ j3 d 寄存器寻址 mov r1,r2& i& _4 A/ f, Q; F8 m
$ I3 G$ i/ q* W1 n9 w6 _+ h* r
立即寻址 mov r0,#0xFF00 7 q. v, |/ F% E6 }( T) r k A1 d
4 l& z4 z2 }6 l3 z/ l) k; r 寄存器移位寻址 mov r0,r1,lsl#39 t. d, P' g% ?5 q( }* J4 z
5 @! X6 {0 A: C* ]: _ 寄存器间接寻址 ldr r1,[r2]
( A6 o3 u" f3 J; Q6 Y- W8 `9 B
9 F9 Q& ?7 e9 A 基址变址寻址 ldr r1,[r2,#4]0 k/ M0 J, w' K5 x& C! w
- W8 g |5 k0 Z7 g$ ?$ a+ _' c& y
多寄存器寻址 ldmia r1!,{r2-r7,r12}
: `7 n2 u r8 W+ K$ Y( \' h. m! L( ]1 E5 B- n
堆栈寻址 stmfd sp!,{r2-r7,lr}
3 W, Z: J+ u* c( P3 a( @: p
# Z$ i0 r4 u) h' Y$ Q: }2 t+ ]: F 相对寻址 beq flag6 c7 v- d% b# C5 u" g9 c g! M
/ y# l0 O/ n* a0 V
flag:
+ J' \1 }& u8 s8 B% T- M4 g* W: V6 ]. l) {+ [- O
四、ARM常用的汇编指令:/ _" U/ S+ b1 f1 R
. ?1 M' R" A1 \! O9 E# f 数据传输指令:mov mvn% e" _4 G: b" o# Z) m$ ]8 f
+ E0 O s& X% p! u: E1 L4 O
算术指令: add sub rsb adc sbc rsc! p7 a- {/ D3 ?+ ~
. |0 ~7 J" o% ]- F. g. d5 V
逻辑指令: and orr eor bic. K4 M6 m- T; i$ y
8 Y, y8 f& B; X* b) e/ s3 x/ m 比较指令: cmp cmn tst teq8 r% w8 {/ g+ V+ Y! z
& _3 V6 |# P4 c# D7 w: r4 V 乘法指令: mvl mla umull umlal smull smlal
- x- F* t8 a" j7 @ B0 l$ p+ }3 y5 U" G. I' F* U/ Q
前导零计数器 :clz
2 A) |7 h& ?) r5 x0 O4 `+ n- L [$ O" l" C, c% F8 E
CPSR寄存器比较特殊,需要专门的指令访问:这就是mrs和msr
# E0 a L% \; R) ]# i8 K, {
, \( u# x7 V! k5 x2 n5 a# `% i mrs用来读取CPSR的值,msr用来写CPSR: x3 Z4 G# ~8 ^8 S
, _ N5 ^6 q5 H- a* Q 协处理器cp15操作指令& _$ d8 Q* G& t# `8 G
- b; l+ \" }! F* a" n1 \. T mrc用来读取cp15中的寄存器,mcr用来写入cp15中的寄存器
0 J8 ^* O7 W# X& C4 n
/ G: _; D* z7 c% F ^的作用:在目标寄存器有pc时,会同时将spsr写入到cpsr中,一般用于从异常模式返回。
4 { O6 w" N: N$ Z8 r5 x0 ^) \8 p! V
例如 ldmfd sp!,{r0-r6,pc}^$ c. T" Z- T- Z) |- w V, W; P
5 r6 w$ `9 n" @! |2 l2 b6 I, f
五、伪指令! k$ Q+ ~2 t. e
# ^4 E* |6 f4 M' e- I- O 1、伪指令不是指令,伪指令和指令的根本区别是经过编译后会不会生成机器码。$ x* |* f1 g! |/ Z
7 L' l8 z1 p( a9 v- @ 2、伪指令的意义在于指导编译过程。
0 O4 G3 I. G& M- F% Q5 B ?
& i( F6 O- P) o$ P p 3、伪指令是和具体的编译器相关的,我们使用gnu工具链,因此学习gnu环境下的汇编伪指令。# K2 K& b) ]/ }
: h$ N0 Y/ L7 R R% { 4、@用来做注释。和C语言中的//是相同的。, H8 B) g1 [3 u3 H- A
: q8 H' i8 ~) W7 | 5、#做注释,一般放在行首,表示这一行都是注释而不是代码
4 f; b" R! U% M6 r9 D7 F+ M" J* h; E- L8 W& _& y& J
6、:以冒号结尾的是标号
3 o1 h# a, L4 B" P0 s9 @: B5 M/ k
6、.点号在gnu汇编中表示当前指令的地址8 ]$ g9 O* G" ]
0 e3 X8 _' C7 G" [ 7、#立即数,前面要加#或者$
6 H2 F1 y& _" a: X" H+ Y+ \9 z# z9 _8 W0 J
8、 重要的几个伪指令:) b5 u7 f( a: |) }" O5 {( z* _
" d4 O; n: d, P
ldr 大范围的地址加载指令# j" S- x% \% @" f: ^
* c0 P, G, J" w3 F! A" L: _2 X
adr 小范围的地址加载指令
/ w# @1 D, c1 J! w9 R& L/ W
# [: ~9 y2 f1 E' B6 o adrl 中等范围的地址加载指令
3 H( b& p) |0 a8 [) o" n( l$ k$ I$ L) y$ f! n0 B2 Q6 v
nop 空操作& Z! G1 m2 w% j8 ?3 Z9 `
& h, m: u; _: w" g c. y 9、adr和ldr
4 g/ H# V- g, h7 I5 D M7 x: P) A" y# M
adr编译时会被1条sub或者add指令替代,而ldr编译时会被一条mov指令替代或者文字池处理。
+ [6 O& u" r# Q/ p' }: y# q* ]
+ } ~, e& [' u' s- D# O. L adr总是以pc为基准来表示地址,因此指令本身和运行地址有关,可以用来检测当前运行地址在
& X9 ?; G( Z" N$ f/ G5 o1 B
8 i! l$ \% j1 s6 k 哪里。4 r0 _) X5 m# j8 E
; _* [ ~+ }, |5 E, I- s ldr加载的地址和链接时给定的地址有关,由链接脚本决定。1 W! n* } i: m" Q
8 R+ A4 F2 z/ H. M$ a% q, Y
欢迎各位指出不足之处
( v$ v S* C& P! y8 I% H& {4 d1 O. M. u; f0 ^/ i
|
|