这是我用来在MIPS上进行快速排序的C代码,在火星编辑器上,运行这些代码时遇到问题
#include <stdio.h>
void QuickSort(int *array, int first, int last){
int q;
if (first<last){
int value = array[last];
int i = first-1;
int tmp;
int j = first;
while(j<=last){
if (array[j] <= value) {
i++;
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
j++;
}
q = i;
QuickSort(array,first,q-1);
QuickSort(array,q+1,last);
}
}
这是我到目前为止的MIPS翻译,我遇到无限循环
.data
numArray: 30, 15, 11, 40, 75, 80, 70, 60
first: 0
last: 7
.text
main:
la $a0, numArray
lw $a1, first
lw $a2, last
jal quick_sort
li $v0, 10
syscall
quick_sort:
subi $sp, $sp, 4 #reserving memory in the stack
sw $ra, 4($sp) #storing the return adress in the stack
xor $t0, $t0, $t0 #int q
bge $a1, $a2, label1 #if (first<last)
sll $t1, $a2, 2 #int value = array[last];
add $t1, $t1, $a0 #callculating array[last] in $t1
lw $t1, 0($t1) #array[last] = array direction + 4 * last
or $t2, $t1, $zero #$t2 will be value
subi $t3, $a1, 1 #int i = first-1;
xor $t4, $t4, $t4 #int tmp
or $t5, $a1, $zero #int j=first
j label2 #while(j<=last)
label3: sll $t6, $a2, 2 #calculating array[j] adress
add $t6, $t6, $a0
lw $t7, 0($t6) #calculating array[j] value
bgt $t7, $t1, label4 #if (array[j] <= value)
addi $t3, $t3, 1 #i++
sll $s0, $t3, 2 #calculating array[i] adress
add $s0, $s0, $a0
lw $s1, 0($s0) #calculating array[i] value
or $t4, $s1, $zero #tmp = array[i]
sw $t7, 0($s0) #array[i] = array[j];
sw $t4, 0($t6) #array[j] = tmp;
label4: addi $t5, $t5, 1 #end if; j++
label2: ble $t5, $a2, label3 #while condition
or $t0, $t3, $zero #q = i
lw $a1, first #first value on the second parameter
subi $a2, $t0, 1 #q-1
jal quick_sort #QuickSort(array,first,q-1)
addi $a1, $t0, 1 #q+1
lw $a2, last #last value on the third parameter
jal quick_sort #QuickSort(array,q+1,last);
label1: lw $ra, 4($sp) #Recovering the return address from the stack
addi $sp, $sp, 4 #releasing memory
jr $ra #going to the return address
也许我需要在堆栈中存储更多的东西,或者我缺少的东西,感谢您的帮助,在那里发现任何奇怪的东西,请让我知道进行检查。
答案 0 :(得分:2)
编辑:
正如Minn在评论中指出的那样,我错过了以下两行内容:
sll $t1, $a2, 2 #int value = array[last];
因此,尽管这一行与其中的注释不匹配,但该值的加载似乎是正确的。
END EDIT
我对这个特定的程序集不熟悉,但是问题似乎出在"register clobbering"上:
根据documentation jal
仅存储返回地址,但不存储任何寄存器。
lw $a1, first #first value on the second parameter
subi $a2, $t0, 1 #q-1
jal quick_sort #QuickSort(array,first,q-1)
addi $a1, $t0, 1 #q+1
lw $a2, last #last value on the third parameter
jal quick_sort
您将$t0
用作q
局部变量,但从未将其保存在堆栈中。
在第一次调用jal quick_sort #QuickSort(array,first,q-1)
之后,$ t0的值将有所不同,但是您会在addi $a1, $t0, 1 #q+1
行中立即使用它,就好像它从未改变过一样,然后将结果传递给第二个调用QuickSort
。
与此错误等效的C语言是使q
成为全局变量,并在函数的开头添加q = 0;
。
您必须记住,当在汇编中工作并为局部变量使用寄存器时,必须在从当前函数调用任何其他函数之前将它们的状态保存到堆栈中,否则您将丢失状态并且您的代码将无法按预期工作!
说实话,这是我第一次看到这种特殊的汇编语言,因此可能还会遗漏其他错误,但这是最明显的错误,因此很容易发现。