|
|
本帖最后由 rergr 于 2022-3-29 15:36 编辑 2 \) J' @$ \7 t H- W9 d P
/ ?( S8 _% A: v6 a f7 H
1、ADR(小范围的地址读取伪指令)" g& W7 k9 v5 T$ ^6 |9 A( @
该指令将基于PC的地址值或基于寄存器的地址值读取到寄存器中。
* R8 c0 Q. ?( q8 Z3 J& Y语法格式
' _; J, I" @- i* g9 p- XADR{cond} register, expr
, n5 [% F$ F! p1 v8 P3 K其中,cond为可选的指令执行的条件
6 a9 D! p B; lregister为目标寄存器
; X- J. C) u3 Q7 |2 h) z$ Wexpr为基于PC或者基于寄存器的地址表达式,其取值范围如下:5 M+ i( i. ?9 v* c& I
当地址值不是字对齐时,其取值范围为-255~255.
# n3 b( j8 M: O) w当地址值是字对齐时,其取值范围为-1020~1020& X1 ]0 |( k6 r3 X+ v
当地址值是16字节对齐时,其取值范围将更大
/ h4 q+ K6 I" M在汇编编译器处理源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能。6 B4 z4 Z$ g5 D7 S
因为ADR伪指令中的地址是基于PC或者基于寄存器的,所以ADR读取到的地址为位置无关的地址。当ADR伪指令中的地址是基于PC时,该地址与ADR伪指令必须在同一个代码段中。7 p5 \2 Z- L" g; o7 O4 r
示例- L# Y" k1 m4 K( u: v0 y" b' i
start MOV r0,#10 ;因为PC值为当前指令地址值加8字节+ u: j# g9 G, V3 W6 C" N/ \% h
ADR r4, start ;本ADR伪指令将被编译器替换成SUB r4,pc,#0xc
$ O, `$ u( U! |9 r( B2 ~ `' p2、 ADRL(中等范围的地址读取伪指令); S5 E7 B; a+ o. F/ H0 [
该指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。
: k2 G4 l2 y8 P语法格式 k6 v* T& V7 V% }) ^
ADRL{cond} register,expr
5 g3 E) }2 ?1 `. l1 a H7 p) ]示例$ Z, G% ^5 G; B9 S1 h( @# R
start MOV r0,#10 ;因为PC值为当前指令地址值加8字节1 {5 n; M8 p4 [
ADRL r4,start+60000 ;本ADRL伪指令将被编译器替换成下面两条指令
3 U, ^. K+ a( |ADD r4,pc,#0xe800& Z' X3 w1 W4 I% K( B3 C: _
ADD r4,r4,#0x254# j0 ?' a$ j4 Z* Q; E( U3 ?4 D1 u. N
3、LDR(大范围的地址读取伪指令), x! d0 i$ g8 t
LDR伪指令将一个32位的常数或者一个地址值读取到寄存器中
# v, N9 p z6 p1 P/ I/ c1 |语法格式, t. s# q1 m: @0 s6 k
LDR{cond} register, =[expr|label-expr]" b; i' w! K: s* a; E- t5 \
其中,expr为32位的常量。编译器将根据expr的取值情况,如下处理LDR伪指令:1 U0 J# g3 N8 Q5 L; E) [
当expr表示的地址值没有超过MOV或MVN指令中地址的取值范围时,编译器用合适的MOV或MVN指令代替该LDR伪指令
( R, N# {7 h) w& s" U; G& p8 M$ ^( ?当expr表示的地址值超过了MOV或者MVN指令中地址的取值范围时,编译器将该常数放在数据缓冲区中,同时用一条基于PC的LDR指令读取该常数。
) X: k$ s, g! Ylabel-expr为基于PC的地址表达式或者是外部表达式。当label-expr为基于PC的地址表达式时,编译器将label-expr表示的数值放在数据缓冲区(literal pool)中,然后将该LDR伪指令处理成一条基于PC到该数据缓冲区单元的LDR指令,从而将该地址值读取到寄存器中。这时,要求该数据缓冲区单元到PC的距离小于4KB。当label-expr为外部表达式,或者非当前段的表达式时,汇编编译器将在目标文件中插入一个地址重定位伪操作,这样连接器将在连接时生成该地址。
; y7 O7 x, s' u$ YLDR伪指令主要有以下两种用途:
1 M' R( p# n4 y8 M. T- u# U当需要读取到寄存器中的数据超过了MOV及MVN指令可以操作的范围时,可以使用LDR伪指令将该数据读取到寄存器中。4 f0 `( w4 T/ q6 H0 [" u
将一个基于PC的地址值或者外部的地址值读取到寄存器中。由于这种地址值是在连接时确定的,所以这种代码不是位置无关的。同时LDR伪指令的PC值到数据缓冲区中的目标数据所在的地址的偏移量要小于4KB。4 c1 h$ V8 N% _9 V6 _
示例' q7 K& N0 z, X" X5 P& u8 Z) ^+ C
将0xff0读取到R1中
: h, X/ d5 v( X% ?2 w$ t+ WLDR R1,=0xFF0
0 H: m& N) X9 X- N汇编后将得到:5 S; z. S7 f3 Z7 y8 I# Y7 n' U
MOV R1,0xFF0: n; G. e8 m0 W
将0xfff读取到R1中3 v# ^3 k* M8 w7 ^9 i
LDR R1,=0xFFF4 r$ Y2 y$ l, Y" r
汇编后将得到:; S" [4 j* P0 F7 J/ {. i8 N2 E
LDR R1,[PC,OFFSET_TO_LPOOL]
( i# Z! u9 l) j) P6 _$ V…
% Z) I1 \! h/ Q1 |( @LPOOL DCD 0xFFF8 s+ F' l: t, [9 M6 T7 X& R
将外部地址ADDR1读取到R1中7 I$ Z! h! J% ?6 ~/ |
LDR R1,=ADDR1
' L* p5 [: N- T' i M汇编后将得到:0 E/ E" C' o! n9 Q, V
LDR R1,[PC,OFFSET_TO_LPOOL]- y* W% @6 D, c
…
+ }7 d7 K3 O1 B, uLPOOL DCD ADDR1, x- y5 {. Y, d! g) U- @4 y
4、NOP空操作伪指令
2 d8 H% A$ |$ R4 C& Y2 z6 X) x在汇编时将被替换成ARM中的空操作,如MOV R0,R04 A. ~6 @6 n N( m# Z5 C0 k
NOP伪指令不影响CPSR中的条件标志位 |
|