这样我们就可以具体来了解这一段的具体意思了:romStart的连接地址是在ram所在的地址,而实际运行是在flash上(这是一段bootloader启动代码,上电运行是在flash中运行的),我们需要将romStart的地址换成在flash中的位置,所以该段代码先加上当前运行位置的地址,然后减去链接时生成的当前位置的地址,这样就得到实际运行时romStart的相对地址,这样就可以直接跳转过去了。
为什么是这样子的一个功能呢?我记得当时上网搜到了这样一段描述:
1. 执行bal之后,ra寄存器的值为0Xbfc0100c;
2. 执行la之后,t0寄存器存放的是romStart的链接地址。
3. 执行addu之后,t0寄存器存放的是0Xbfc0100c+romStart的链接地址。
4. 执行la之后,ra寄存器存放的是0xbfc01008的地址对应的链接地址。
5. 执行subu之后,t0寄存器存放的是0xbfc01008的地址对应的链接地址-(0Xbfc0100c+romStart),此时t0寄存器存放的即是romStart对应的ROM地址。
看了上面这段解释,总感觉有那么点的奇怪。难道最终计算出来的romStart在flash中的地址没有偏移4字节吗?
后来,我有幸接触到了Broadcom的CFE。它里面关于reloc的做法比较合理,很清晰,新手很容易就看明白。
参照上面的发法试着分析一下,是不是很容易?没有一点歧义吧?
对于vxWorks中存在的歧义,至今仍未参透,期待个中高手的指点了!
附:
何谓链接地址?凡是标号的值都是标号所在指令的链接地址(即RAM地址)。在分支指令中的标号所表示的值是一个相对于本分支指令地址的16bit的偏移量。汇编器会将标号所表示的有效地址(目标地址)转换成合适的偏移值放入指令中。在跳转指令中的标号所表示的值也是由汇编器将标号所在的有效地址(目标地址)转换成合适的偏移值,转换规则详见指令说明。
本文是在学习网络上一位博友的日志之后,有感所写,在此感谢一下他。
欢迎光临 Chinaunix (http://bbs.chinaunix.net/) | Powered by Discuz! X3.2 |