※ 引述《LinoYo (Lino)》之銘言:
: 不好意思,請教一下大家有關於下面這張圖片
: https://imgur.com/a/ufbOMwC
: 第一個問題是在問說錯的地方在哪裡,以及如何修正
: 請問一下須修正的地方是哪裡?
: 是否為第6、7行的$v0、$v1來存,為了給call funtion f的caller用嗎
: 還有第2行及第9行的lw、sw似乎可以不必要?
: 第二個問題問說此assembly code轉成C code寫出來且funtion f是什麼意思
: 有看沒有懂。
: 麻煩各位指點指點,謝謝!
手機排版請見諒。有點久沒唸計算機組織,有錯的話還請鞭小力一點
MIPS 不同字母開頭的暫存器有不同使用慣例,比如有一些暫存器的數值要 caller 自己保管,不然 callee 可能會把它用掉。有些則是 callee 有責任要維護好。我目前發現的問題有:
1. sp 不應該存在 ra:因為使用 jal 指令呼叫 f 時,會自動把呼叫完 f 之後的下個指令存在 ra ,你把它用 sp 蓋掉, jr ra 後就會把廢棄的 stack 裡面的東西當指令用(但那裡面存的是垃圾)。
2. 但 sp 也是 callee 要維護的暫存器。所以應該要把 sp 在記憶體裡,而不是 ra 中。在 epilogue 的時候從記憶體裡面回復到 sp。
2. 但 sp 也是 callee 要維護的暫存器。所以應該要把 sp 在記憶體裡,而不是 ra 中。在 epilogue 的時候從記憶體裡面回復到 sp。
3. callee 有責任維護 $s0 ~ $s7 暫存器,使 caller 看到的 $s 暫存器們的內容呼叫前後是一樣的,但 f 並沒有做到這件事(他直接去改 $s0 跟 $s1)所以還少了「 prologue 時把 $s 們的內容塞進記憶體, epilogue 時
第二個問題問「什麼樣的 C 程式會被組譯成上面那段組合語言」。但這個問題變數有點多,因為不太能斬釘截鐵地說編譯器一定會編出什麼東西來。但我會猜 function body 是這樣:
f(...){return foo(foo(a,b), c+d);}
其中一個想法是裡面並沒有區域變數,如果隨便宣告一個整數暫存 c + d 的話,可能就會需要對 stack 做一些事。但顯然組譯結果裡面沒有任何對 stack 的動作。
但這還是有一個問題,C99 規格書中並沒有指定 function parameter 的計算順序,所以編譯出來的結果也可能會是先算 foo(a,b), 再算 c + d。所以也許有比這個更好的作法啦。