|
本帖最后由 rergr 于 2022-3-29 15:36 编辑 0 A, O8 v" {- y
" [3 ?( s# W% a# K i
1、ADR(小范围的地址读取伪指令)
" O" u& M5 c7 j2 W0 v1 t9 m }该指令将基于PC的地址值或基于寄存器的地址值读取到寄存器中。
& b5 [$ k/ z" r n! e: b: K语法格式7 ~7 N# q# J9 V8 W; z' W0 U
ADR{cond} register, expr# T; b# H5 C7 {7 G- c* V
其中,cond为可选的指令执行的条件/ M( q: c/ n) v8 C: o6 q# e
register为目标寄存器
, X( `; R. p0 @2 H/ Jexpr为基于PC或者基于寄存器的地址表达式,其取值范围如下: S- ?1 A5 ~& [
当地址值不是字对齐时,其取值范围为-255~255.+ J6 U R% @. t3 l8 o
当地址值是字对齐时,其取值范围为-1020~1020
[3 a# s7 p* F当地址值是16字节对齐时,其取值范围将更大
% T( Y4 |# J- a$ B3 m- C0 p8 o7 z在汇编编译器处理源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能。4 P% D: D( M* g+ c# [1 r0 \4 P
因为ADR伪指令中的地址是基于PC或者基于寄存器的,所以ADR读取到的地址为位置无关的地址。当ADR伪指令中的地址是基于PC时,该地址与ADR伪指令必须在同一个代码段中。
' x9 G: I! ` x/ n. D示例 ~/ p. g& I+ ^3 g4 K$ l
start MOV r0,#10 ;因为PC值为当前指令地址值加8字节
: j8 t+ Y! I: E2 A1 S7 nADR r4, start ;本ADR伪指令将被编译器替换成SUB r4,pc,#0xc$ d: b7 y9 p( t0 D
2、 ADRL(中等范围的地址读取伪指令): b7 o o: _8 x/ r8 ] {
该指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。
/ M' ?6 E( L8 G语法格式
7 K+ s, t! D' G6 I( XADRL{cond} register,expr
' p0 ~3 W1 q$ S% }- V示例! U* V. d2 `7 l+ y
start MOV r0,#10 ;因为PC值为当前指令地址值加8字节
2 ]4 G D/ P1 i) S2 d- }ADRL r4,start+60000 ;本ADRL伪指令将被编译器替换成下面两条指令* b$ H+ A$ }( l& p
ADD r4,pc,#0xe800* i, _: s p2 k1 B
ADD r4,r4,#0x254
1 y! _ n; H ]9 Q1 R) L" D+ Z9 f7 |3、LDR(大范围的地址读取伪指令)
+ F" \/ U8 B# @; J' s. x6 wLDR伪指令将一个32位的常数或者一个地址值读取到寄存器中
: w' O6 \2 P4 n2 {! q语法格式
5 t" q0 |3 L! O L) i' \LDR{cond} register, =[expr|label-expr]
6 Z7 Z6 K8 ]. \& q8 M* Y其中,expr为32位的常量。编译器将根据expr的取值情况,如下处理LDR伪指令:
3 M- }, Q) g" ~ Y! E当expr表示的地址值没有超过MOV或MVN指令中地址的取值范围时,编译器用合适的MOV或MVN指令代替该LDR伪指令
W( `0 X; d+ f当expr表示的地址值超过了MOV或者MVN指令中地址的取值范围时,编译器将该常数放在数据缓冲区中,同时用一条基于PC的LDR指令读取该常数。
) d8 ]) ~, S! [label-expr为基于PC的地址表达式或者是外部表达式。当label-expr为基于PC的地址表达式时,编译器将label-expr表示的数值放在数据缓冲区(literal pool)中,然后将该LDR伪指令处理成一条基于PC到该数据缓冲区单元的LDR指令,从而将该地址值读取到寄存器中。这时,要求该数据缓冲区单元到PC的距离小于4KB。当label-expr为外部表达式,或者非当前段的表达式时,汇编编译器将在目标文件中插入一个地址重定位伪操作,这样连接器将在连接时生成该地址。
0 o7 A! ^% {! YLDR伪指令主要有以下两种用途:
8 b4 C# q5 u& [7 c: J' I当需要读取到寄存器中的数据超过了MOV及MVN指令可以操作的范围时,可以使用LDR伪指令将该数据读取到寄存器中。) t) B2 O5 H% l, h+ O
将一个基于PC的地址值或者外部的地址值读取到寄存器中。由于这种地址值是在连接时确定的,所以这种代码不是位置无关的。同时LDR伪指令的PC值到数据缓冲区中的目标数据所在的地址的偏移量要小于4KB。7 L7 d' Y) L' R9 F1 o4 K- ]8 f
示例
' S. E1 J3 [# F8 J将0xff0读取到R1中$ K: g! B8 ~; g5 M
LDR R1,=0xFF0
/ h- F5 N1 [3 {8 `8 X汇编后将得到:6 O4 T: Y4 U- o8 J+ B5 J
MOV R1,0xFF0
; K3 ^: a9 d9 ?. `将0xfff读取到R1中0 M: R7 l0 f: v+ a
LDR R1,=0xFFF
, i9 X( c, D- m. l; i5 P& p汇编后将得到:& |: ~: A0 e7 I v2 i" }* ~2 b
LDR R1,[PC,OFFSET_TO_LPOOL]* \+ k& M8 w3 j) W) e- o. s
…
. V8 A0 y y, G4 \( v" ?0 H! |7 `: iLPOOL DCD 0xFFF2 D. ?7 B9 ^9 Z
将外部地址ADDR1读取到R1中7 P% }$ \0 U* k( Y
LDR R1,=ADDR1
. x; }: ~' C: s. T汇编后将得到:
: k5 k% J/ j! j' a' L+ n* jLDR R1,[PC,OFFSET_TO_LPOOL]# i( } A/ s6 q* I* B7 w* z. u" v
…4 Y, Q5 c ]+ |3 c6 l
LPOOL DCD ADDR1' @* L/ X" R# M5 o; M1 c
4、NOP空操作伪指令! K$ u. o9 G7 z. i/ X. b
在汇编时将被替换成ARM中的空操作,如MOV R0,R0
: C5 v8 }1 o7 n% G" `4 W% VNOP伪指令不影响CPSR中的条件标志位 |
|