1 现象
- 程序完全正确,但是由于程序链接的位置不对,导致程序没有正常运行。
2 寻找原因
- 对生成的bin文件进行反汇编:
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
-
查看生成的反汇编文件
发现在在链接的开始地址处(0x87800000),定义了一个名为"clk_enable"的函数或代码段的起始位置,而不是_start程序(_start 是一个特殊的符号或标识符,它在编译和链接过程中用于表示程序的起始点。)。 -
在我们的start代码中,我们初始化了堆栈指针,这个程序必须放在链接的起始地址处(0x87800000)
3 原因
- 为什么编译后的bin文件没有正确的链接顺序呢?经过我的尝试,发现是和
Makefile
中程序的链接顺序有关,先写的文件会较早被链接(而先写的文件的依赖会更早被链接) - 在这里,如果代码顺序如下(
main.o
比start.o
先写)
# 定义目标文件列表
objs := main.o start.o
# 生成目标文件 ledc.bin
ledc.bin : $(objs)
arm-linux-gnueabihf-ld -Ttext 0x87800000 -o ledc.elf $^
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
那么 main.o
及其依赖会比start.o
先被链接。
4 解决方法
确保每次书写 Makefile
时,start.o
都写在最前面:
# 定义目标文件列表
objs := start.o main.o
# 生成目标文件 ledc.bin
ledc.bin : $(objs)
arm-linux-gnueabihf-ld -Ttext 0x87800000 -o ledc.elf $^
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis