程序运行地址和加载地址(2)

注意最左边的数字,这就代表程序的运行时地址。也就是说程序的代码的地址是以运行地址为基址来标示的。什么意思呢, 看 head.s中的  ldr    pc,=loop  这段,这是想让 程序调回到 loop处(死循环)
 当运行地址设定为 0x0 时 从汇编代码我们看到 loop标号代表的地址为0000004
 也就是说  ldr    pc,=loop 反汇编为 ldr    pc, [pc, #-4] 即pc值为pc-4地址里面放的值(4)。就是跳转到 00000004 地址去
 
 那么把运行地址设定为0x30000000时, 从反汇编代码中我们看到 这时 loop表号代表的地址是0x30000000
 那么 ldr    pc,=loop 就是跳转到 地址 0x30000000
 
简单的理解就是 程序运行地址 就是 计算机认为程序运行时应该处于的地址。
所以 运行地址设置为0 时,程序中的所有代码的中的标号都是以0x0为基址的。计算机认为他运行的时候的地址是从 0x0开始的。
 运行地址设置为0x30000000 时,程序中的所有代码的中的标号都是以0x30000000为基址的。计算机认为他运行的时候的地址是从0x30000000开始的
 
 
明白了 运行地址 的概念后,我们来看看程序的启动过程

假设现在程序的 加载地址(烧到nand flash中的位置)为0 运行地址为0x30000000
前面说过程序是烧写在 nand flash中从 0地址开始的地方,那么以nand flash方式启动后,该程序被拷贝到 片内ram中。这时候pc为0。并开始运行程序,也就是说,计算机现在从 片内内存地址0开始运行程序进行一些初始化操作并将sdram初始化后再跳转到sdram中去运行。
但是我们上面不是说,程序运行地址被设置成了 0x30000000(SDRAM的起始地址)吗。

但是程序在跳转到sdram之前却是在0x0地址开始运行。这就造成了前面这段还未跳转到sdram(从0x30000000开始)的程序的实际程序运行地址和设定的运行地址不符合。


如果程序中没有用到 地址有关代码,和全局变量静态变量之类地址有关变量,那么这段 在初始化SDRAM之前 的程序 其实还是可以运行下去的
并在初始化SDRAM后,跳转到SDRAM中去运行,一切正常
但是如果程序中用了这些代码。就不会运行成功了。

原因很简单,应为现在我们设定的 运行地址为 0x30000000,那么当我们执行地址有关代码 如 ldr pc,=A (A是个标号或函数名)
就是使用了 绝对地址,那么 pc = 0x3000000+x (x为标号A相对于起始也就是前面设定的运行地址的偏移) 。

那么这条指令执行之后,pc 指针将跳转到 0x30000000后的某处(SDRAM中)。但是 sdram 现在 还未初始化!
这就 造成了 错误。
同样 如果有全局变量 或静态变量也是。

所以我们需要使用 b bl类的 位置无关指令。  如  b  A
b bl跳转是基于 pc的 跳转。即相对跳转 ,比如执行 b A 这条指令时,假设 现在pc =5. A标号相对当前的位置为2(在之后)
那么 b A 后 pc =pc +2    即计算机不管当前pc指针是多少,他执行的是相对于当前位置的跳转。也就避免了 向上面的那样跳转到了 0x30000000之后的未初始化的地址中去

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/bf03c36549f4617861426569451f601f.html