这两天研究arm裸板程序,自己写了一个重定位程序,半天跑不通,最后终于解决了,但是这个问题总觉得莫名其妙,没有搞清楚为什么,所以请教下各位大神。
各位听我慢慢道来,先看代码关键部分:
copy:
ldr r0, =_start
adr r1, _start
ldr r3, =code_end
copy_loop:
ldr r4, [r1], #4
str r4, [r0], #4
cmp r0, r3
bne copy_loop
ldr pc, =led_shine
上述代码中“code_end”是从链接脚本中引入的,如下:
link.lds(全):
SECTIONS
{
. = 0xD0024000;
.text : {
start.o
}
code_end = .;
}
链接出来后运行一直不成功,不知道怎么回事,所以我将最终生成的.bin反汇编发现如下问题
d0024060 <copy>:
d0024060: e59f0044 ldr r0, [pc, #68] ; d00240ac
d0024064: e24f106c sub r1, pc, #108 ; 0x6c
d0024068: e59f3044 ldr r3, [pc, #68] ; d00240b4
d002406c <copy_loop>:
d002406c: e4914004 ldr r4, [r1], #4
d0024070: e4804004 str r4, [r0], #4
d0024074: e1500003 cmp r0, r3
d0024078: 1afffffb bne d002406c <copy_loop>
d002407c: e59ff034 ldr pc, [pc, #52] ; d00240b8
注意上面
d0024068: e59f3044 ldr r3, [pc, #68] ; d00240b4
这句,就是对应的ldr r3, =code_end
code_end指向的地址保存在d00240b4,再看后面
d00240b0: e0200244 eor r0, r0, r4, asr #4
d00240b4: d00240e2 andle r4, r2, r2, ror #1
d00240b8: d002403c andle r4, r2, ip, lsr r0
code_end指向的地址是d00240e2,居然是非4字节对齐的位置。我判断的是cmp r0, r3 bne copy_loop,是判断r0, r3是否相等。所以每次str r4, [r0], #4过后,r0加4,是不可能等于r3的(r3的值是d00240e2,因为四字节对齐,所以r0在这个值附近只会等于d00240e0, 或者d00240e4),这样就加过了,程序就跑飞了
我最后在ldr r3, =code_end后面加了一句add r3, r3, #2然后就跑通了
虽然问题解决了,但是我实在想不通这是为什么。
完全搞不懂为什么链接出来是这个样子,难道链接的时候所有的东西不是按4字节对齐的?
麻烦各位大神指导!
------解决方案--------------------
不过我倒是想起来一件事,以前做自动更新时用UltraEdit看过代码,长度的确不一定是4的整数倍
------解决方案--------------------
看看 《嵌入式Linux应用开发完全手册》