×
单片机 > 单片机程序设计 > 详情

对链接地址0x30008000(S3C2440)的理解

发布时间:2022-01-05 发布时间:
|

当我们写链接器脚本的时候,我们会设置代码段的起始链接地址为0x30008000(S3C2440)。如果对链接地址理解错误的话,可能会出现像我这样的问题。


Q:gboot的链接器脚本里写的其实链接地址是内存中的0x30008000,再用交叉工具反汇编得到的start.S前几行代码地址都变成了0x30008000+,不太对啊。ARM启动流程里面讲处理器将NAND中的代码复制了4K到垫脚石中,垫脚石的地址是0x0,也正是因为这样,我们设置的异常向量表才有意义,处理器才能准确的找到处理异常的标号。但是把链接地址改成了0x30008000还怎么找?


A:首先要理解链接地址。我认为,链接地址就是为程序假想了一个起点,之后的代码都是在这个假想的起点基础上展开的。我们只有根据这个链接地址,才能找到后续的一些指令并执行。但是这个链接地址不是实际的指令的地址,我们先对gboot.elf进行反汇编看看


30008000 <_start>:

30008000: ea000014 b 30008058

30008004: e59ff014 ldr pc, [pc, #20] ; 30008020 <_undefined_instruction>

30008008: e59ff014 ldr pc, [pc, #20] ; 30008024 <_software_intrrupt>

3000800c: e59ff014 ldr pc, [pc, #20] ; 30008028 <_prefetch_abort>

30008010: e59ff014 ldr pc, [pc, #20] ; 3000802c <_data_abort>

30008014: e59ff014 ldr pc, [pc, #20] ; 30008030 <_not_used>

30008018: e59ff014 ldr pc, [pc, #20] ; 30008034 <_irq>

3000801c: e59ff014 ldr pc, [pc, #20] ; 30008038 <_fiq>


用b reset举例,虽然reset标号的地址已经到了0x30008000,但是我们的代码此时实际上是在垫脚石中运行的,也就是说PC指针还是指在0x0的位置。这样0x0和0x30008000就形成了一个映射的关系,即0x4相当于0x30008004,0x8相当于0x30008008......,都是因为我们将链接起始地址设成了0x30008000,这也就是我们所说的相对跳转。


Q:为什么链接起始地址要写成0x30008000?


A:照理说这个地址是随意的,只要在S3C2440的寻址空间内都可以。但是后期我们要执行C语言程序,而对堆栈等的初始化都是对SDRAM进行的,即在0x30000000之后的64M空间中。所以为了C语言能够成功运行,直接将代码的链接地址设到内存中,这样方面之后的绝对跳转,即


ldr pc, =main

一定要注意寄存器可用的位数,若少于32位的,必须用移位来赋值,或者定义时就确定位数


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR熔丝位操作时的要点和需要注意的相关事项