Skip to content

Commit 71679b1

Browse files
committed
零.一版編譯目標:精五門(RISC-V)真言極簡子集
1 parent 4cd8164 commit 71679b1

2 files changed

Lines changed: 108 additions & 3 deletions

File tree

book/.vitepress/config.mts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,31 @@ export default defineConfig({
1818
items: [
1919
{ text: "大品天仙訣之臆想", link: "/大品天仙訣之臆想" },
2020
{ text: "序・去往新世界", link: "/序・去往新世界" },
21-
{ text: "離塵第一步:自舉", link: "/離塵第一步:自舉" }
21+
{ text: "離塵第一步:自舉", link: "/離塵第一步:自舉" },
2222
],
2323
},
2424
{
2525
text: "金丹概覽",
2626
items: [
2727
{ text: "什麼語言容易自舉", link: "/什麼語言容易自舉" },
28-
{ text: "結丹流程概覽(通用編譯流程)", link: "/結丹流程概覽(通用編譯流程)" },
28+
{
29+
text: "結丹流程概覽(通用編譯流程)",
30+
link: "/結丹流程概覽(通用編譯流程)",
31+
},
2932
],
3033
},
3134
{
3235
text: "音界咒零.一版",
3336
items: [
34-
{ text: "音界咒零.一版設計與定義", link: "/音界咒零.一版設計與定義" },
37+
{
38+
text: "音界咒零.一版設計與定義",
39+
link: "/音界咒零.一版設計與定義",
40+
},
3541
{ text: "全形字體選擇", link: "/全形字體選擇" },
42+
{
43+
text: "零.一版編譯目標:精五門(RISC-V)真言極簡子集",
44+
link: "/零.一版編譯目標:精五門(RISC-V)真言極簡子集",
45+
},
3646
],
3747
},
3848
],
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
音界咒的編譯目標是精五門(RISC-V)真言,精五門真言本就十分精簡,在零.一版,更是僅需要
2+
3+
- 整數加減乘除
4+
- 指定暫存器的值
5+
6+
等寥寥幾個指令而已。
7+
8+
但在介紹這些指令之前,先來寫個最簡單的範例,並讓它動起來。
9+
10+
## 實驗環境架設
11+
12+
絕大部分的人手邊都沒有精五架構的板子,需要先安裝交叉編譯器跟精五模擬器(本作選擇使用 qemu)。
13+
14+
## 返回 100
15+
16+
以下是貧道所能構造的最簡易的範例,它一啟動就以 100 當結束碼關閉程序:
17+
18+
```assembly
19+
.section .text
20+
.global _start
21+
22+
_start:
23+
li a7, 93 # RISCV Linux 中 exit 系統呼叫編號是 93
24+
li a0, 100 # a0 是函數呼叫時,第一個參數位置
25+
ecall # 執行系統呼叫 exit(100)
26+
```
27+
將之命名為 `100.S`
28+
29+
### 編譯、執行
30+
```
31+
riscv64-unknown-elf-gcc -nostdlib 100.S # 編譯後應得 a.out 檔案
32+
qemu-riscv64 a.out # qemu-riscv64 並非單單模擬裸機,還實作了部分系統呼叫
33+
echo $? # 可以看到上一個程序的結束碼是 100
34+
```
35+
36+
## 整數加減乘除
37+
38+
```assembly
39+
add 目標, 源1, 源2
40+
sub 目標, 源1, 源2
41+
mul 目標, 源1, 源2
42+
div 目標, 源1, 源2
43+
```
44+
45+
以上就是加減乘除四個指令了,此處的目標、源1、源2,都是暫存器的名字。精五(RISC-V)有 32 個整數通用暫存器,在零.一版的編譯目標中,僅使用臨時暫存器 t0 ~ t6 就可以了。
46+
47+
除了讓暫存器跟暫存器加減乘除,精五也支援讓暫存器與(12位)立即數做加運算。
48+
49+
```assembly
50+
addi 目標, 源, 立即數
51+
```
52+
53+
由於立即數可以寫負數,就不支援減立即數的操作了,畢竟加上一個負數就等同於減。
54+
55+
## 指定暫存器的值
56+
57+
```
58+
li 目標, 立即數 # 將目標暫存器的值設為立即數
59+
mv 目標, 源 # 將目標暫存器的值設為源暫存器的值
60+
```
61+
62+
`li``mv` 都是偽指令,也就是說,在組譯階段,指令會被變成一到多個真實指令。
63+
64+
例如當立即數可用 12 位元表示時,`li 目標, 立即數` 會被譯為 `addi 目標, x0, 立即數`。其中 `x0` 是一個特殊的唯獨暫存器,其值永遠為 0。
65+
66+
`mv 目標, 源` 會被譯為 `addi 目標, 源, 0`
67+
68+
## 音界咒編譯實例
69+
70+
```音界
71+
元.甲=(1+3)*4
72+
甲+1
73+
```
74+
編譯出的精五真言,其結束碼為音界咒中最後一行的值,在上述範例中,即是「甲+1」的值。
75+
76+
77+
```assembly
78+
.section .text
79+
.global _start
80+
81+
_start:
82+
li t0, 1 # t0 = 1
83+
li t1, 3 # t1 = 3
84+
add t0, t0, t1 # t0 = t0 + t1
85+
86+
li t1, 4 # t1 = 4
87+
mul t0, t0, t1 # t0 = t0 * t1
88+
addi t0, t0, 1 # t0 = t0 + 1
89+
90+
li a7, 93 # RISCV Linux 中 exit 系統呼叫編號是 93
91+
mv a0, t0 # a0 = t0
92+
ecall # 執行系統呼叫 exit(t0)
93+
```
94+
95+
試著編譯執行看看,並驗證結束碼是否是 17。

0 commit comments

Comments
 (0)