链接地址、运行地址、加载地址、存储地址、位置相关与位置无关
uboot-链接地址、运行地址、加载地址、存储地址、位置相关与位置无关
一.概念
1.运行地址:程序执行时的地址,因为命令执行分取指、译码、执行,所以运行地址就是PC-8处的地址。
2.链接地址:链接地址是给编译器用的,用来计算代码中相关地址偏移的。
3.加载地址和存储地址是等价的,只是两个不同的说法而已,指的是程序保存在Flash中的地址。
4.位置无关码:b、bl、mov等都是位置无关码
5.位置相关码:ldr pc,=xxx 等都是位置有关码
二.实例
由于运行地址与链接地址有时相同,有时又不相同,所以容易造成一些困惑,这里举例说明一下:
下面是链接脚本:
这个链接脚本中指定的程序链接地址是0x30000000,是因为2440开发板中的sdram地址是0x30000000。下面是start.S中代码重定位部分:
因为代码是烧写在nor flash中的,nor flash被映射在0地址,所以加载地址就是0。链接地址是0x30000000,所以生成的bin文件中代码保存的位置是0x30000000。如下分析图显示代码烧写执行步骤:
注:代码重定位之前,进行了sdram的初始化,由于截图未截上,这里写出代码部分:bl sdram_init。
接下来我们查看反汇编代码:
执行bl sdram_init时,反汇编中会跳转到30000478这个地址,但是这个时候我们sdram_init还没有执行,sdram并没有被初始化,所以这个地址是不存在的。这里只是反汇编中为了方便代码阅读这么写。这个时候是跳转到pc+offset处。假设程序从0x30000000执行,当前指令地址:0x3000005c ,那么就是跳到0x30000478;如果程序从0运行,当前指令地址:0x5c 调到:0x00000478。这个时候我们看到的程序运行地址还是在nor flash中,所以运行地址与链接脚本里的地址不一样。
三、ldr pc, =xxx命令解释
ldr pc, =step1 :该指令是从内存中的某个位置(step1)读出数据并赋给PC,同样依赖当前PC的值,但是偏移量是那个位置(step1)的链接地址(运行时的地址),所以可以用它实现从Flash到RAM的程序跳转。