现在我正在努力理解RISC-V ISA,但我对机器代码和程序集有一点不清楚。
我写了一个这样的C代码:
int main() {
return 42;
}
然后,我通过以下命令生成了.s文件:
$ /opt/riscv/bin/riscv64-unknown-linux-gnu-gcc -S 42.c
输出为:
.file "42.c"
.option nopic
.text
.align 1
.globl main
.type main, @function
main:
addi sp,sp,-16
sd s0,8(sp)
addi s0,sp,16
li a5,42
mv a0,a5
ld s0,8(sp)
addi sp,sp,16
jr ra
.size main, .-main
.ident "GCC: (g5964b5cd727) 11.1.0"
.section .note.GNU-stack,"",@progbits
现在,我运行以下命令来生成一个精灵。
$ /opt/riscv/bin/riscv64-unknown-linux-gnu-gcc -nostdlib -o 42 42.s
因此,生成了一个二进制文件。我试着用objdump这样读:
$ /opt/riscv/bin/riscv64-unknown-linux-gnu-objdump -d 42
所以输出是这样的:
42: file format elf64-littleriscv
Disassembly of section .text:
00000000000100b0 <main>:
100b0: 1141 addi sp,sp,-16
100b2: e422 sd s0,8(sp)
100b4: 0800 addi s0,sp,16
100b6: 02a00793 li a5,42
100ba: 853e mv a0,a5
100bc: 6422 ld s0,8(sp)
100be: 0141 addi sp,sp,16
100c0: 8082 ret
我不明白的是objdump输出中机器代码的含义。例如,根据该页面,第一条指令addi
被翻译成.....0010011
(尽管这不是官方规范(。但是,转储的十六进制是1141
。1141
只能表示2个字节,但指令应该是32位,4个字节。
我想我遗漏了一些点,但我应该如何读取riscv的objdump的输出?
您可以告诉objdump以这种方式使用-M no-aliases
来显示压缩(16位(指令
riscv64-unknown-elf-objdump -d -M no-aliases
在这种情况下,以c.
开头的指令是压缩指令。
不幸的是,这也会禁用其他一些别名,如果你习惯了它们,就会使asm读起来不那么好看。您只需查看hexdump中的字节数(2对4(,就可以判断它是否是压缩指令。