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