1.先看启动代码:
.text
.global _start
_start:
ldr sp, =4096
bl disable_watch_dog
bl memsetup
bl copy_2th_to_sdram
bl create_page_table
bl mmu_init
ldr sp, =0xB4000000
ldr pc, =0xB0004000 //此处,指定了跳转到main.o处运行(在lds文件中指定了main.o在sdram的位置)
# bl main
halt_loop:
b halt_loop
2.然后看lds文件:
SECTIONS{
first 0x00000000 : { head.o init.o nand.o}
second 0xB0004000 : AT(2048) { main.o } //此处,指定main.o运行在0xB0004000
}
3.然后看主函数两种不同的书写格式
第一种格式为:(正确)
void delay(unsigned int time); //delay函数为声明,无代码,不产生操作指令
int main(void)
{
;
}
void delay(unsigned int time)
{
;
}
反汇编为:
b0004000 <main>: //main.o的入口函数为main,地址为b0004000
b0004000: e3a0320a movr3, #-1610612736; 0xa0000000
b0004004: e5932050 ldrr2, [r3, #80]
(省略)
b0004024 <delay>:
b0004024: e3500000 cmpr0, #0; 0x0
b0004028: d1a0f00e movlepc, lr
第二种格式为:(有问题)
void delay(unsigned int time) //函数,产生操作指令,入口地址的函数发生了变化
{
;
}
int main(void)
{
;
}
反汇编为:
b0004000 <delay>: //b0004000的入口变成了delay函数,不能进入main函数
b0004000: e3500000 cmpr0, #0; 0x0
b0004004: d1a0f00e movlepc, lr
(省略)
b0004018 <main>:
b0004018: e3a0320a movr3, #-1610612736; 0xa0000000
b000401c: e5932050 ldrr2, [r3, #80]
总结:
1.如果用ldr pc, =xxx指令跳转到一个可重定位文件执行,那个我们希望成为入口函数的函数要写在最前边,其他产生操作指令的动作、函数定义要写在他的后边。
2.如果入口函数调用其他函数,而这个函数又在本文件中定义,那这个函数一样会在入口函数前展开。
3.解决办法:
a.把入口函数需要调用的函数都写在另一个文件中,然后用#include包含过来
b. 把要调用的函数,加上声明:static inline ,变成内联函数。