MIPS中这种快速排序有什么问题?

时间:2018-11-13 23:55:55

标签: c mips mips32

这是我用来在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

也许我需要在堆栈中存储更多的东西,或者我缺少的东西,感谢您的帮助,在那里发现任何奇怪的东西,请让我知道进行检查。

1 个答案:

答案 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;

您必须记住,当在汇编中工作并为局部变量使用寄存器时,必须在从当前函数调用任何其他函数之前将它们的状态保存到堆栈中,否则您将丢失状态并且您的代码将无法按预期工作!

说实话,这是我第一次看到这种特殊的汇编语言,因此可能还会遗漏其他错误,但这是最明显的错误,因此很容易发现。