Skip to content

Commit 588043d

Browse files
committed
加入術應有的編譯結果
1 parent ccacbd1 commit 588043d

File tree

4 files changed

+126
-5
lines changed

4 files changed

+126
-5
lines changed

book/大品天仙訣之臆想.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
轉念一想,或許「大品天仙訣」早已是成品也說不定,著訣前輩刻意僅寫就百餘字的總訣,指明修真離塵之綱要,而具體內容則留待道友共同補完。
66

7-
思及此處,貧道心頭一熱,憶起早年蓬萊修行,派中良師寥寥,益友難尋,縱有勇猛精進之心,終究事倍功半,作詩一首,暫且按下不表:
7+
思及此處,貧道心頭一熱,憶起昔年蓬萊修道時,派中良師寥寥,益友難尋,縱有勇猛精進之心,終究事倍功半,作詩一首,暫且按下不表:
88

99
> 少日曾懷凌雲志,欲就神術探源頭。煉氣十年出鄉里,泊舟萬里到帝州。一國精英齊聚首,六載光陰盡發朽。出得蓬門滿涕淚,已是人間第九流。
1010
1111
畢業矣,方悟得法、財、侶、地缺一不可,欲再從頭是不可能了,然而今日洽逢良機,發奮著同人書,若能裨益道友修行之「法」,乃至識得同修之「侶」,吾心甚慰。
1212

1313
## 總訣用語風格
1414

