需要 RISCV 链接器来处理 JAL 偏移量

Need RISCV linker to handle JAL offsets

下面的RISC-V汇编代码(RV32)用来说明问题。

start:    jal end
end:      jal start

我使用以下简单命令调用汇编程序...

riscv32-unknown-elf-as -m32 example.s -o example.o

为了检查生成的代码,我反汇编了它...

riscv32-unknown-eft-objdump -D example.o

给出以下输出...

00000000 <start>:
    0:  004000ef    jal 4 <end>

00000004 <end>
    4:  ffdff0ef    jal 0 <start>

第一个'jal'已经正确指出需要在PC上加4才能跳转到下一行地址4。(注意:立即数的奇数布局jal 指令意味着实际值指令编码 2,然后在 CPU 处将其乘以 2 以获得实际偏移量 4)。第二个 'jal' 的偏移量为 -2。同样,CPU 乘以 2 我们可以 -4 作为偏移量。

我实际上想生成一个原始输出文件,它不包含 ELF 信息并且仅由 8 个字节组成,这 8 个字节构成了两条指令。我 运行 直接反对微控制器,而微控制器不是 运行 操作系统。我希望将输出闪存到非易失性 RAM,然后在复位时执行。

所以我使用以下链接器命令生成二进制输出...

riscv32-unknown-elf-ld --oformat=binary example.o -o example

但这似乎丢失了相对寻址值,因为使用以下命令查看生成的输出字节...

xxd example

...给出以下结果...

00000000:  ef00 0000 eff0 ffff

考虑到它是小端字节序,这意味着与之前看到的反汇编相比,每组四个字节的顺序相反。我们可以看到第一个跳转 '000000ef' 已经失去了它的跳转偏移量。第二跳'fffff0ef' 也和应用twos compliment 前后不同,我们得到-1,这肯定是错误的!

知道跳跃偏移量是如何损坏的吗?我需要向链接器指定一些额外的选项来正确处理偏移量吗?我找不到任何明显的东西,作为 Linux 和 GNU 的初学者,我被困住了。

事实证明链接器中存在错误,解决方法是使用...

riscv32-unknown-elf-objcopy -O binary example.o example