我正在學習 MIPS,我正在嘗試用 MIPS 表達用 C 語言撰寫的代碼。
其中,在研究應該保留的暫存器的時候,我以為我是通過簡單的考慮暫存器的型別來決定是否保留它們的。
int leaf_example (int g, int h, int i , int j)
{
int f;
f = (g h)-(i j);
return f;
}
比如上面的代碼,有條件g~j是$a0~ a3,f是$s0,回傳值存放在$v0.
在這個時候,因為有問題的情況下,f存盤在$s和$s被保存的需求,所以我理解的是,值$s0被存盤在堆疊上,然后$s以后被恢復。
void sort(int v[],int n)
{
int i, j;
for (i = 0 i < n; i ){
for (j = i - 1; j >= 0 && v[j] > v[j 1]; j-=1){
swap(v, j);
}
}
}
但是,當有類似上面的代碼時,用MIPS表示如下:

Why is it that the two values ??that come in as arguments of the sort() function are stored separately and then used when they are not stored in $s? I don't know how to determine which registers should be preserved.
In the code above, I want to know why you need to preserve $a0 $a1. That said, I'd really appreciate it if you could tell me how to distinguish which values ??should be preserved in the code.
uj5u.com熱心網友回復:
在 C 或偽代碼中,我們有生命周期有限的邏輯變數,它們按作用域來來去去(例如區域變數和引數),而在匯編中我們有物理存盤。當我們將演算法翻譯成匯編語言時,我們必須將邏輯變數映射到物理存盤中。
為變數選擇的特定存盤必須滿足其生命周期和使用要求。根據軟體慣例,MIPS 將暫存器(物理存盤)細分為呼叫保留和呼叫破壞暫存器。
我們需要做的是對變數及其使用方式進行分析。您想回答以下問題:對于每個變數,它保存的值是否在函式呼叫之前定義,并在函式呼叫之后使用。如果任何變數的答案是肯定的,那么該變數必須存盤在一個保留的位置,該位置將在函式呼叫中幸存下來,并且這些位置要么是$s暫存器,要么是(本地)堆疊記憶體。但無論哪種方式,都涉及記憶體,直接在后一種情況下,在前一種情況下使用$s暫存器,必須保留這些暫存器本身以遵循約定。
該$s暫存器是有利的,并且可取的,如果代碼使用變數多次(通過動態計),這是常有與環路的情況。否則,如果變數僅使用一次(或在對性能而言意外或不重要的動態路徑上),例如,記憶體可能比$s暫存器更適合它們。
在第一個函式中,$s為區域變數使用暫存器是愚蠢的f——f應該進入$v0. 為什么?兩個原因:
$v0可用,并且不會被此函式從第一次使用f到最后一次使用所做的任何事情所破壞,并且,- 函式以 結束
return f;,這意味著在函式的末尾,f的值需要在 中$v0。
所以,把它放在第一位是有道理的,并且避免了使用$s暫存器的開銷,而且不需要$v0在最后復制進去。
在第二個函式中,它swap在回圈內部呼叫,因此,然后
- 假定函式呼叫會清除所有引數暫存器(它們是呼叫破壞集的一部分)
sort本身將消失,$a0并$a1作為進行該函式呼叫的引數傳遞部分。
變數i、j、v和n都在函式呼叫之前定義并在函式呼叫之后使用。 i 既是一種用法又是另一種定義i——變數應該在函式呼叫中存活下來。對于j--. v并且n都在函式進入時定義并重復使用,因此顯然它們也必須在swap函式呼叫中幸存下來(否則回圈的下一次迭代將不起作用)。
由于這 4 個變數使用相當頻繁,因此$s暫存器是很好的候選者,作為替代方案,記憶體將需要在回圈體中插入額外的加載和存盤。
權衡是$s在序言和尾聲中對暫存器進行一次保存和恢復,而不是在回圈體中進行加載和存盤,如果回圈執行多次,這是一個很好的交易。
當我們將邏輯變數映射到物理存盤時,這些不一定是永久的,因此有時邏輯變數“存在”(映射到)代碼的一個部分與另一部分不同的物理存盤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/313755.html
標籤:assembly mips cpu-registers calling-convention
上一篇:澄清TST指令-ARM匯編
