EDA365电子论坛网

标题: ARM之ARM汇编 [打印本页]

作者: piday123    时间: 2021-4-28 11:00
标题: ARM之ARM汇编
+ ^4 I) P0 {: n* \
一、指令和伪指令
! R+ r6 n7 g4 g! _$ D8 [
, b& o( \1 o; h5 B3 S    汇编指令是CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以; I( ?& A& N' ~( F; r' j; _% j- y
, P( ?2 t  ?* x% F* a2 W' X& J
    由CPU读取执行。. l& \; }# ~4 n9 V! ]4 b$ }* n

; R" C' `( X: Q- B    汇编伪指令本质上不是指令(只是和指令一起写在代码中),它是编译器环境提供, w* k3 @' a& f) B0 J; r. J* [

) z: o! K& G1 m* b1 S' A7 h! B) z    的,目的是用来指导编译过程,经过编译后伪指令不会生成机器码。9 K6 t- C: _( q/ A: y! M; v/ a: J

' L9 ]% {6 g: Y8 v3 W二、两种不同风格的ARM指令! J+ [1 t( T! G+ m3 F

+ p! u0 [: f* J9 ~+ u4 M& e$ l    1、ARM官方的ARM汇编风格:指令一般用的小、windows中IDE开发环境如:LDR
  R; `& Z! E# J. p$ l: `0 r3 s0 z4 F) A  Q0 R
        R0,[R1]4 R% V/ ?9 j/ R  R6 [
5 b) r0 ?  ]# s/ \. w* b
    2、GNU风格的ARM汇编:指令一般用小写字母、linux中常用。如:ldr r0,[r1]
9 b7 r( j1 `, F7 F$ {9 Z: U. M, U1 w) S/ r) M
三、ARM汇编的特点
  Z  l7 r1 s; v
' y1 D/ [" {3 B4 ?# x" x7 F( Z    1、LDR/STR架构
2 z$ P: e: y) M0 e& `" G+ _; g& v6 U
7 }" b! P$ l; L, L- a' n        (1)、ARM采用RISC架构,CPU本身不能直接读取内存,需要将内存中的值加载" }/ Q/ c8 _  ^+ ~2 \' e) T. a
, n  G% t+ \# x) ~
            到通用寄存器中才能被CPU处理。& |7 Y7 Q/ F' p  |

) D4 L; B' j4 x- w        (2)、ldr指令将内存内容加载入通用寄存器。: A, N6 u& V/ R1 ^6 s. E
3 O8 e2 ]$ _9 ~. y& r; j2 V
        (3)、str指令将寄存器中的值加载到内存空间中。
; c; A/ g# n0 w+ q! R: l$ a* R: R
        (4)、ldr/str组合用来实现ARM CPU和内存数据交换。1 M0 b- \- A# N/ [' y; v
. [7 ~& j+ ]4 ^: P
    2、ARM汇编特点:多级流水线3 z5 u" G, y! J
9 U" z- G; I- B
        - : e3 o! |' }' A* a& E( F6 X
+ J& f- _! q" J2 [) T9 w
    3、8中寻址方式
2 Y$ L: a( s( Y9 {( }' R, M0 X, B* T0 o9 }, q2 o  u; L
        寄存器寻址               mov r1,r2
- t- X( M3 d) B" _8 j) @9 g3 E; h6 S2 p5 R& F9 j
        立即寻址                  mov r0,#0xFF00 * a* u! H/ V# b) E! H
! s; ^5 E" \* G, X( M
        寄存器移位寻址        mov r0,r1,lsl#3
" S6 d: n' {0 b! R! \" @3 J3 B" w9 W; ^5 m1 a
        寄存器间接寻址        ldr r1,[r2]1 d5 q+ x2 _( A! |6 A

- T  ^0 E+ F& ^+ k  L* U5 [0 o        基址变址寻址           ldr r1,[r2,#4]1 m* [( }* @  m7 c

% k4 \' f5 u, ~  [  O* ~4 c( X        多寄存器寻址          ldmia r1!,{r2-r7,r12}
) A) W( ^. F8 f4 j1 Z3 f
, G+ Z6 `) E, j5 Z8 E' @7 Q% g# b+ \        堆栈寻址                 stmfd sp!,{r2-r7,lr}
" o2 j% G$ X" k# I2 L% O0 q) }# s8 |
        相对寻址                         beq flag$ Y  y$ ?& e9 u% G7 W

1 @% R8 q2 e* O  s9 r3 {, {                                        flag:
$ Z# _9 c# h8 u! T! e" N
, e* R& {& ~: ?: @* {四、ARM常用的汇编指令:0 f, X% w& i! ]6 c$ P/ w9 f

. e% W: a$ m, w6 {        数据传输指令:mov mvn) y: q# o) M/ y0 d% N

* J4 ^8 A1 J% j# t- f0 w+ K        算术指令:    add sub rsb adc sbc rsc
) I: G; P3 u. {
* u) ]3 G: S# W/ Q        逻辑指令:    and orr eor bic5 J4 T7 D) u% y* v

: h7 ^6 Z  y2 I7 b  Z) Q$ w        比较指令:    cmp cmn tst teq) A* M- Y9 z8 G& \" n2 F# g+ B
4 s% h+ i! M! D, J! F- X
        乘法指令:    mvl mla umull umlal smull smlal$ _/ h2 X6 d( i  K  @4 Y* _  R  ~
' i+ w& M: a8 e0 F# R
        前导零计数器 :clz  q( m: H7 w% X+ {8 _* o) g) j: t$ k

, b  ^+ I9 t- g) K% @        CPSR寄存器比较特殊,需要专门的指令访问:这就是mrs和msr9 x" ~- `( Y% G/ Y  N/ j3 N
* X7 v  `6 J# ^/ v& U
            mrs用来读取CPSR的值,msr用来写CPSR
0 o$ z, @' z( y# O4 V! ]1 j
; T/ O) C6 `& _, c6 o# n1 _! C        协处理器cp15操作指令) W% V' T. X- @* g

* S% g9 ?: g+ S" o1 n            mrc用来读取cp15中的寄存器,mcr用来写入cp15中的寄存器# k8 M8 O3 s, p) U: X+ r

& j3 b  r1 O6 Y  L9 Q       ^的作用:在目标寄存器有pc时,会同时将spsr写入到cpsr中,一般用于从异常模式返回。
" a1 _2 B, o& u4 ]. r6 q, v4 P$ J2 X! j
        例如 ldmfd sp!,{r0-r6,pc}^
9 ?* T4 M8 a8 Q3 u2 L# r# C; r
( G9 W' u. K( W* ~五、伪指令) F) t  h% {' ^) Z, j% j5 K
! {2 G  v9 z+ m2 w' \9 H
    1、伪指令不是指令,伪指令和指令的根本区别是经过编译后会不会生成机器码。
8 N1 ]. g  O4 Y5 Z  M; F9 J: y4 ~* |' U3 w$ ]9 V
    2、伪指令的意义在于指导编译过程。# u3 U6 f# @+ |+ ^$ z1 G
! u! y3 u* B% G- x% ?% l1 E; f
    3、伪指令是和具体的编译器相关的,我们使用gnu工具链,因此学习gnu环境下的汇编伪指令。
7 F6 F6 e7 g# I) h! h5 ~0 x- ~
( ?+ _+ D* w9 x    4、@用来做注释。和C语言中的//是相同的。% @0 W' x* `& w$ L, O6 `; t2 g& c

; q5 j' S1 q( c/ j    5、#做注释,一般放在行首,表示这一行都是注释而不是代码
- L  k* h- u7 h4 d3 \5 g+ b. k) _
4 L- ~! U8 ^6 x    6、:以冒号结尾的是标号: r) r5 w. l# K# q6 I3 T- K/ U1 I

0 O, }, `" S) ^; ^5 S* e    6、.点号在gnu汇编中表示当前指令的地址
0 @+ P+ S# s0 q. F5 ^4 x* O5 E+ M
" n$ s) ~- U1 R8 l* I5 M    7、#立即数,前面要加#或者$3 X8 R. e  ?. u$ J; S; }

. [2 B( j& i7 S' T    8、 重要的几个伪指令:
, i3 N* ^6 r; s% o8 M, z- X5 N$ M4 m5 W5 k1 Z! k) C/ b( ~, z/ r
        ldr    大范围的地址加载指令
: X9 J8 E: \% B1 t5 M/ N+ `
  o& E6 V; N/ ^1 O- l7 I* F' Y$ w        adr 小范围的地址加载指令
3 Z! F) f$ R$ a" l# I: t8 i+ |7 X( @0 Y5 J7 |; P8 T" x
        adrl 中等范围的地址加载指令
0 J' G; @+ @% _! V2 S2 o' ?: [- K" R+ @' ]0 S
        nop 空操作: E  u, C) B" j2 Y6 [9 E+ k

# m0 Y8 A5 r- C/ |* b    9、adr和ldr # @8 n# ^! B1 N. P- R

1 q+ j1 ]( {% P! e  A0 U: u        adr编译时会被1条sub或者add指令替代,而ldr编译时会被一条mov指令替代或者文字池处理。
8 L( E" i: W- R3 b# h2 }) H
# f# b) y8 L( n  j* Z2 L; N4 Q$ x) r        adr总是以pc为基准来表示地址,因此指令本身和运行地址有关,可以用来检测当前运行地址在: T& i8 u9 E& [% N
7 {7 G$ U7 Q. L: M
        哪里。* g4 B5 D+ V; r- H" z- b6 _/ b
( V3 S( t; g. ^$ @+ x4 J, q% H
        ldr加载的地址和链接时给定的地址有关,由链接脚本决定。( f% d5 [- r! m5 n% ^
6 @! J) q5 N" p9 l- S( j/ z( X
    欢迎各位指出不足之处
2 b# f, D! O, e& _
1 w+ G" i: E) p
作者: xiaogegepcb    时间: 2021-4-28 13:11
ARM汇编




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2