关于加载地址和运行地址理解

来源:互联网 发布:手机淘宝如何举报卖家 编辑:程序博客网 时间:2024/05/16 18:20

这几天在看uboot的汇编部分,唯一觉得有点弄不懂的就是存储地址和运行地址了,网上看了很多文章,最后还是没有完全通透,云里雾里的,昨晚看了这篇帖子突然恍然大悟,特来谈谈个人的想法,不对的地方还请朋友们帮忙指出来,以便修正,谢谢^_^

加载地址/存储地址和运行地址/链接地址区别:
a.加载地址是指代码存储所在的物理地址,由于ARM总是从0开始取值,即PC初始值为0,所以加载地址必须对应0地址,程序才能正确启动执行,之后才可以进行跳转,比如设置PC等于一个子程序的入口地址,而这个入口地址可能在rom中也可能在ram中。
b.运行地址是链接器根据链接文件中指定的链接地址作为程序运行的起始地址,(作用)将程序中所有指令地址按照相对于这个起始地址的位置进行赋值,与程序实际运行时地址不一定相同,因为实际的程序运行起始地址总是0,而链接地址不一定为0,决定于程序需要在ROM还是RAM中运行);如果链接地址与加载地址设为相同,则所有寻址地址在ROM上都有对应的指令存在,也就可以正常执行;但如果链接地址与加载地址不同,则所有指令的地址是根据链接地址确定的,在ROM上不存在与之对应的代码入口(即使链接地址正好还处于ROM代码中,接下来执行的指令也将是不正确的和存在偏移的)
总的来说就是:加载地址是程序实际执行时的真实起始地址且必须为0;而链接地址的作用就是在链接过程中以链接地址为基准,确定程序中所有指令的相对位置,加载地址与链接地址相同时,该相对位置处才存在对应的指令,否则该相对位置处将不存在正确指令(uboot中存在特殊情况)所以加载地址与运行地址不同时的区别就是指令的寻址地址不同,而这个寻址地址只对位置相关指令如ldr起作用。
那么在程序中不就是根据指令地址来执行程序的吗,怎么有时候两者不同时程序也能正确执行?这就扯到了位置无关指令和位置相关指令,其实很容易理解:位置无关指的就是程序的实际运行地址(PC值)是根据之前的pc进行正负偏移得到的(比如b、bl指令)他不管代码被链接后指令所应该在的地址,这个偏移量在汇编时已经确定,不管程序当前位置处于rom还是ram,b指令总能得到下条指令的地址(绝对偏移)而继续执行;程序相关指的就是接下来的pc不是进行绝对偏移,而是进行相对偏移(比如ldr指令),也就是直接给pc赋一个相对值,这个值就是上面说的基于链接地址计算得到的指令的相对地址,那么问题就迎刃而解了——由上面推导可知:如果链接地址与加载地址不同,则pc得到的值与实际指令存放的地址就不是相同的,也就是该处没有有效的可执行指令,当然载入pc后程序也就会跑飞了。
问:将链接地址与加载地址刻意设为不同有什么作用?
答:如果所有代码都在ROM中执行,则链接地址必须设为加载地址0,除非你只用位置无关指令;而在嵌入式应用中,往往想要把程序加载到SDRAM中快速运行,但是碍于起始地址的影响,不可能直接达到这一步,所以思路就是:让程序加载地址等于rom起始地址,而链接地址等于ram中某一处的起始地址(暂且称为ram_start),所以在链接完成后所有指令的相对位置,程序先从ROM中启动,然后让代码中最前面内容实现代码的复制(ROM中程序->RAM中的ram_start处),并通过ldr指令(在这之前不应该使用位置相关指令给pc赋值!)将接下来要执行的指令的相对地址(在RAM范围内)赋给pc,程序就可以继续正确运行下去了。(b指令当然就没法用来跳转了)

下面来看几张图:
第一张为存储地址映射图
存储映射图
第二张为两次不同的链接地址所对应的反汇编
不同链接地址反汇编
第三张为代码重映射后存储映射图
重定位后示意图
第四张为程序运行流程示意图
运行示意图

1 0