@@ -248,7 +248,38 @@ fn 計算(
248248 }
249249}
250250```
251+ ### 計算施術
251252
252253相比零.一版,此處增加了一種算式——` 施術 ` ,依然可用堆疊機來完成,先分別計算各個實參,將實參的值壓入棧中,等實參都計算完畢後,將實參值載入參數暫存器後,施術(call)。
253254
254- ### 計算施術
255+ ``` rust
256+ // 結束時,棧頂 = t0 = 術的歸值
257+ fn 施術(真言檔: & mut File , 術: & O施術, 符號表: & O符號表) -> io :: Result <()> {
258+ writeln! (真言檔, " # 施展「{}」" , 術. 術名)? ;
259+
260+ assert! (術. 實參. len () <= 8 , " 音界咒暫不支援超過八個術參" );
261+
262+ // 將參數計算結果逐一推入棧中
263+ // NOTE: 不可將計算結果直接賦值給暫存器
264+ // 因其下個參數的計算過程中,可能又會汙染掉參數暫存器
265+ for 參數 in & 術. 實參 {
266+ // 任何計算完成後,棧會擴大一個字長
267+ // 計算結果會被置於棧頂
268+ Self :: 計算(真言檔, 參數, 符號表)? ;
269+ }
270+ // 將參數從棧中逐一載入參數暫存器
271+ for 編號 in (0 .. 術. 實參. len ()). rev () {
272+ writeln! (真言檔, " \ t ld a{}, 0(sp)" , 編號)? ;
273+ writeln! (真言檔, " \ t addi sp, sp, 8" )? ; // 將參數計算結果彈出
274+ }
275+
276+ writeln! (真言檔, " \ t call {}" , 術. 術名)? ;
277+
278+ // 歸值放回 t0
279+ writeln! (真言檔, " \ t mv t0, a0" )? ;
280+ writeln! (真言檔, " \ t addi sp, sp, -8" )? ; // 增加棧 64 位元的空間
281+ writeln! (真言檔, " \ t sd t0, 0(sp)" ) // t0 放入棧頂
282+ }
283+ ```
284+
285+ 至此,術的編譯大致講解完畢,部分與零.一版重複的程式碼就先不貼上來了。若有興趣,可直接參考[ 音界咒源碼] ( https://github.com/MROS/yinjie-lang/blob/3c6389823284722338642e3de672ef48d8e8ac9e/%E9%9B%B6%E8%99%9F%E7%B7%A8%E8%AD%AF%E5%99%A8/src/%E7%9C%9F%E8%A8%80%E7%94%9F%E6%88%90/%E7%9C%9F%E8%A8%80%E7%94%9F%E6%88%90%E5%99%A8.rs ) 。
0 commit comments