這是我撰寫的嘗試在 mips 中實作 c 磁區函式的代碼。似乎有一個錯誤,因為該程式不起作用,但我找不到它在哪里。我知道最好除錯它,但我不知道如何除錯。另外我對存盤和恢復暫存器有點困惑,也許問題就在那里。
此外,我在 Visual Studio 中安裝了 mips 程式集除錯器,但應用程式無法識別它,而且 mips 似乎沒有其他選項。
partition:
#int partition(int f, int l) {
# int pivot = v[l];
# int i = f;
# for (int j = f; j < l; j )
# if (v[j] < pivot)
# swap(i ,j);
# swap(i, l );
# return (i);
#}
addi $sp, $sp, -24 #make room for 6
sw $a0, 0($sp) #store f
sw $a1, 4($sp) #store l
sw $ra, 8($sp) #store return address
sw $t2, 12($sp) #store i
#sw $t3, 16($sp) #store j
sw $t1, 16($sp) #store pivot
sw $s0, 20($sp) #store s0
la $s0, v # s0 = address of v
sll $t0, $a1, 2 # t0 = 4*l
add $t0, $s0, $t0 # t0 = address of v[l]
lw $t1, 0($t0) # t1 = v[l], t1 = pivot
move $t2, $a0 # t2 = i, t2 is f
move $t3, $a0 # t3 = j, t3 is f
for1:
slt $t4, $t3, $a1 #if(j<l) t4=1
beq $t4, $zero, end1 #goto end1 if t4 = 0
sll $t4, $a0, 2 # t4 = 4*j
add $t4, $s0, $t4 #t4 = address of v[j]
lw $t5, 0($t4) #t5 = v[j]
slt $t6, $t5, $t1 # if (v[j] < pivot) t6=1 else t6=0
bne $t6, $zero, else
move $a0, $t2 #a0 = i
move $a1, $t3 # a1 = j
jal swap # swap(i ,j);
addi $t2, $t2,1 # i
else:
addi $t3, 1 #j
j for1
#here stops the for1 loop
end1: #come here when exiting the for1 loop
# a0=f & a1=l
move $a0, $t2 #a0 = i
lw $a1, 4($sp) #a1= l
jal swap
move $v0, $a0 #v0=i / return i
lw $ra, 8($sp) #restore ra
lw $s0, 20($sp) #restore s0
lw $a0, 0($sp) #restore a0
lw $a1, 4($sp) #restore a1
#lw $s1, 4($sp) #restore s1
addi $sp, $sp, 24 #restore stack
jr $ra
uj5u.com熱心網友回復:
另外我對存盤和恢復暫存器有點困惑,也許問題就在那里。
是的,您的暫存器用法與標準呼叫約定不同。我們看不到您的磁區函式的呼叫者,也看不到該swap函式,因此我們無法評論它們。
根據 MIPS 呼叫約定,$s如果函式使用暫存器中的任何一個,則必須在回傳給呼叫者之前保留/恢復其原始值。相比之下,其他暫存器($a, $t, $v)不需要這樣保存,因此可以自由使用而無需進一步考慮。
$s暫存器對于保存在具有函式呼叫的回圈中使用的變數很有用。這是因為允許函式呼叫清除非$s暫存器,但必須保留$s暫存器。因此,存盤在$s暫存器中的變數將在函式呼叫中繼續存在。
暫存器的替代方案$s是堆疊記憶體,因為它也可以在函式呼叫中存活。要使用堆疊記憶體,我們必須存盤和重新加載,這對于非回圈非重復代碼是可以的,但對于回圈代碼,這些加載和存盤代表開銷。
相比之下,$s暫存器也被存盤和加載,但每次函式呼叫只存盤一次,而不是在函式體中。因此,如果函式體有回圈,那么在 prologue/epilogue 中進行加載和存盤比在函式體內進行加載和存盤更有效。
因此,經驗法則是:如果有函式呼叫但沒有回圈,請考慮堆疊記憶體用于需要在函式呼叫中存活的變數。如果沒有函式呼叫,則不要使用$s暫存器。如果有回圈或大量函式呼叫,請考慮$s為需要在函式呼叫中幸存的變數使用暫存器。
您需要能夠分析變數在函式呼叫中是否存在。分析是:變數中保存的值是否在函式呼叫之前存在/存在,然后在函式呼叫之后使用?如果是這樣,該變數必須在函式呼叫中存活下來,因此必須使用堆疊記憶體或$s暫存器。
您正在$t為函式呼叫回圈中使用的變數使用暫存器——這是不正確的,并且可能是一個問題(我們看不到swap,所以不能肯定地說)。
您還在序言中保留(并在結語中恢復)不值得保留的暫存器,這是浪費但在其他方面無害。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/472522.html
下一篇:裝配-計算算術平均值-分段錯誤
