关于加载地址和运行地址理解
2017-12-30 20:52
218 查看
加载地址/存储地址和运行地址/链接地址区别:
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指令当然就没法用来跳转了)
下面来看几张图:
第一张为存储地址映射图
第二张为两次不同的链接地址所对应的反汇编
第三张为代码重映射后存储映射图
第四张为程序运行流程示意图
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指令当然就没法用来跳转了)
下面来看几张图:
第一张为存储地址映射图
第二张为两次不同的链接地址所对应的反汇编
第三张为代码重映射后存储映射图
第四张为程序运行流程示意图
相关文章推荐
- 关于加载地址和运行地址理解
- 关于运行地址和加载地址的几个很多初学者模糊不清的问题我在这里总结一下
- 对于ARM加载时、运行时地址的理解,各位多指教。
- 关于java运行的简单理解
- 运行地址,链接地址,加载地址,存储地址 位置无关码、位置有关码
- 关于apache以fastcgi模式运行php的错误理解纠正
- 代码的加载地址与运行地址
- 几个地址参数及uboot加载启动内核过程的理解
- 运行地址和加载地址
- 一段有趣的js代码,让你对js的运行加载有深刻的理解
- 运行地址和加载地址
- 运行地址和加载地址
- 关于laravel 自动加载和依赖注入、服务容器、服务提供者的理解--1
- U-Boot移植——链接地址、运行地址、加载地址、存储地址
- 关于inline hook中函数地址计算的理解
- 代码的加载地址与运行地址
- 运行地址和加载地址
- 关于对OC运行时机制的理解
- 关于程序动态库链接和运行时搜索路径设置的个人理解
- 关于广播地址分类的理解