ARM处理器学习之GPIO操作篇(gnu link script)
led_control.lds
/* * led_control 的链接脚本。 * * */ MEMORY { rom (rx) : ORIGIN = 0x80000000, LENGTH = 2M ram (!rx) : ORIGIN = 0x40000000, LENGTH = 2M } ENTRY(_start) SECTIONS { . = 0x80000000 ; .init : { initsystem.o(.text) start_copy_addr = . ; } >rom . = 0x40000000 ; .main : AT (ADDR(.init)+SIZEOF(.init)) { control_led.o(.text) } >ram }
Makefile
control_led.bin:control_led.s initsystem.s arm-linux-gcc -g -c -o control_led.o control_led.s arm-linux-gcc -g -c -o initsystem.o initsystem.s arm-linux-ld -Tled_control.lds -nostdlib -g control_led.o initsystem.o -o control_led_elf arm-linux-objcopy -O binary -S control_led_elf control_led.bin clean: rm -f control_led.bin control_led_elf *.o
6:源码重点解释
关于上面两个.s的汇编文件,这里就不再赘述,请读者自行分析。主要说说这个链接脚本的相关知识。gnu 链接脚本的详细资料参见,gnu_Linker.pdf这个官方资料。
链接文件的细节问题这里也不再提及,只说一下关键点。
1问:为什么我将初始化,copy的代码放在一个单独的文件里?
1答:我最开始把所有代码放在一个文件里,使用.section 伪指令定义新的段名,在链接脚本里使用不同的地址存放不同的段。但程序一直不能正常运行,后反编译得知,我这样做,链接出来的映像文件和我在链接脚本里指定的不一样。后查资料得知,gnu link 对每个源文件都有默认的三个段名:.text .data .bss 。链接脚本里的输入段只允许这些段名。因此我将启动代码单独放在一个文件里,且所有的代码均在 .text 这个段里。
2问:我在链接脚本里能定义标号吗?定义的标号,怎么在汇编里引用呐?
2答:可以在链接脚本里定义标号,这里定义的标号的意义等同于在编程语言里的地址。在上面给出的例子中,我们copy代码并不是从第一条指令开始copy的,而是从执行完初始化和copy代码这些功能后开始指令。那我们怎么知道initsystem里面的指令到底占用多少空间,我们在链接脚本里定义了
start_copy_addr = . ;
其中
start_copy_addr 为标号的名称,它的值被赋成 . 其中这个dot代表当前链接的地址,此时的地址是从0x80000000开始加上initsystem.o 里所有代码长度后的值。那我们从这个地址开始copy代码是最合适的了,那这个地址在ARM 汇编里怎么使用哪?
.extern LDR R1,=start_copy_addr @R1指向源地址@先声明这个标号
LDR R1,=start_copy_addr @R1 指向源地址
在c语言里应该这样:
extern start_copy_addr ;
然后 使用&start_copy_addr 的方法来使用这个标号的值。
7:相关资料
我下面列出的相关资料都上传到我的csdn资源中。下载地址:http://download.csdn.net/detail/zhanglianpin/7546779
ARM开发指南中文版系列文章。
gnu-assembler.pdf
gnu_Linker.pdf
linker&&loader.pdf
8:后记
其实,程序链接这方面的知识,对理解程序结构是很有帮助的。尤其做嵌入式软件开发。我们阅读uboot linux 内核等开源程序时,若不理解链接过程是很难阅读透彻的。
另外,我们写程序时,其实有很多伪指令都是针对编译、链接器的。了解了这方面的知识,我们综合利用程序、链接才能充分实现我们的想法。
ARM处理器GPI 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)