在ARM学习过程中,用到代码的重定向,链接脚本中字节不对齐时碰到的问题,具体初始化代码如下
1、链接脚本
SECTIONS { . = 0xD0020010; .text : { start.o * (.text) } .data : { * (.data) } bss_start = .; .bss : { * (.bss) } bss_end = .; }
2、这段代码的主要功能是将代码拷贝到指定的连接地址运行,
.global _start _start: adr r0,_start ldr r1,=_start ldr r2,=bss_start cmp r0,r1 beq clean_bss copy_loop: ldr r3,[r0],#4 str r3,[r1],#4 cmp r1,r2 bne copy_loop clean_bss: ldr r0,=bss_start ldr r1,=bss_end cmp r0,r1 beq run_on_dram mov r2,#0 clean_loop: str r2,[r0],#4 cmp r0,r1 bne clean_loop run_on_dram: ldr pc,=main halt: b halt
3、主函数
char c; int main() { uart0_init(); while(1) { c = getc(); putc(c+1); } return 0; }
遇到的问题是加了连接脚本重定向之后程序不能运行了,通过反汇编查处问题所在。
在反汇编代码中看到
d0020060: d002027c andle r0, r2, ip, ror r2 //bss_start d0020064: d002027d andle r0, r2, sp, rorr2//bss_end
bss_end与bss_end竟然只相差一个字节,也就是说bss段只占用了一个字节,bss清0代码为
str r2,[r0],#4
cmp r0,r1 //r0为bss_start,r1为bss_end
每次清0步进为4字节而由于bss段只有一个字节,第一次比较r0,r1时,不相等,执行循环,bss_start地址加4之后清0在比较,由于多加4个字节,因此也不想等,继续加,这样一直循环下去,到只程序在这里执行死循环。
为什么bss段只有一个字节呢?
bss段是放置未初始化的全局变量和静态变量,由于main中使用了一个全局的char c变量,因此只占用一个字节。
解决办法:
最后的解决办法是将charc定义为局部变量,也可以将清0段代码步进改为1,如果在连接文件中使用ALIGN(4)进行字节对齐,当使用char数组是应该注意每一个char均占用了4byte,因此不能用以往占用一个字节的方式读取char数组中元素;