0

我正在尝试为 MIPS Malta 板编写一些启动代码,在 QEMU 中进行仿真。

据我了解,马耳他板将 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 文件,但会产生具有绝对寻址的代码,我可以将其删除。

有没有正确的方法来做到这一点?

4

0 回答 0