【发布时间】:2021-12-18 09:27:24
【问题描述】:
我正在设计自己的 RISC-V CPU,并且已经能够实现一些指令代码。
我已经安装了 GCC 编译器的 RV32I 版本,所以我现在可以使用汇编器 riscv32-unknown-elf-as。
我正在尝试用一条指令组装一个程序:
# simple.asm
add x5,x6,x7
我用汇编器编译它,然后用这个命令运行 objdump:
riscv32-unknown-elf-as simple.asm -o simple
riscv32-unknown-elf-objdump -D simple
这会打印出以下内容:
new: file format elf32-littleriscv
Disassembly of section .text:
00000000 <.text>:
0: 007302b3 add t0,t1,t2
Disassembly of section .riscv.attributes:
00000000 <.riscv.attributes>:
0: 2d41 jal 0x690
2: 0000 unimp
4: 7200 flw fs0,32(a2)
6: 7369 lui t1,0xffffa
8: 01007663 bgeu zero,a6,0x14
c: 00000023 sb zero,0(zero) # 0x0
10: 7205 lui tp,0xfffe1
12: 3376 fld ft6,376(sp)
14: 6932 flw fs2,12(sp)
16: 7032 flw ft0,44(sp)
18: 5f30 lw a2,120(a4)
1a: 326d jal 0xfffff9c4
1c: 3070 fld fa2,224(s0)
1e: 615f 7032 5f30 0x5f307032615f
24: 3266 fld ft4,120(sp)
26: 3070 fld fa2,224(s0)
28: 645f 7032 0030 0x307032645f
我的问题是:
- 这是怎么回事?我想我应该有一个简单的单行十六进制,但还有很多事情要做。
- 如何指示我的处理器开始读取某个内存地址的指令?看起来 objdump 也不知道指令从哪里开始。
为了清楚起见,我现在将我的处理器视为裸机。我想象我将在处理器中硬编码指令从内存地址 X 开始,数据在内存地址 Y 可用,堆栈在内存地址 Z 可用。这是正确的吗?或者这是错误的方法?
【问题讨论】:
-
实际的 CPU 本身会有一些硬连线地址,它会在复位/上电时从中获取。通常系统会在该物理地址处设计有 ROM 或闪存。 (并且可能有一个 ELF 程序加载器的代码,它将尊重 ELF 入口点元数据,或者您可以在二进制文件的开头将一个平面二进制文件与正确的代码链接。)
-
@PeterCordes - 谢谢!是否可以将我上面编译的文件原样传递给我的处理器?如果是,我需要进行哪些更改才能让它从正确的内存地址获取指令?
-
objdump -D反汇编 所有 ELF 部分,而不仅仅是.text。如您所见,.text部分中只有一条指令,如果您使用了objdump -d,这就是您所看到的。 (我通常使用objdump -drwC,虽然-w可能与RISC-V 无关) -
是否可以将我在上面编译的文件按原样传递给我的处理器? - 不是您可能想的那样。另请注意,您为输出选择了错误的文件名。
as生成一个目标文件(通常是.o),而不是可执行文件。您可以将ld链接到平面二进制文件中,或者将objcopy链接到其中的 .text 部分。 (理论上,您可以将整个 ELF 可执行文件甚至目标文件放入 ROM 中,这样 .text 部分恰好从 CPU 获取的位置开始,但不会查看元数据字节。 -
@PeterCordes - 我明白了,我想我看错了。我以为
as会生成最终的二进制文件,但根据您的说法,我需要使用ld为我的处理器生成文件或使用objcopy将相关位复制到正确的地址。对吗?
标签: assembly cpu-architecture elf riscv riscv32