关于adr与ldr伪指令的理解

日前在学习arm的裸机开发,看启动代码时发现ldr伪指令与adr伪指令让我很困惑,为了弄懂他俩到底有什么区别,我在网上查阅了很多资料,也看了很多博文,最后加上自己的理解,感觉可以把这个经验分享给大家,让初学者们共同进步。

在这里我就不机械式的说这两条指令的定义了,虽然所有的用法都是基于他们的定义,但是要把定义理解透彻了才能真的明白个所以然来,这是很费时间的。我就按我的理解来吧。

首先adr伪指令它是小范围相对地址读取指令,也就是可以在在小范围内可以把地址值赋值给Pc或者寄存器,这个地址值通常都是我们在程序里所用的标号,程序里标号就代表一个地址。至于地址值怎么计算的呢?这就要说说相对的意思了,相对转移就是基于当前指令的地址加上或减去一个偏移量,这个偏移量是多少我们不用管,它是由编译器编译时计算出来的。还有就是adr指令只在同一个段中有效。这句看似无关紧要的说明,其实是很重要的,在接下来的例子中会提到。

而ldr伪指令这是大范围绝对地址读取指令,他通常也是把标号的地址值付给Pc或寄存器,只是他的地址值绝对的,这里的绝对又是什么意思呢?绝对的意思就是说这个地址值在编译连接是就已经确定了,即在生成目标文件时就已经确定了。也就是说在程序执行时不管什么时候在ldr伪指令中用到这个标号时,它对应的地址值只有一个,永远多不会变。

说了这么一大堆,可能有点迷糊了,下面举例说明一下吧。

例:在arm启动代码里开始有这样一段代码

AREA    Init,CODE,READONLY
ENTRY
ResetEntry


b ResetHandler
b HandlerUndef;handler for Undefined mode
b HandlerSWI;handler for SWI interrupt
b HandlerPabort;handler for PAbort
b HandlerDabort;handler for DAbort
b .;reserved
b HandlerIRQ;handler for IRQ interrupt
b HandlerFIQ;handler for FIQ interrupt

这里有一个标号ResetEntry,我们都知道arm启动代码的执行分两个阶段,第一个阶段是在Irom或者在SteppingTone中,第二个阶段在Sdram中。当程序在第一个阶段里执行时ResetEntry的地址值是0x0,这也是编译连接后它的地址值,那地址值又为什么是0呢?答案很简单,因为arm在上电后,程序是从0地址开始执行的,而标号ResetEntry代表的就是程序开始执行的地址。那么在第一个阶段中执行adr r0,ResetEntry后r0的值是0,执行完ldr r0,=ResetEntry后,r0的值也是0。也许现在还看不出来这两个指令有什么区别,但接下来程序跳到第二阶段里去执行,那么当执行adr r0,ResetEntry后,r0的值是多少呢,答案是:|Image$$RO$$Base|,它又是多少呢?这就要看看你在调试设置中Ro Base里面填的是多少了。如下图所示:


这里设置的是0x8000,所以r0的值就是0x8000。而执行完ldr r0,=ResetEntry后,r0的值还是0。这就看到区别了吧。可能细心的朋友会问,在程序执行的两个阶段里应该有两个ResetEntry啊?为什么adr r0,ResetEntry中的ResetEntry的地址值就必须是0X8000?原因在前文其实已经提到了,因为adr的作用域只在一个代码段,当程序在第二阶段执行时,代码段已经被复制到了Sdram中了,所以adr的寻址范围是不能超过这个代码段的,而在这个代码段中只有一个ResetEntry标号,所以地址值也只能是这个标号处的值了,也就是0x8000。

以上就是个人对adr、ldr两个伪指令用法的理解,只是个人观点,如有不对还请各位指正。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值