为什么静态链接时要指定地址?
背景: 闪存为 0x02000000/2M,SDRAM 为 0x10000/16M,处理器:ks8695。
Bootloader和OS被烧入Flash,复位时,OS被复制到SDRAM地址0x10000处,然后将PC(程序计数器)设置为0x10000(即运行OS)。
既然PC设置为0x10000(因为此时处理器可以执行操作系统的第一条指令),为什么在链接时需要指定操作系统文本部分的绝对地址(通过设置-Ttext=0x10000) ? (当我将-Ttext设置为0x0时,操作系统将无法正常运行)。
最好的问候,
wenlujon
background:
flash at 0x02000000/2M, SDRAM at 0x10000/16M, processor: ks8695.
the Bootloader and OS are burned into the flash, when resetting, OS is copied to SDRAM at address 0x10000, then set PC(program counter) to 0x10000 (that is, run the OS).
since the PC is set to 0x10000(since the processor can execute the first instruction of OS at this point), why is it necessary to specify the absolute address of the Text Section of the OS(through setting -Ttext=0x10000) when linking it? (when I set -Ttext to 0x0, the OS won't run properly).
Best regards,
wenlujon
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为您已经回答了自己的问题 - 您系统中的 RAM 位于 0x10000。执行代码的两种主流方式是存储下载(SnD)和就地执行(XIP)。看起来您将代码存储在闪存中并将其复制到 RAM 中。因此,二进制文件中的所有地址都必须与 RAM 起始地址偏移,否则二进制文件中的地址将是错误的。
如果您的闪存是 NOR,从技术上讲,您可以将其保留为 NOR 并就地运行代码 (XIP),尽管它可能不适合您的平台。
这有帮助吗?
I think you sort of answered your own question - the RAM in your system is located at 0x10000. The two mainstream ways of executing code are store-and-download (SnD) and eXecute-in-place (XIP). It seems like you're storing the code in flash and copying it to RAM. So all the addresses in your binary must be offset with the RAM start address, otherwise they will be wrong in the binary.
If your flash is NOR you could technically leave it in NOR and run the code in place (XIP) though it may not be suitable for your platform.
Does that help?
你的电脑位于 0x10000,因此你必须将其链接到 0x10000,因为你的代码正在执行绝对寻址。
引导加载程序不执行任何链接或符号解析,它只是将一些二进制 blob 复制到 0x10000,然后将 PC 设置为 0x10000。因此,您的代码必须准备好在 0x10000 处运行,这就是您需要在链接器中指定这一点的原因。
函数调用通常使用 PC 相对寻址来完成,但当您想要访问数据时则不必这样做。假设你有一个表T。如果你链接在0x0,而你的表在0x1234。您可能有一些引用此地址的说明。
现在您将代码移至 0x10000。你的表地址现在是 0x11234,但是你的代码现在还没有移动它,所以它尝试在 0x1234 处加载数据,那里什么也没有,或者是废话。
现在,当您使用偏移量链接代码时,用于访问 T 的指令集会相应地修改。这就是链接的全部用途,将符号解析为地址!
Your PC is at 0x10000, so you have to link it at 0x10000, because your code is doing absolute addressing.
The bootloader is not doing any linking or symbol resolution, it is just copying some binary blob to 0x10000 and then setting the PC to 0x10000. So your code has to be prepared to run at 0x10000, that is why you need to specify this in the linker.
function call are usually done using PC relative addressing, but this is not necessary the case when you want to have access to data. Assume you have a table T. If you are linked at 0x0, and your table is at 0x1234. You may have some instruction that refer to this address.
Now you move your code to 0x10000. Your table address is now 0x11234, but your code does not now it has been moved, so it tries to load data at 0x1234, where there is nothing, or crap.
Now when you link your code with an offset, the set of instruction that was used to access T is modified accordingly. That is all what linking is for, resolving symbol into adrresses !
是的,绝对寻址是一个很好的理由,但是第一条指令呢?它不应该与绝对寻址有任何关系。
假设操作系统的第一条指令是0xe1a00000,则操作系统偏移量0x10000处的指令是0xe3a01303。如果-Ttext设置为0x0,通过查看映射文件,我们在地址0x0处得到0xe1a00000,在地址0x10000处得到0xe3a01303(目标板中的CPU仍然不知道这一点!)。
当引导加载程序将操作系统复制到地址0x10000时,它会将0xe1a00000复制到0x10000,将0xe3a01303复制到0x20000(它们只是数据),我对吗?
然后将PC设置为0x10000,CPU应该执行0xe1a00000,因为该指令占用地址0x10000,但CPU实际上执行的是地址0x20000处的0xe3a01303。
yes, absolute addressing is a good reason, but what about the first instruction? It should not have anything to do with absolute addressing.
given the first instruction of the OS is 0xe1a00000, the instruction at offset 0x10000 of the OS is 0xe3a01303. if -Ttext is set to 0x0, by looking into the map file, we get 0xe1a00000 at address 0x0, 0xe3a01303 at address 0x10000 (CPU in the target board still does not know this at all!).
when bootloader copies the OS to the address 0x10000, it will copies 0xe1a00000 to 0x10000 and 0xe3a01303 to 0x20000(they are nothing but data), am I right?
then set PC to 0x10000, CPU should execute 0xe1a00000 because the instruction occupies the address 0x10000, but CPU actually executes 0xe3a01303 which is at address 0x20000.