|
|
本帖最后由 rergr 于 2022-3-29 15:36 编辑
6 l) N1 b8 o& H& i" C& ]$ q# K+ o4 b: ]# y
1、ADR(小范围的地址读取伪指令)/ @' E/ h9 r9 h, h# P; D: T. ^! [
该指令将基于PC的地址值或基于寄存器的地址值读取到寄存器中。
6 a" b5 h$ ?+ ]# T+ _ E0 G, r1 ~8 m语法格式$ F% G; i0 z# e1 E
ADR{cond} register, expr6 n* F- N5 C8 Q- l. y( ~
其中,cond为可选的指令执行的条件+ n+ r# q% q- W9 v. T
register为目标寄存器
; F& I$ D* Y: C) f. f# sexpr为基于PC或者基于寄存器的地址表达式,其取值范围如下:
0 M6 {* ^+ a3 ~) G" Y当地址值不是字对齐时,其取值范围为-255~255.
- h4 f# l1 b. Y8 y当地址值是字对齐时,其取值范围为-1020~1020# z i% j* V4 V2 F+ z7 E' G+ }
当地址值是16字节对齐时,其取值范围将更大
6 x; _8 ` z) t2 W7 v: W8 v( ~7 @在汇编编译器处理源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能。8 E: G; T" ^( S
因为ADR伪指令中的地址是基于PC或者基于寄存器的,所以ADR读取到的地址为位置无关的地址。当ADR伪指令中的地址是基于PC时,该地址与ADR伪指令必须在同一个代码段中。
. Q- n* ^2 W4 e0 V: s8 ^示例
/ O$ R. I/ ^" z5 v3 d; k3 E `* Z$ istart MOV r0,#10 ;因为PC值为当前指令地址值加8字节6 \' z# s: ~7 _3 K' M
ADR r4, start ;本ADR伪指令将被编译器替换成SUB r4,pc,#0xc
( B5 t0 b" J3 [: o2、 ADRL(中等范围的地址读取伪指令)
; A8 g: y8 [# E该指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。
$ T' I3 g/ l% H语法格式
' H4 W ~4 c1 Z+ I- ^9 G; r `ADRL{cond} register,expr0 ?$ L5 k+ N$ `) [# y
示例6 }; F$ N( g# I8 d
start MOV r0,#10 ;因为PC值为当前指令地址值加8字节" N0 p$ Y+ J+ J0 J3 M2 ]4 s i) \$ ~
ADRL r4,start+60000 ;本ADRL伪指令将被编译器替换成下面两条指令0 w8 z+ B: r8 W" t' T* U
ADD r4,pc,#0xe800& o) D* W; n) e
ADD r4,r4,#0x254
! b) ^9 h, d8 w* |3、LDR(大范围的地址读取伪指令)6 r7 B2 }% F, r$ K- e- ]$ l
LDR伪指令将一个32位的常数或者一个地址值读取到寄存器中4 H$ b- p1 a* O+ E/ w' o. d
语法格式: {: @8 Q+ s3 S4 B0 H" C5 W/ }# y3 t+ y% Q
LDR{cond} register, =[expr|label-expr]4 g O$ f# h/ T; P' Y
其中,expr为32位的常量。编译器将根据expr的取值情况,如下处理LDR伪指令:
- X" g- i6 D2 Q" i/ J& p7 s7 s当expr表示的地址值没有超过MOV或MVN指令中地址的取值范围时,编译器用合适的MOV或MVN指令代替该LDR伪指令
) e/ G4 x- U) b) g当expr表示的地址值超过了MOV或者MVN指令中地址的取值范围时,编译器将该常数放在数据缓冲区中,同时用一条基于PC的LDR指令读取该常数。, t7 h9 h+ a* T& a4 V+ U: F( I
label-expr为基于PC的地址表达式或者是外部表达式。当label-expr为基于PC的地址表达式时,编译器将label-expr表示的数值放在数据缓冲区(literal pool)中,然后将该LDR伪指令处理成一条基于PC到该数据缓冲区单元的LDR指令,从而将该地址值读取到寄存器中。这时,要求该数据缓冲区单元到PC的距离小于4KB。当label-expr为外部表达式,或者非当前段的表达式时,汇编编译器将在目标文件中插入一个地址重定位伪操作,这样连接器将在连接时生成该地址。# ~; F- n! Z' ^+ ~1 T
LDR伪指令主要有以下两种用途:
1 m+ E* f4 r- m j% v/ [当需要读取到寄存器中的数据超过了MOV及MVN指令可以操作的范围时,可以使用LDR伪指令将该数据读取到寄存器中。' L% S {- M f( R8 |. l2 j/ P% N
将一个基于PC的地址值或者外部的地址值读取到寄存器中。由于这种地址值是在连接时确定的,所以这种代码不是位置无关的。同时LDR伪指令的PC值到数据缓冲区中的目标数据所在的地址的偏移量要小于4KB。
8 g( F4 ?3 D* ~: g! N M示例: ^" [+ j7 ^* n
将0xff0读取到R1中
# `. N0 P5 G, x w9 b; e* p$ H. n( SLDR R1,=0xFF0
5 E2 X* {% B+ ^9 a汇编后将得到:
; @* r, f5 P1 J @' t% |) ]MOV R1,0xFF0
6 Y1 z! R5 a( n+ L$ [将0xfff读取到R1中
7 d0 ]7 X! _0 G8 u4 J: F8 }6 RLDR R1,=0xFFF
. E" D9 n# x7 q1 N e7 D) P汇编后将得到:& o" d* ^$ N( |" [9 y
LDR R1,[PC,OFFSET_TO_LPOOL]2 W, s2 q2 ~9 d3 ~
…$ E4 W+ d1 c% O0 h3 s
LPOOL DCD 0xFFF
- H0 ~$ Q4 s* s5 M$ W! t$ b将外部地址ADDR1读取到R1中
/ O" y. M; y8 |LDR R1,=ADDR1
& z* ~) U% k: i) l' {汇编后将得到:
8 ]: d( r% N: tLDR R1,[PC,OFFSET_TO_LPOOL]8 D" P! c0 X; x" @2 H3 O* Z
…
0 [4 i+ Q/ z4 i ^LPOOL DCD ADDR1% P n) _8 _, m' u' O W
4、NOP空操作伪指令
% J9 S/ A2 X/ S# j+ v% J% g在汇编时将被替换成ARM中的空操作,如MOV R0,R0
+ Q& p4 J0 s. DNOP伪指令不影响CPSR中的条件标志位 |
|