位置无关是加载时的概念,而不是运行时的概念。位置无关是一种代码质量,它允许将其加载到内存中的任何地址并且仍然可以工作,但位置无关不是正在运行的程序的质量。
一旦我们有一个调用堆栈和/或(重新定位的)数据引用代码,我们就不再具有代码或数据的位置独立性并且无法移动它们。实际上,当程序开始执行时,位置独立性就消失了(尽管有位置独立的代码)。
返回地址(通过调用(例如BL
)动态生成)以及指向代码的数据指针(代码指针向量(如在 vtables 中)和初始化的全局函数指针)都会破坏正在运行的程序的位置独立性。
作者的警示节点是描述位置独立性消失的一种方式。更令人困惑的是,通过非常小心的操作,即使代码的执行已经开始,它们也允许实际移动代码,所以这里我们的位置独立性实际上在执行开始后持续了一小段时间。
但是一个程序如果不放弃位置独立性就不能正常运行(例如调用和使用函数指针),所以他们选择在low_level_init
.
例如,reset
代码很长地使用非标准调用来调用low_level_init
- 为它提供一个lr
值而不使用BL
or mov lr,pc
(这将捕获 的预重映射(ROM)地址cstartup
。)lr
提供的值是地址的(搬迁)cstartup
将low_level_init
“返回”!
(10) LDR r0,=_reset /* pass the reset address as the 1st argument */
(11) LDR r1,=_cstartup /* pass the return address as the 2nd argument */
(12) MOV lr,r1 /* set the return address after the remap */
(13) LDR sp,=__stack_end__ /* set the temporary stack pointer */
(14) B low_level_init /* relative branch enables remap */
_cstartup:
B
与 the 相结合的是MOV lr,r1
调用。