From 588043df2f694a452fda71471c84fb756902fd21 Mon Sep 17 00:00:00 2001 From: MROS Date: Tue, 15 Oct 2024 19:53:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E8=A1=93=E6=87=89=E6=9C=89?= =?UTF-8?q?=E7=9A=84=E7=B7=A8=E8=AD=AF=E7=B5=90=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...43\344\271\213\350\207\206\346\203\263.md" | 4 +- ...25\345\210\206\346\236\220\357\274\211.md" | 1 - ...00\357\274\211\346\226\275\350\241\223.md" | 124 +++++++++++++++++- ...10\350\210\207\346\246\202\350\277\260.md" | 2 +- 4 files changed, 126 insertions(+), 5 deletions(-) diff --git "a/book/\345\244\247\345\223\201\345\244\251\344\273\231\350\250\243\344\271\213\350\207\206\346\203\263.md" "b/book/\345\244\247\345\223\201\345\244\251\344\273\231\350\250\243\344\271\213\350\207\206\346\203\263.md" index f117f77..2efb965 100644 --- "a/book/\345\244\247\345\223\201\345\244\251\344\273\231\350\250\243\344\271\213\350\207\206\346\203\263.md" +++ "b/book/\345\244\247\345\223\201\345\244\251\344\273\231\350\250\243\344\271\213\350\207\206\346\203\263.md" @@ -4,7 +4,7 @@ 轉念一想,或許「大品天仙訣」早已是成品也說不定,著訣前輩刻意僅寫就百餘字的總訣,指明修真離塵之綱要,而具體內容則留待道友共同補完。 -思及此處,貧道心頭一熱,憶起早年蓬萊修行,派中良師寥寥,益友難尋,縱有勇猛精進之心,終究事倍功半,作詩一首,暫且按下不表: +思及此處,貧道心頭一熱,憶起昔年蓬萊修道時,派中良師寥寥,益友難尋,縱有勇猛精進之心,終究事倍功半,作詩一首,暫且按下不表: > 少日曾懷凌雲志,欲就神術探源頭。煉氣十年出鄉里,泊舟萬里到帝州。一國精英齊聚首,六載光陰盡發朽。出得蓬門滿涕淚,已是人間第九流。 @@ -12,7 +12,7 @@ ## 總訣用語風格 -總訣原文可見於[此處](https://github.com/immortal-formula/immortal-formula),不再複述。原文是在試圖提出一種學習計算機科學的法門,其行文風格偏向文言文,但夾雜許多現代用語,欲仿古卻畫虎不成反類犬,這固然有著訣前輩古文功底不夠的成分,拖不了關係的還有:當今計算機科學源於西方,引入華夏後,諸多術語難以凝練漢語表示, +總訣原文可見於[此處](https://github.com/immortal-formula/immortal-formula),不再複述。原文是在試圖提出一種學習計算機科學的法門,其行文風格偏向文言文,但夾雜許多現代用語,欲仿古卻畫虎不成反類犬,這固然有著訣前輩古文功底不夠的成分,脫不了關係的還有:當今計算機科學源於西方,引入華夏後,諸多術語難以凝練漢語表示, 而前輩顯然察覺到了這個問題,甚至提出了自己的一套解決方法:引進修道、修仙的用語,重載其語義來適配計算機科學,這些用語似乎未必出自道家典籍,還雜揉了網路小說的設定。如此用語,是難以與從英語直譯過來的術語一一對應,然而細思又覺巧妙,若計算機科學濫觴於漢地,其用語本就該與今日大相徑庭,並與漢字結合更加緊密,入詩詞歌賦都會簡易得多。 diff --git "a/book/\351\233\266\357\274\216\344\270\200\347\211\210/\345\211\226\346\236\220\357\274\210\350\252\236\346\263\225\345\210\206\346\236\220\357\274\211.md" "b/book/\351\233\266\357\274\216\344\270\200\347\211\210/\345\211\226\346\236\220\357\274\210\350\252\236\346\263\225\345\210\206\346\236\220\357\274\211.md" index 4b3d0c7..3ad4430 100644 --- "a/book/\351\233\266\357\274\216\344\270\200\347\211\210/\345\211\226\346\236\220\357\274\210\350\252\236\346\263\225\345\210\206\346\236\220\357\274\211.md" +++ "b/book/\351\233\266\357\274\216\344\270\200\347\211\210/\345\211\226\346\236\220\357\274\210\350\252\236\346\263\225\345\210\206\346\236\220\357\274\211.md" @@ -346,7 +346,6 @@ fn 剖析變數宣告(&self, 游標: usize) -> Option<(O變數宣告, usize)> let 游標 = self.消耗(游標, O詞::等號)?; // 若匹配不了 "=" ,短路返回 None let (算式, 游標) = self.剖析算式(游標)?; // 若匹配不了 算式 ,短路返回 None - // Some((O變數宣告 { 算式, 變數名 }, 游標)) } ``` diff --git "a/book/\351\233\266\357\274\216\344\272\214\347\211\210/\347\262\276\344\272\224\347\234\237\350\250\200\347\224\237\346\210\220\357\274\210\344\270\200\357\274\211\346\226\275\350\241\223.md" "b/book/\351\233\266\357\274\216\344\272\214\347\211\210/\347\262\276\344\272\224\347\234\237\350\250\200\347\224\237\346\210\220\357\274\210\344\270\200\357\274\211\346\226\275\350\241\223.md" index 98475ae..26f3285 100644 --- "a/book/\351\233\266\357\274\216\344\272\214\347\211\210/\347\262\276\344\272\224\347\234\237\350\250\200\347\224\237\346\210\220\357\274\210\344\270\200\357\274\211\346\226\275\350\241\223.md" +++ "b/book/\351\233\266\357\274\216\344\272\214\347\211\210/\347\262\276\344\272\224\347\234\237\350\250\200\347\224\237\346\210\220\357\274\210\344\270\200\357\274\211\346\226\275\350\241\223.md" @@ -71,6 +71,8 @@ #### 棧動態增長 也可以如零.一版一樣,一邊計算一邊把臨時結果壓入棧,實作可能簡單一些。但最終仍要把棧恢復到舊貌,也就是說仍然要記錄棧到底增長了多少,或者採用 `fp` 暫存器來記錄當下的棧底為多少。 +臨時增長棧也會導致用 `sp` 來索引區域變數的位址會不太穩定,以 `fp` 來索引實作會比較容易。(棧臨時增長時,`sp`動,但`fp`不動) + 使用 `fp` 的棧會形如: ![精五棧圖解](../image/精五棧圖解fp.png) @@ -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 + 荒 +``` +全在暫存器就算完了。 diff --git "a/book/\351\233\266\357\274\216\344\272\214\347\211\210/\350\250\255\350\250\210\350\210\207\346\246\202\350\277\260.md" "b/book/\351\233\266\357\274\216\344\272\214\347\211\210/\350\250\255\350\250\210\350\210\207\346\246\202\350\277\260.md" index 5d2cba3..ca18e75 100644 --- "a/book/\351\233\266\357\274\216\344\272\214\347\211\210/\350\250\255\350\250\210\350\210\207\346\246\202\350\277\260.md" +++ "b/book/\351\233\266\357\274\216\344\272\214\347\211\210/\350\250\255\350\250\210\350\210\207\346\246\202\350\277\260.md" @@ -136,4 +136,4 @@ ## 法咒執行流程 -編譯時應可指定第一個要施展的術的名字,若無指定,便先行施展`初`術。若檔案中無`初`術,執行最後一個宣告的`術`。若一個術都沒定義,編譯後的執行檔將直接結束。 +編譯時應可指定第一個要施展的術的名字,若無指定,便先行施展`初`術。若檔案中無`初`術,編譯失敗。