|
本帖最后由 rergr 于 2022-3-29 15:36 编辑
9 s8 h3 U" i4 S: v, C3 |6 D3 s. q9 o! Y+ W* y* T
1、ADR(小范围的地址读取伪指令)
" m3 M8 I4 g% Y" z m x0 h该指令将基于PC的地址值或基于寄存器的地址值读取到寄存器中。
; [, c+ W% P. m3 h! c' g语法格式+ O4 s9 [5 o# ^0 L0 `( `
ADR{cond} register, expr- b/ m# v, K) W2 j9 w$ }
其中,cond为可选的指令执行的条件" ? L5 V# p N; X3 A, w9 h& z* ]
register为目标寄存器
7 ]* Y3 D! T9 T* {% Gexpr为基于PC或者基于寄存器的地址表达式,其取值范围如下:4 r, k0 _: m' m8 a0 |
当地址值不是字对齐时,其取值范围为-255~255.
2 r/ h; U: C9 d* W( F3 m# v当地址值是字对齐时,其取值范围为-1020~1020% ^; z* ]( j# O* V
当地址值是16字节对齐时,其取值范围将更大; T+ P+ D6 Z% l0 `8 [! J; z
在汇编编译器处理源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能。9 D, f$ F9 F S2 P
因为ADR伪指令中的地址是基于PC或者基于寄存器的,所以ADR读取到的地址为位置无关的地址。当ADR伪指令中的地址是基于PC时,该地址与ADR伪指令必须在同一个代码段中。
1 K8 ~2 w6 V, C. n' y示例4 {0 |7 T/ ]6 Z
start MOV r0,#10 ;因为PC值为当前指令地址值加8字节
4 B; i' R: b* ?% \( }; a5 Z' z/ j; }7 NADR r4, start ;本ADR伪指令将被编译器替换成SUB r4,pc,#0xc7 W3 z S' f+ V
2、 ADRL(中等范围的地址读取伪指令)
* {6 l) U& o8 x# L9 [该指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。
. b7 _0 t4 t$ r6 w# P语法格式6 ~& N, Z3 G5 b9 l) }. T1 e2 Z
ADRL{cond} register,expr* b3 K8 S& ^: s' T5 ^# ?* q% d
示例: q# S E% J' E! f0 ?5 J+ E
start MOV r0,#10 ;因为PC值为当前指令地址值加8字节
* v) t1 w9 V* n. w7 g8 e/ IADRL r4,start+60000 ;本ADRL伪指令将被编译器替换成下面两条指令8 I V' \( i1 q7 q4 x3 O, a3 Y3 [
ADD r4,pc,#0xe800
+ q7 p- a4 k yADD r4,r4,#0x254
. }1 @* H' x3 I6 P7 B5 P3 g/ K$ u6 _% }3、LDR(大范围的地址读取伪指令)
! n8 A9 g0 n, eLDR伪指令将一个32位的常数或者一个地址值读取到寄存器中, B1 w' i) ^3 r5 W0 L9 H, X
语法格式8 ^/ s/ R& A6 L* A
LDR{cond} register, =[expr|label-expr]# a4 f& w% v) H p s" j! o0 V
其中,expr为32位的常量。编译器将根据expr的取值情况,如下处理LDR伪指令:
9 C7 C! D4 s! v当expr表示的地址值没有超过MOV或MVN指令中地址的取值范围时,编译器用合适的MOV或MVN指令代替该LDR伪指令
; N- C5 J- g$ X/ O* N8 H" C当expr表示的地址值超过了MOV或者MVN指令中地址的取值范围时,编译器将该常数放在数据缓冲区中,同时用一条基于PC的LDR指令读取该常数。
# t+ i; g; r1 o3 R; P3 @* ~label-expr为基于PC的地址表达式或者是外部表达式。当label-expr为基于PC的地址表达式时,编译器将label-expr表示的数值放在数据缓冲区(literal pool)中,然后将该LDR伪指令处理成一条基于PC到该数据缓冲区单元的LDR指令,从而将该地址值读取到寄存器中。这时,要求该数据缓冲区单元到PC的距离小于4KB。当label-expr为外部表达式,或者非当前段的表达式时,汇编编译器将在目标文件中插入一个地址重定位伪操作,这样连接器将在连接时生成该地址。
6 T; \% Z* B4 XLDR伪指令主要有以下两种用途:0 E& Y2 M; I. o0 c: m& I
当需要读取到寄存器中的数据超过了MOV及MVN指令可以操作的范围时,可以使用LDR伪指令将该数据读取到寄存器中。
1 \4 b5 W, P3 w0 E将一个基于PC的地址值或者外部的地址值读取到寄存器中。由于这种地址值是在连接时确定的,所以这种代码不是位置无关的。同时LDR伪指令的PC值到数据缓冲区中的目标数据所在的地址的偏移量要小于4KB。' P4 S" N2 F0 K; D" p' L
示例7 q [& v* L: o/ Q' _ a
将0xff0读取到R1中9 k0 P) o* }1 S3 _1 M7 X, q7 Z- `
LDR R1,=0xFF0
! Z4 i1 C0 a+ u2 F/ }& G汇编后将得到:# B: K, p5 o: k5 x% ~3 f7 R" n; t
MOV R1,0xFF0
: ~$ I1 {; M% Y# H4 m% t9 D将0xfff读取到R1中
5 F+ |3 N7 T1 x% P* [3 ^! HLDR R1,=0xFFF8 u- a/ k$ X. v" L% k
汇编后将得到:! @6 ^: G, J. \: Z8 j
LDR R1,[PC,OFFSET_TO_LPOOL]8 Y6 W7 G# y. _& y) s; p" f
…
' h: _( U9 t; `) c Y7 ?LPOOL DCD 0xFFF6 x g4 C' K( e2 ?' u# f3 c
将外部地址ADDR1读取到R1中* Q) Z, S: {$ Z3 D) d N
LDR R1,=ADDR1' K! j& N- ?6 x* i* Q o* [ K D- M
汇编后将得到:, ?* I& t/ I) `$ {7 n7 a
LDR R1,[PC,OFFSET_TO_LPOOL]: f: H* g3 h3 r" y5 f
…( ?$ |( S6 h4 s- u7 `
LPOOL DCD ADDR1+ x4 Z; z1 S7 L5 _/ M) L+ v
4、NOP空操作伪指令) V8 a2 N, `+ c" n: X( p9 U6 A3 O
在汇编时将被替换成ARM中的空操作,如MOV R0,R0 y, C+ S" i) v! S4 ^; H: Z
NOP伪指令不影响CPSR中的条件标志位 |
|