ARM ldr与adr指令对比

adr指令与ldr指令,都是加载,而他们的区别在于:
     adr指令加载符号时加载运行地址(相对位置),编译器编译后改成add指令或sub指令
     ldr指令加载符号时加载链接地址(绝对位置),编译器编译后仍是ldr指令(原来的ldr是伪指令)。

实际测试以下程序:
.global _start
_start:

    adr r0, _start
    ldr r0, _start
    ldr r0, =_start

    b .              @结尾死循环

反汇编结果如下:
00000000 <_start>:
   0:    e24f0008     sub    r0, pc, #8
   4:    e51f000c     ldr    r0, [pc, #-12]    ; 0 <_start>
   8:    e59f0000     ldr    r0, [pc, #0]    ; 10 <_start+0x10>
   c:    eafffffe     b    c <_start+0xc>
  10:    00000000     andeq    r0, r0, r0
首先看 adr r0, _start
   0:    e24f0008     sub    r0, pc, #8
由于arm有两级流水线,所以当前pc指令指向0x8,所以r0就是0x0。
ldr r0, _start
   4:    e51f000c     ldr    r0, [pc, #-12]    ; 0 <_start>
可以看出r0的值也指向0x0.
ldr r0, =_start
   8:    e59f0000     ldr    r0, [pc, #0]    ; 10 <_start+0x10>
此时注意到r0的值指向了0x10,而0x10地址内存放的正是00000000, _start标号。

从上面的实际测试看出,
adr r0, _start     ;这条指令中adr被转化为了add或sub指令,是根据pc当前指向的位置来获取_start标号的位置,是基于pc的偏移量,因此取得的是相对位置
ldr r0, _start     ;这条指令也是根据pc当前指向位置来获取_start标号的位置,与adr不同的是使用了ldr指令
ldr r0, _start     ;这条指令是用文字池的方式来得到一个地址,而地址里放的内容才是_start标号的地址,取得的是绝对位置

查阅其他资料时得知,adr主要是用作短加载,因转化为add/sub的形式,所以其寻址空间较小。adr的寻址空间只有前后4kb,而且必须在同一个代码段中,只能用于短加载。ldr没有这些要求,ldr指令取得的是绝对地址,可用来长加载或长跳转。

综上:ldr和adr的区别主要就是地址的位置无关性的差别。

补充:指令adrl
adrl //转化成两个ADD,寻址空间是8KB
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值