【发布时间】:2016-11-16 03:49:55
【问题描述】:
以下 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' 也和之前和之后的不一样,我们得到-1,这绝对是错误的!
知道跳跃偏移是如何被破坏的吗?我需要为链接器指定一些额外的选项以正确处理偏移量吗?我找不到任何明显的东西,作为 Linux 和 GNU 的初学者,我被困住了。
【问题讨论】: