我试图为在MEMU模拟的MIPS Malta电路板编写一些启动代码。
据我了解,马耳他电路板将4MB代码从闪存加载到物理RAM中的特定位置(0x1fc00000,即MIPS程序地址空间中的0xbfc00000:MIPS32复位中断位置)。我正在尝试生成将在此位置加载和运行的代码。
我有一个简单的汇编程序,它永远循环:
.text
_start:
b _start
当我用GNU汇编程序组装它时,我得到一个带有包含此代码的.text部分的ELF文件。用objdump拆解它:
Disassembly of section .text:
00000000 <_start>:
0: 1000ffff b 0 <_start>
4: 00000000 nop
...
使用链接描述文件我可以将.text部分重定位到0x8fc00000,此时反汇编产生:
Disassembly of section .text:
8fc00000 <_start>:
8fc00000: 1000ffff b 8fc00000 <_start>
8fc00004: 00000000 nop
...
由于ELF文件包含其他不可执行的部分,ELF标题等,我使用objcopy只转储文本部分:
mips-freebsd-objcopy -O binary --only-section .text boot.o.ld boot.bin
但是,由于分支操作数仍然是相对的,因此结果代码不使用绝对寻址并且分支到0x0而不是0x8fc00000:
% mips-freebsd-objdump -D -m mips -b binary boot.bin
boot.bin: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ffff0010 b 0x0
4: 00000000 nop
...
我徒劳地搜索了objcopy或ld的标志,它会将相对地址解析为输出中的绝对地址。有objcopy标志来操作节开始地址,但我相信这些只是改变了输出格式的偏移表,所以不会影响二进制输出(显然没有这样的表)。
到目前为止,我发现的唯一解决方法是在汇编源中添加.org指令:
.org 0x8fc00000
这可以理解地产生一个带有零的~2GB文件前置填充,但产生的代码具有绝对寻址,我可以将其删除。
有没有正确的方法呢?