![](/img/trans.png)
[英]How can I resolve RISC-V assembly pseudo instructions to true RISC-V instructions?
[英]Bare metal RISC-V CPU - how does the processor know which address to start fetching instructions from?
我正在设计自己的 RISC-V CPU,并且已经能够实现一些指令代码。
我已经安装了 RV32I 版本的 GCC 编译器,所以我现在可以使用汇编程序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
我的问题是:
明确地说,此时我将我的处理器视为裸机。 我想象我将在处理器中硬编码指令从内存地址 X 开始,数据在内存地址 Y 处可用,堆栈在内存地址 Z 处可用。这是正确的吗? 或者这是错误的方法?
处理器如何知道从哪个地址开始获取指令?
实际的 CPU 本身会有一些硬连线地址,它可以在复位/上电时从中获取。 通常,系统会在该物理地址处设计有 ROM 或闪存。 (并且可能有一个 ELF 程序加载器的代码,它将尊重 ELF 入口点元数据,或者您可以在二进制文件的开头将一个平面二进制文件与正确的代码链接起来。)
这里发生了什么? 我以为我会有一个简单的单行十六进制,但还有很多事情要做。
您的objdump -D
反汇编所有 ELF 部分,而不仅仅是 .text。 如您所见,.text 部分中只有一条指令,如果您使用了 objdump -d,您会看到这样的内容。 (我通常使用objdump -drwC
,尽管-w
no line-wrapping 可能与 RISC-V 无关,不像 x86,其中单个 insn 可能很长。)
是否可以将我上面编译的文件按原样传递给我的处理器?
不是你想的那样。 另请注意,您为输出选择了错误的文件名。 as 生成目标文件(通常为 .o),而不是可执行文件。 您可以将ld
链接到一个平面二进制文件中,或者将objcopy
的.text
部分链接和objcopy
。
(理论上,您可以将整个 ELF 可执行文件甚至目标文件放入 ROM 中,这样.text
部分恰好从 CPU 获取的位置开始,但不会查看元数据字节。因此,ELF 入口点地址元数据在ELF 可执行文件将无关紧要。)
.o
和可执行文件之间的区别:a .o
只有重定位元数据供链接器填充实际地址,绝对用于la
伪指令,或相对用于auipc
的情况,例如多个.o
文件,其中一个文件从其他。 (否则可以在组装时计算相对位移,而不是在链接时计算。)
因此,如果您的代码使用任何内存地址标签,则需要链接器在代码中填写这些重定位条目。 然后你可以从链接的 ELF 可执行文件中objcopy
一些部分。 或者使用链接器脚本来设置平面二进制文件的布局。
对于只有add
,没有la
或任何内容的简单情况,没有重定位条目,因此.o
的文本部分与链接的可执行文件中的相同。
使用objcopy
也很棘手的是静态数据,例如.data
和.bss
部分。 如果您仅将.text
部分复制到平面二进制文件,则在任何地方都不会有数据。 (但在 ROM 中,您需要一个启动函数,将.data
静态初始值设定项从 ROM 复制到 RAM,并将.bss
空间归零。如果您想编写 asm 源以具有正常外观的.data
部分非零值,您希望您的构建脚本计算出要复制的大小,以便您的启动函数可以使用它,而不必手动执行所有这些操作。)
@PeterCordes 的回答让我走上了正确的道路。 我终于想出了如何生成我可以使用的原始内存转储文件。
步骤如下:
修改了程序集文件以具有.text
和.data
部分以及_start
标签。 我的simple.asm
文件现在如下所示:
.globl _start .text _start: add x5,x6,x7 .data L1: .word 27
使用以下命令将.asm
组装到.o
文件:
riscv32-unknown-elf-as simple.asm -o simple.o
为特定处理器创建链接描述文件。 我关注了这个惊人的视频,该视频介绍了从头开始创建链接器脚本的过程。 现在,我只需要.text
和.data
部分。 所以我的链接器脚本( mycpu.ld
)如下所示:
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv") ENTRY(_start) MEMORY { DATA (rwx) : ORIGIN = 0x0, LENGTH = 0x80 INST (rx) : ORIGIN = 0x80, LENGTH = 0x80 } SECTIONS { .data : { *(.data) }> DATA .text : { *(.text) }> INST }
使用riscv32-unknown-elf-gcc
生成 ELF 文件,它会自动调用riscv32-unknown-elf-ld
:
riscv32-unknown-elf-gcc -nostdlib -T mycpu.ld -o simple.elf simple.o
从.elf
文件创建一个原始二进制或十六进制文件,我将用它来填充内存的内容。
riscv32-unknown-elf-objcopy -O binary simple.elf simple.hex
最终的simple.hex
包含以下内容(使用hexyl
):
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 1b 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │•0000000┊00000000│
│00000010│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000020│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000030│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000040│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000050│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000060│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000070│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000080│ b3 02 73 00 ┊ │וs0 ┊ │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
其中b3027300
是add x5,x6,x7
的十六进制值。
就是这样! 非常感谢@PeterCordes 的帮助! :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.