我有这个RISC-V汇编程序:
addi x2,x0,5
addi x3,x0,12
addi x7,x3,-9
or x4,x7,x2
and x5,x3,x4
add x5,x5,x4
beq x5,x7,0x48
我想得到十六进制的汇编指令。格式加载到FPGA中。我通过执行以下命令获得这些值:
#!/bin/bash
# Given a source assembly file, assembly it and display
# the hex values for each instruction
SRC_FILE=$1
RV_AS=riscv64-unknown-elf-as
RV_OBJCOPY=riscv64-unknown-elf-objcopy
$RV_AS -o /tmp/gen_asm_instr.elf $SRC_FILE -march=rv32ima
$RV_OBJCOPY -O binary /tmp/gen_asm_instr.elf /tmp/gen_asm_instr.bin
xxd -e -c 4 /tmp/gen_asm_instr.bin | cut -d ' ' -f 2
如果我注释掉最后一个汇编指令(beq
),一切都可以工作。我得到以下结果:
00500113
00c00193
ff718393
0023e233
0041f2b3
004282b3
这是6条说明,一切正常。但是,如果取消最后一条指令的注释,就会得到:
00500113
00c00193
ff718393
0023e233
0041f2b3
004282b3
00729463
0000006f
这是8条指令。如果我"拆解"在上面,我得到:
Dis-assemble
# Create a file 'template.txt' with the above instructions:
00000000: 00500113 00c00193 ff718393 0023e233
00000010: 0041f2b3 004282b3 00729463 0000006f
# Use xxd and obdjump to recover the assembly instructions
xxd -r template.txt > a.out # generate a binary file
xxd -e a.out > a-big.txt # switch endianness
xxd -r ./a-big.txt > a2.out # generate a bin. file with the switched endianness
riscv64-unknown-elf-objdump -M no-aliases -M numeric -mabi=ilp32 -b binary -m riscv -D ./a2.out # dis-assemble it
结果:
./a2.out: file format binary
Disassembly of section .data:
0000000000000000 <.data>:
0: 00500113 addi x2,x0,5
4: 00c00193 addi x3,x0,12
8: ff718393 addi x7,x3,-9
c: 0023e233 or x4,x7,x2
10: 0041f2b3 and x5,x3,x4
14: 004282b3 add x5,x5,x4
18: 00729463 bne x5,x7,0x20
1c: 0000006f jal x0,0x1c
因此RISC-V汇编器将beq
指令转换为两个:bne
和jal
。
为什么会这样?我怎样才能避免呢?
编辑
我已经尝试在线汇编:
https://riscvasm.lucasteske.dev/
,同样发生
当为分支目标使用硬编码的数字地址时,构建系统似乎会这样做。无法解释为什么它选择这样做,但我会注意到jal
的范围(20位直接)比beq
(12位直接)远得多。由于bxx
和jal
都是相对于pc的,它们都不支持绝对寻址。汇编程序可能不知道代码将位于何处,因此给了您额外的范围以到达该绝对地址。
如果你使用一个标签作为分支目标,它不会在触手可及的范围内这样做。