在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数组中元素;