Skip to content

Commit

Permalink
加入術應有的編譯結果
Browse files Browse the repository at this point in the history
  • Loading branch information
MROS committed Oct 15, 2024
1 parent ccacbd1 commit 588043d
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 5 deletions.
4 changes: 2 additions & 2 deletions book/大品天仙訣之臆想.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

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

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

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

## 總訣用語風格

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

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

Expand Down
1 change: 0 additions & 1 deletion book/零.一版/剖析(語法分析).md
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,6 @@ fn 剖析變數宣告(&self, 游標: usize) -> Option<(O變數宣告, usize)>
let 游標 = self.消耗(游標, O詞::等號)?; // 若匹配不了 "=" ,短路返回 None
let (算式, 游標) = self.剖析算式(游標)?; // 若匹配不了 算式 ,短路返回 None

//
Some((O變數宣告 { 算式, 變數名 }, 游標))
}
```
Expand Down
124 changes: 123 additions & 1 deletion book/零.二版/精五真言生成(一)施術.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
#### 棧動態增長
也可以如零.一版一樣,一邊計算一邊把臨時結果壓入棧,實作可能簡單一些。但最終仍要把棧恢復到舊貌,也就是說仍然要記錄棧到底增長了多少,或者採用 `fp` 暫存器來記錄當下的棧底為多少。

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

使用 `fp` 的棧會形如:

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

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

## 術的真言形式
## 施術的真言形式

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

```assembly
甲:
# 四個區域變數+返回位址+舊 fp
# 總共 6 * 8 位元組 (64 位元系統)
addi sp, sp, -48
# 儲存返回地址
sd ra, 40(sp) # ra = return address = 返回地址
# 儲存舊棧底(fp)
sd s0, 32(sp) # s0 就是 fp
# 更新 s0(fp) 為現在的棧底
addi s0, sp, 48
// 初始化區域變數
li t0, 1 # t0 = 1
sd t0, -24(s0) # 元.天 = 1
sd t0, -32(s0) # 元.地 = 1
sd t0, -40(s0) # 元.玄 = 1
sd t0, -48(s0) # 元.黃 = 1
call 乙 # jal ra, 術乙
# 收尾
ld ra, -8(s0) # 恢復返回位址給暫存器 ra
mv sp, s0 # 歸還棧空間
ld s0, -16(s0) # 恢復 fp
ret # jr ra
乙:
# 四個區域變數+返回位址+舊 fp
# 總共 6 * 8 位元組 (64 位元系統)
addi sp, sp, -48
# 儲存返回地址
sd ra, 40(sp) # ra = return address = 返回地址
# 儲存舊棧底(fp)
sd s0, 32(sp) # s0 就是 fp
# 更新 s0(fp) 為現在的棧底
addi s0, sp, 48
// 初始化區域變數
li t0, 1 # t0 = 1
sd t0, -24(s0) # 元.宇 = 1
sd t0, -32(s0) # 元.宙 = 1
sd t0, -40(s0) # 元.洪 = 1
sd t0, -48(s0) # 元.荒 = 1
# 同零.一版用堆疊機來計算宇+宙+洪+荒
# 宇入棧
addi sp, sp, -8
ld t0, -24(s0)
sd t0, 0(sp)
# 宙入棧
addi sp, sp, -8
ld t0, -32(s0)
sd t0, 0(sp)
# 加
ld t1, 0(sp)
addi sp, sp, 8
ld t0, 0(sp)
add t0, t0, t1
sd t0, 0(sp)
# 洪入棧
addi sp, sp, -8
ld t0, -40(s0)
sd t0, 0(sp)
# 加
ld t1, 0(sp)
addi sp, sp, 8
ld t0, 0(sp)
add t0, t0, t1
sd t0, 0(sp)
# 荒入棧
addi sp, sp, -8
ld t0, -48(s0)
sd t0, 0(sp)
# 加
ld t1, 0(sp)
addi sp, sp, 8
ld t0, 0(sp)
add t0, t0, t1
sd t0, 0(sp)
# 答案在棧頂,將其載到 t1 暫存器
ld t1, 0(sp)
# 彈出計算結果後 sp 又回到術開始時的原本位置,棧大小恢復如初
addi sp, sp, 8
# 準備參數,施展外術「曰」
mv a0, t1
call 曰
# 收尾
ld ra, -8(s0) # 恢復返回位址給暫存器 ra
mv sp, s0 # 歸還棧空間
ld s0, -16(s0) # 恢復 fp
ret # jr ra
```
全在暫存器就算完了。

再來看看乙那段將宇、宙、洪、荒相加的算式,若編譯器好好優化,會怎麽計算:

```assembly
// 初始化區域變數
lw t1, -8(s0) # 「宇」載至t1
lw t2, -16(s0) # 「宙」載至t1
lw t3, -24(s0) # 「洪」載至t1
lw t4, -32(s0) # 「荒」載至t1
add t5, t1, t2 # t5 = 宇 + 宙
add t5, t5, t3 # t5 = t5 + 洪
add t5, t5, t4 # t5 = t5 + 荒
```
全在暫存器就算完了。
2 changes: 1 addition & 1 deletion book/零.二版/設計與概述.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,4 @@

## 法咒執行流程

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

0 comments on commit 588043d

Please sign in to comment.