uboot中的汇编 adr r0, _start详解

在U-Boot的代码重定位部分(start.S)有这么一段:

relocate:           /* relocate U-Boot to RAM       */
adr r0, _start      /* r0 <- current position of code   */
ldr r1, _TEXT_BASE  /* test if we run from flash or RAM */
cmp r0, r1          /* don't reloc during debug         */
beq stack_setup

从注释可知,adr r0, _start虽加载的是同一个标号_start的地址,但是其结果会因为当前U-Boot到底是运行于Flash还是运行于RAM而有所不同!主要是由于链接地址与运行地址的不一致导致的。

1 位置无关指令

根据参考资料[2]的指出,在汇编语言中,bl、b、adr(adr属于伪指令,一般被编译器解释成sub指令)指令都属于位置无关指令,不管程序装载在哪个位置上,bl、b、adr指令都能正确的运行,其原因是bl、b、adr指令的地址域是基于PC的相对偏移寻址,相当于PC+offset。当ARM启动时,ARM自动取0x00000000位置上的指令,此时PC=0x00000000。基于PC偏移量的指令都能正确的执行。

2 偏移offset

对于adr r0, _start,标号_start的值在链接的时候已经确定(smdk2410将_start链接为0x33f80000),在后期运行时也是无法改变的。同时adr r0, _start命令的链接地址也是在链接时就已经确定了(这里假设为0x33f80010)。因此_start链接地址与adr r0, _start链接地址之间的偏移offset = 0x33f80000 - 0x33f80010 = -0x10。这个偏移是固定的(因为链接地址是固定的)。

3 FLASH运行

在FLASH运行时候,标号_start存储于0x00000000地址处,而相应的adr r0, _start命令存储于地址0x00000010处。当执行adr r0, _adr命令时,PC等于其存储地址0x00000010,因此r0 = PC + offset = 0x00000010 - 0x10 = 0x00000000。

4 RAM运行

假设已经通过重定位将U-Boot的代码复制到SDRAM 0x33f80000开始的位置,此时_start存储于0x33f80000地址处,adr r0, _ad命令存储于0x33f80010地址处。当在RAM中执行该命令时,PC等于其存储地址0x33f80010,偏移地址offset不变,因此r0 = PC + offset = 0x33f80010 - 0x10 = 0x33f80000。

5 总结

通过上述分析可知,当U-Boot分别运行的FLASH和RAM时,adr r0, _start的结果是不一样的,主要是因为PC不一样,但是偏移offset是不变的。

参考资料

[1]从两句汇编认识运行时地址与链接地址

[2]U-Boot移植过程中的运行地址和装载地址的区别

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值