![](/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.