|
|
本帖最后由 rergr 于 2022-3-29 15:36 编辑 1 Y2 @0 B E! q% l$ {
9 G7 Y2 `# f1 _8 I0 H$ Z- C( \0 ~& B
1、ADR(小范围的地址读取伪指令)
% }' B8 p! m* [2 ]+ h; K该指令将基于PC的地址值或基于寄存器的地址值读取到寄存器中。
) L( T: V9 [9 `! ~4 N7 E语法格式
% B0 ?, w) s+ RADR{cond} register, expr
% `3 }5 @5 i n! [! n a+ S6 s其中,cond为可选的指令执行的条件
' P. e! u% W- Z% p7 p* R/ [; qregister为目标寄存器% [1 f$ G0 h2 a
expr为基于PC或者基于寄存器的地址表达式,其取值范围如下:8 K/ D L0 ?$ k: Y
当地址值不是字对齐时,其取值范围为-255~255. t# t3 Q# n0 o! [
当地址值是字对齐时,其取值范围为-1020~1020# p. h4 }# N1 y0 g c! I, f
当地址值是16字节对齐时,其取值范围将更大
7 K4 H5 W" m* K' r在汇编编译器处理源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能。
0 }% B; W1 X# _' r( ]( M因为ADR伪指令中的地址是基于PC或者基于寄存器的,所以ADR读取到的地址为位置无关的地址。当ADR伪指令中的地址是基于PC时,该地址与ADR伪指令必须在同一个代码段中。9 ~% Z: s7 t% C8 s s& O* b: S
示例- l2 u6 v9 T' ^' d; N; c2 ~( i7 h0 g% u
start MOV r0,#10 ;因为PC值为当前指令地址值加8字节
3 Y1 |' U9 r/ ~2 bADR r4, start ;本ADR伪指令将被编译器替换成SUB r4,pc,#0xc, ?! k5 e( W# J5 E4 v9 u) ~3 v1 L$ s
2、 ADRL(中等范围的地址读取伪指令)
+ y- P. q" w; i, Q该指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。
. z) e' Z/ T3 k- B语法格式% x# \* ^3 ^* l% a/ H
ADRL{cond} register,expr
2 h, U8 e0 F" ~1 g4 s, ~1 h示例
5 ]% F3 A6 r- dstart MOV r0,#10 ;因为PC值为当前指令地址值加8字节
+ Q( w7 D, f+ I& G4 @. w* RADRL r4,start+60000 ;本ADRL伪指令将被编译器替换成下面两条指令% p& ^( C6 C/ K* v% G
ADD r4,pc,#0xe800
/ }' ?3 p) x) vADD r4,r4,#0x254& f2 g7 M1 {0 b. N
3、LDR(大范围的地址读取伪指令)
% [; H$ ^' c& [- \5 {- zLDR伪指令将一个32位的常数或者一个地址值读取到寄存器中
9 i6 w* L5 d+ I1 j# b/ Y9 o语法格式# {# N/ o8 G& X" y0 ]% h
LDR{cond} register, =[expr|label-expr]2 M' g' ` o4 a
其中,expr为32位的常量。编译器将根据expr的取值情况,如下处理LDR伪指令:- i! A$ t* D; g# t
当expr表示的地址值没有超过MOV或MVN指令中地址的取值范围时,编译器用合适的MOV或MVN指令代替该LDR伪指令" k! h( v4 q; R: h* J
当expr表示的地址值超过了MOV或者MVN指令中地址的取值范围时,编译器将该常数放在数据缓冲区中,同时用一条基于PC的LDR指令读取该常数。' ^8 [5 v( J2 i- m
label-expr为基于PC的地址表达式或者是外部表达式。当label-expr为基于PC的地址表达式时,编译器将label-expr表示的数值放在数据缓冲区(literal pool)中,然后将该LDR伪指令处理成一条基于PC到该数据缓冲区单元的LDR指令,从而将该地址值读取到寄存器中。这时,要求该数据缓冲区单元到PC的距离小于4KB。当label-expr为外部表达式,或者非当前段的表达式时,汇编编译器将在目标文件中插入一个地址重定位伪操作,这样连接器将在连接时生成该地址。
* b; H$ c9 R qLDR伪指令主要有以下两种用途:
" ?+ I; v3 w& |1 t当需要读取到寄存器中的数据超过了MOV及MVN指令可以操作的范围时,可以使用LDR伪指令将该数据读取到寄存器中。
5 C* z4 Y+ L$ D$ X将一个基于PC的地址值或者外部的地址值读取到寄存器中。由于这种地址值是在连接时确定的,所以这种代码不是位置无关的。同时LDR伪指令的PC值到数据缓冲区中的目标数据所在的地址的偏移量要小于4KB。
- @& T; M: Y& A9 S( F u Z) d示例
6 l: h" k, c% t# r& @) X将0xff0读取到R1中! t& B3 D* R+ Q& G, g/ O+ |
LDR R1,=0xFF0' ?' G% @( M1 F6 I2 H7 D8 x
汇编后将得到:7 }* \% }4 V' k6 c" H
MOV R1,0xFF0
2 b, T, {- z% n* M' @将0xfff读取到R1中
! C- C# @ v6 e4 F# \- E: fLDR R1,=0xFFF; Y# g* L4 }# t6 u% i$ o
汇编后将得到:: E4 z% j/ L8 z; @5 a
LDR R1,[PC,OFFSET_TO_LPOOL]/ U6 P: c1 W# c0 _: Q7 Z
…9 C6 t f) Z! {/ G) \$ X" T. W6 b
LPOOL DCD 0xFFF& |6 M/ G( ?0 y# G0 C5 H. c/ c
将外部地址ADDR1读取到R1中
, i8 R+ T1 l' c$ N! yLDR R1,=ADDR1$ D* H8 q/ ~& ^3 a/ M0 \
汇编后将得到:
; g! X: m# W1 @LDR R1,[PC,OFFSET_TO_LPOOL]9 B& ?" J. F( C' q, P
…% j9 ?! ] }" P& }
LPOOL DCD ADDR1
! w8 F/ D' h, [4、NOP空操作伪指令( ^; U# |8 k* L! {9 M
在汇编时将被替换成ARM中的空操作,如MOV R0,R0
1 v1 [/ b; R+ e+ q4 n, |NOP伪指令不影响CPSR中的条件标志位 |
|