目标:
学习掌握ARM伪指令:ADR,ADRL,LDR,NOP。
ARM伪指令:
ARM指令和ARM伪指令有何异同?
ARM伪指令不是ARM指令,仅仅是为了编程方便,ARM伪指令是汇编器支持的,所以不同的汇编器,伪指令可能写法不同。如GNU ARM汇编器,ARM公司的ARM汇编器等。
ARM伪指令有汇编器转换成ARM指令。一条ARM伪指令可能转换成一条或者多条ARM伪指令。
关于ARM伪指令几点说明:
1、 ARM伪指令不是ARM指令,由汇编器转换成ARM指令
2、 一条伪指令可能转换成一条或者多条ARM指令
3、 定义ARM伪指令是为了编程方便,伪指令可以像ARM指令一样使用,由汇编器转换。
我们主要了解以下几条ARM伪指令:
1、 ADR: 小范围地址加载伪指令(使用相对寻址方式获得地址)
2、 ADRL: 地址加载伪指令(使用相对寻址方式获得地址),加载范围比ADR略大
3、 LDR: 地址/标号/数值加载伪指令
4、 NOP: 空指令,多用于延时
ADR伪指令:
ADR伪指令是将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。通常,汇编器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,汇编失败。
语法:
图:ADR伪指令
cond:条件助记符,如:EQ,NE等等。
register:寄存器,如R0。
expr:地址表达式,相对于PC或则其他通用寄存器。
示例:
图:ADR指令示例
可以看到,ADR 伪指令在汇编后会转换成一条加法(ADD)或者减法(SUB)指令,而且指令中第二个源操作数采用立即数格式,因为是表示一个连续范围,所以8位图里立即数的移位数是0,所以这个立即数就是8位图立即数的基数,一个8位的二进制数,0---255。
所以如果字对齐时,可以表示255个字,255*4=1020字节,如果地址时字节对齐的,那就是255字节。
注:
1、 需要回顾以下数据处理指令的8位图立即数(参考前面的内容)
2、 这条伪指令取地址是采用相对取址方式(这一点要记住,很重要)
ADRL 伪指令:
1、 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。
2、 ADRL比ADR伪指令可以读取更大范围的地址 。
3、 在汇编器对源程序进行汇编时,ADRL伪指令被汇编器替换成两条合适的指令。若不能用两条指令实现,则产生错误,汇编失败。
语法:
图:ADRL伪指令
cond:条件助记符,如:EQ,NE等等。
register:寄存器,如R0。
expr:地址表达式,相对于PC或则其他通用寄存器。
LDR 伪指令:
LDR伪指令用于加载32位的数值或一个地址值到指定寄存器。
在汇编器汇编源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未可以使用8位图立即数表示,则使用MOV或MVN指令替代。否则汇编器将数据放入内存区,并使用一条程序相对偏移的LDR指令从内存区读出数据。
语法1:
将数值或者标号地址值加载到寄存器
图:LDR伪指令语法1
cond:条件助记符
register:通用寄存器
=expr或者=label_expr:=后面跟常数或者一个标号
示例:
ldr r0, =0xFFFF0000
将数值0xFFFF0000加载到寄存器R0,
ldr r1, =0xFFFFFFFF
将数值0xFFFFFFFF加载到寄存器r1
ldr r0, =strcmp
将标号strcmp对应的地址值加载到寄存器r0
...
LDR R1, =test_data
LDR R0, [R1]
...
test_data
执行后,R1寄存器的值时test_data这个标号表示的地址,R0是0x12345678 。
语法2:
将标号对应地址单元的一个字的值加载到寄存器。
图:LDR伪指令语法2
cond:条件助记符
register:通用寄存器
label_expr:标号(代表地址)表达式
注:这种写法没有 =
示例:
...
LDR R1, test_data
...
test_data
这种写法不用于加 =
说明:
ldr 伪指令的两种写法:
1、 有 =,是加载数值,或者标号代表的地址
2、 没有=,是加载标号表示的地址单元的数据到寄存器
ldr伪指令和ldr加载指令如何区分?
ldr 指令的地址模式是 基址+偏移量的方式:ldr r0,[r1, #8],写法上有 [],而伪指令没有。所以加载指令ldr写法上一定有 []。
NOP 伪指令:
空指令,用于延时。
通常汇编器使用 mov r0, r0 指令替代。
语法:
NOP
示例:
领取专属 10元无门槛券
私享最新 技术干货