准备
- 编译链:arm-linux-gnueabihf-gcc
- 源文件:led.s(汇编文件)
程序编译
-
编译文件
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
-
链接文件
这里要理解一下“运行地址”和“存储地址”这两个概念,存储地址是可执行程序文件所在的位置,这个地址可以随意选择;运行地址是代码运行时所处的地址,这个地址就是在我们链接文件的时候确定的,代码要运行,就必须处在运行地址处。这次,我将代码烧写到SD卡中,要运行就需要把可执行代码从SD卡拷贝到运行地址处。下面将 led.o 文件链接到地址 0x87800000,生成文件 led.elf。
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
-
格式转换
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
上述命令中,“-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,
选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试
信息。
这样,我们就得到了最终的可以在开发板上运行的 led.bin 可执行文件。至于为什么要进行格式转换,我去百度了一下,说明如下:
BIN文件只包含机器码;ELF文件除了机器码外,还包含了一些其他的信息,例如段的加载地址,运行地址,重定位表,符号表等等,这也使得ELF的文件比BIN文件更大。执行BIN文件比较简单,将其内容拷贝到运行起始地址就可以了,而ELF文件就比较麻烦,它需要一个ELF Loader。而uboot和内核启动的时候是没有 ELF Loader 的,所以需要转为BIN文件
Makefile内容
led.bin:led.s
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
rm -rf *.o led.bin led.elf led.dis
arm-linux-gnueabihf-objdump -D led.elf > led.dis
这一行是反汇编。