|
本帖最后由 rergr 于 2022-3-29 15:36 编辑 * [/ |1 q- Z/ R. x' I; ^( T& S
7 F: r+ h3 F. R. K0 d; q, q4 [
1、ADR(小范围的地址读取伪指令)7 L+ W" v2 J8 }
该指令将基于PC的地址值或基于寄存器的地址值读取到寄存器中。
, }& c4 D: e7 E, p4 A7 e& s$ Y+ e语法格式) |% l2 t$ N, `8 B" ^
ADR{cond} register, expr8 N( T9 i2 v6 L3 H. U
其中,cond为可选的指令执行的条件
4 D# g* O, U0 n9 W$ k% `register为目标寄存器# R& j* s# \, L' s4 O- {0 N( z
expr为基于PC或者基于寄存器的地址表达式,其取值范围如下:8 c: S# P: v8 L
当地址值不是字对齐时,其取值范围为-255~255.
* f% }1 P0 ~ Q6 u9 h1 u$ ^6 b3 d当地址值是字对齐时,其取值范围为-1020~1020 }0 q [7 F+ h0 M5 T
当地址值是16字节对齐时,其取值范围将更大7 m' [+ ]+ B6 v8 p9 ~8 p
在汇编编译器处理源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能。
6 T3 m- \; _# ^$ b2 ^6 p! V' { m% w因为ADR伪指令中的地址是基于PC或者基于寄存器的,所以ADR读取到的地址为位置无关的地址。当ADR伪指令中的地址是基于PC时,该地址与ADR伪指令必须在同一个代码段中。
* R0 o9 u; l% P1 r: k5 c8 z示例
0 p$ G% K2 c* F3 K t$ M# o- S @start MOV r0,#10 ;因为PC值为当前指令地址值加8字节
9 y. w; k- \% \: w$ H AADR r4, start ;本ADR伪指令将被编译器替换成SUB r4,pc,#0xc. V. H7 \* w2 R: R5 [0 k/ Q
2、 ADRL(中等范围的地址读取伪指令)
& R7 O5 v ]6 K4 q; V2 B该指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。
/ G$ D! [6 L) r语法格式 {5 g# m) E7 R0 ~$ S5 k( J- X
ADRL{cond} register,expr7 p' c" ^# Z- D( w+ h
示例
- w) @1 b, h9 K8 Q, H9 X) O+ N9 Z7 q$ kstart MOV r0,#10 ;因为PC值为当前指令地址值加8字节. \: G: }( P" R6 j& W
ADRL r4,start+60000 ;本ADRL伪指令将被编译器替换成下面两条指令
% w- ~8 g* o1 I. @; M3 C& K) PADD r4,pc,#0xe800. v8 S) i5 |- g8 l# v
ADD r4,r4,#0x254
+ h8 `0 k+ ^4 N* ~9 n7 Q z9 H; u+ q2 f3、LDR(大范围的地址读取伪指令)0 i+ [1 V2 H& n K4 v1 V
LDR伪指令将一个32位的常数或者一个地址值读取到寄存器中
1 c% M9 M {4 g语法格式( E6 l' j7 v+ Q6 y X
LDR{cond} register, =[expr|label-expr]
6 j2 S+ x- k2 ]9 N0 k9 o/ E其中,expr为32位的常量。编译器将根据expr的取值情况,如下处理LDR伪指令:
. s0 W' L) @1 [当expr表示的地址值没有超过MOV或MVN指令中地址的取值范围时,编译器用合适的MOV或MVN指令代替该LDR伪指令
! [- ~+ w, j: O7 K4 A% c( @当expr表示的地址值超过了MOV或者MVN指令中地址的取值范围时,编译器将该常数放在数据缓冲区中,同时用一条基于PC的LDR指令读取该常数。% A/ B M/ I* n/ t$ O. ~. |7 v
label-expr为基于PC的地址表达式或者是外部表达式。当label-expr为基于PC的地址表达式时,编译器将label-expr表示的数值放在数据缓冲区(literal pool)中,然后将该LDR伪指令处理成一条基于PC到该数据缓冲区单元的LDR指令,从而将该地址值读取到寄存器中。这时,要求该数据缓冲区单元到PC的距离小于4KB。当label-expr为外部表达式,或者非当前段的表达式时,汇编编译器将在目标文件中插入一个地址重定位伪操作,这样连接器将在连接时生成该地址。) ~5 d6 F9 V0 X3 Y" h$ d: T
LDR伪指令主要有以下两种用途:
/ k G5 W! M4 o. G+ R* }0 V当需要读取到寄存器中的数据超过了MOV及MVN指令可以操作的范围时,可以使用LDR伪指令将该数据读取到寄存器中。
" |7 M, M' p$ u/ H0 \& f" X2 O将一个基于PC的地址值或者外部的地址值读取到寄存器中。由于这种地址值是在连接时确定的,所以这种代码不是位置无关的。同时LDR伪指令的PC值到数据缓冲区中的目标数据所在的地址的偏移量要小于4KB。
9 W# c- r5 v9 F, o4 D, C# [示例
1 V8 o5 {, _5 i6 t! r! o- t将0xff0读取到R1中5 p5 d# U5 |5 Q7 ^/ g7 O/ ?
LDR R1,=0xFF0
- ?2 g+ |/ w/ U. W汇编后将得到:% j: e+ T$ a3 U4 i
MOV R1,0xFF0
, S7 Q4 m) C8 `# G* _0 K" k将0xfff读取到R1中
( _" I0 X2 b" |" x2 o/ gLDR R1,=0xFFF
4 N: Z5 }( d- [- F& o汇编后将得到:& P. C/ T9 z) }; M% e1 e; |
LDR R1,[PC,OFFSET_TO_LPOOL]- z5 ~3 I3 X6 @1 o0 R
…
5 Q5 i: X) G3 _& M7 l8 `2 o' n( E# hLPOOL DCD 0xFFF# G& x$ g+ y( q5 u8 X
将外部地址ADDR1读取到R1中( H$ H, h3 W, b3 x2 R5 u0 n0 `
LDR R1,=ADDR17 o8 i8 |( X! E
汇编后将得到:/ h6 q& E; V% m
LDR R1,[PC,OFFSET_TO_LPOOL]
[0 ~4 j# p3 @( L0 ~. p…, m5 b8 \( L+ }
LPOOL DCD ADDR1
1 O' w+ `1 t, B( G& _9 C4、NOP空操作伪指令
E5 g3 a$ Z$ d在汇编时将被替换成ARM中的空操作,如MOV R0,R0
. Y( P. m& k; a5 {8 ENOP伪指令不影响CPSR中的条件标志位 |
|