15-
總訣原文可見於[此處](https://github.com/immortal-formula/immortal-formula),不再複述。原文是在試圖提出一種學習計算機科學的法門,其行文風格偏向文言文,但夾雜許多現代用語,欲仿古卻畫虎不成反類犬,這固然有著訣前輩古文功底不夠的成分,拖不了關係的還有:當今計算機科學源於西方,引入華夏後,諸多術語難以凝練漢語表示,
15+
總訣原文可見於[此處](https://github.com/immortal-formula/immortal-formula),不再複述。原文是在試圖提出一種學習計算機科學的法門,其行文風格偏向文言文,但夾雜許多現代用語,欲仿古卻畫虎不成反類犬,這固然有著訣前輩古文功底不夠的成分,脫不了關係的還有:當今計算機科學源於西方,引入華夏後,諸多術語難以凝練漢語表示,
1616

1717
而前輩顯然察覺到了這個問題,甚至提出了自己的一套解決方法:引進修道、修仙的用語,重載其語義來適配計算機科學,這些用語似乎未必出自道家典籍,還雜揉了網路小說的設定。如此用語,是難以與從英語直譯過來的術語一一對應,然而細思又覺巧妙,若計算機科學濫觴於漢地,其用語本就該與今日大相徑庭,並與漢字結合更加緊密,入詩詞歌賦都會簡易得多。
1818

book/零.一版/剖析(語法分析).md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,6 @@ fn 剖析變數宣告(&self, 游標: usize) -> Option<(O變數宣告, usize)>
346346
let 游標 = self.消耗(游標, O詞::等號)?; // 若匹配不了 "=" ,短路返回 None
347347
let (算式, 游標) = self.剖析算式(游標)?; // 若匹配不了 算式 ,短路返回 None
348348

349-
//
350349
Some((O變數宣告 { 算式, 變數名 }, 游標))
351350
}
352351
```

book/零.二版/精五真言生成(一)施術.md

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
#### 棧動態增長
7272
也可以如零.一版一樣,一邊計算一邊把臨時結果壓入棧,實作可能簡單一些。但最終仍要把棧恢復到舊貌,也就是說仍然要記錄棧到底增長了多少,或者採用 `fp` 暫存器來記錄當下的棧底為多少。
7373

74+
臨時增長棧也會導致用 `sp` 來索引區域變數的位址會不太穩定,以 `fp` 來索引實作會比較容易。(棧臨時增長時,`sp`動,但`fp`不動)
75+
7476
使用 `fp` 的棧會形如:
7577

7678
![精五棧圖解](../image/精五棧圖解fp.png)
@@ -83,7 +85,127 @@ gcc 可以用 `-fomit-frame-pointer` 來調控是否採用 `fp` 的棧形式,`
8385

8486
不過要計算臨時變數也挺麻煩,先以記錄 `fp` 的方式來實作施術吧。
8587

86-
## 術的真言形式
88+
## 施術的真言形式
8789

8890
來看看上述的甲、乙兩術翻成真言會是什麼樣子:
8991

92+
```assembly
93+
甲:
94+
# 四個區域變數+返回位址+舊 fp
95+
# 總共 6 * 8 位元組 (64 位元系統)
96+
addi sp, sp, -48
97+
# 儲存返回地址
98+
sd ra, 40(sp) # ra = return address = 返回地址
99+
# 儲存舊棧底(fp)
100+
sd s0, 32(sp) # s0 就是 fp
101+
# 更新 s0(fp) 為現在的棧底
102+
addi s0, sp, 48
103+
104+
// 初始化區域變數
105+
li t0, 1 # t0 = 1
106+
sd t0, -24(s0) # 元.天 = 1
107+
sd t0, -32(s0) # 元.地 = 1
108+
sd t0, -40(s0) # 元.玄 = 1
109+
sd t0, -48(s0) # 元.黃 = 1
110+
111+
call 乙 # jal ra, 術乙
112+
113+
# 收尾
114+
ld ra, -8(s0) # 恢復返回位址給暫存器 ra
115+
mv sp, s0 # 歸還棧空間
116+
ld s0, -16(s0) # 恢復 fp
117+
ret # jr ra
118+
119+
120+
乙:
121+
# 四個區域變數+返回位址+舊 fp
122+
# 總共 6 * 8 位元組 (64 位元系統)
123+
addi sp, sp, -48
124+
# 儲存返回地址
125+
sd ra, 40(sp) # ra = return address = 返回地址
126+
# 儲存舊棧底(fp)
127+
sd s0, 32(sp) # s0 就是 fp
128+
# 更新 s0(fp) 為現在的棧底
129+
addi s0, sp, 48
130+
131+
// 初始化區域變數
132+
li t0, 1 # t0 = 1
133+
sd t0, -24(s0) # 元.宇 = 1
134+
sd t0, -32(s0) # 元.宙 = 1
135+
sd t0, -40(s0) # 元.洪 = 1
136+
sd t0, -48(s0) # 元.荒 = 1
137+
138+
# 同零.一版用堆疊機來計算宇+宙+洪+荒
139+
140+
# 宇入棧
141+
addi sp, sp, -8
142+
ld t0, -24(s0)
143+
sd t0, 0(sp)
144+
145+
# 宙入棧
146+
addi sp, sp, -8
147+
ld t0, -32(s0)
148+
sd t0, 0(sp)
149+
150+
# 加
151+
ld t1, 0(sp)
152+
addi sp, sp, 8
153+
ld t0, 0(sp)
154+
add t0, t0, t1
155+
sd t0, 0(sp)
156+
157+
# 洪入棧
158+
addi sp, sp, -8
159+
ld t0, -40(s0)
160+
sd t0, 0(sp)
161+
162+
# 加
163+
ld t1, 0(sp)
164+
addi sp, sp, 8
165+
ld t0, 0(sp)
166+
add t0, t0, t1
167+
sd t0, 0(sp)
168+
169+
# 荒入棧
170+
addi sp, sp, -8
171+
ld t0, -48(s0)
172+
sd t0, 0(sp)
173+
174+
# 加
175+
ld t1, 0(sp)
176+
addi sp, sp, 8
177+
ld t0, 0(sp)
178+
add t0, t0, t1
179+
sd t0, 0(sp)
180+
181+
# 答案在棧頂,將其載到 t1 暫存器
182+
ld t1, 0(sp)
183+
# 彈出計算結果後 sp 又回到術開始時的原本位置,棧大小恢復如初
184+
addi sp, sp, 8
185+
186+
# 準備參數,施展外術「曰」
187+
mv a0, t1
188+
call 曰
189+
190+
# 收尾
191+
ld ra, -8(s0) # 恢復返回位址給暫存器 ra
192+
mv sp, s0 # 歸還棧空間
193+
ld s0, -16(s0) # 恢復 fp
194+
ret # jr ra
195+
196+
```
197+
全在暫存器就算完了。
198+
199+
再來看看乙那段將宇、宙、洪、荒相加的算式,若編譯器好好優化,會怎麽計算:
200+
201+
```assembly
202+
// 初始化區域變數
203+
lw t1, -8(s0) # 「宇」載至t1
204+
lw t2, -16(s0) # 「宙」載至t1
205+
lw t3, -24(s0) # 「洪」載至t1
206+
lw t4, -32(s0) # 「荒」載至t1
207+
add t5, t1, t2 # t5 = 宇 + 宙
208+
add t5, t5, t3 # t5 = t5 + 洪
209+
add t5, t5, t4 # t5 = t5 + 荒
210+
```
211+
全在暫存器就算完了。

book/零.二版/設計與概述.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,4 @@
136136

137137
## 法咒執行流程
138138

139-
編譯時應可指定第一個要施展的術的名字,若無指定,便先行施展``術。若檔案中無``術,執行最後一個宣告的``。若一個術都沒定義,編譯後的執行檔將直接結束
139+
編譯時應可指定第一個要施展的術的名字,若無指定,便先行施展``術。若檔案中無``術,編譯失敗

0 commit comments

Comments
 (0)