我已经研究这个代码好几天了,但我完全没有修复它的想法。无论我做什么,这个运行时异常都不会发生任何变化。我该如何修复它? 对于上下文,我尝试将此 Java 代码(第一个代码块)转换为 RISC-V 汇编代码(第二个代码块)。我的错误发生在汇编代码的第 76 行(lw t0, 0(s0) # Load hub value)。
//declare an array Y1 and its length lenY1
static int Y1[] = {13, 101, 79, 23, 154, 4, 11, 38, 88, 45, 17, 94, 62, 1};
static int lenY1 = 14;
public static void main(String[] args) { //Define main method
quickSort(Y1, lenY1); //Call quickSort method
for (int i = 0; i<lenY1; i++) //Loop for printing
System.out.print(Y1[i] + " ");
System.out.println("\n"); //Print the sorted array
}
public static void quickSort(int[] x, int n) { //Define quickSort method
qSort(x,0,n-1); //Call qSort method with appropriate parameters
}
public static void qSort(int x[], int left, int right) { //Define qSort method
int middle;
if (left < right) { //Loop for sorting If left is less than right
middle = partition(x, left, right); //middle = partition(x, left, right)
qSort(x, left, middle); //qSort(x, left, middle)
qSort(x, middle+1, right); //qSort(x, middle+1, right)
}
}
public static int partition(int x[], int left, int right) { //Define partition method
int pivot, l, r, temp; //Load arguments
pivot = x[left]; //Choose pivot
l = left-1; //Initialize variables
r = right+1;
while (true) { //Loop partition
do {r--;} while (x[r] > pivot); //Loop right
do {l++;} while (x[l] < pivot); //Loop left
if (l < r) { //Swap
temp = x[l];
x[l] = x[r];
x[r]= temp;
}
else
return r;
}
}
}
# Declare Y1 array
.data
Y1: .word 13, 101, 79, 23, 154, 4, 11, 38, 88, 45, 17, 94, 62, 1
lenY1: .word 14
SortedMsg: .asciz "\nSorted Array: \n"
.text
main:
# Call quickSort on Y1
la a0, Y1 # Load address of Y1 into a0
lw a1, lenY1 # Load length of Y1 into a1
jal ra, quickSort # Call quickSort
# Print Y1
li a2, 0 # Initialize index to 0
print_loop:
slli t0, a2, 2 # Multiply index by 4
add t0, t0, a0 # Add to base address of Y1
lw a0, 0(t0) # Load element into a0
li a7, 1 # Print integer ecall
ecall
addi a2, a2, 1 # Increment index
blt a2, a1, print_loop # Loop if index less than length
# Exit
li a7, 10 # Exit ecall
ecall
quickSort:
addi sp, sp, -16 # Allocate stack space
sw ra, 0(sp) # Save return address
sw s0, 4(sp) # Save s0
sw s1, 8(sp) # Save s1
sw s2, 12(sp) # Save s2
mv s0, a0 # Save array address
mv s1, a1 # Save length
jal ra, qSort # Call qSort
lw ra, 0(sp) # Restore return address
lw s0, 4(sp) # Restore s0
lw s1, 8(sp) # Restore s1
lw s2, 12(sp) # Restore s2
addi sp, sp, 16 # Deallocate stack space
ret # Return
qSort:
mv s2, a0 # Save array address
mv s0, a1 # Save left index
mv s1, a2 # Save right index
blt s0, s1, qsort_done # If left greater than or equal to right, done
jal ra, partition # Call partition
mv a0, s2 # Pass array address
mv a1, s0 # Pass left index
mv a2, a0 # Pass partition index
jal ra, qSort # Recursive call on left
mv a0, s2 # Pass array address
mv a1, a0 # Pass partition index
addi a2, a0, 1 # Pass right index
mv s1, a2
jal ra, qSort # Recursive call on right
qsort_done:
ret # Return
partition:
mv s0, a0 # Save array address
mv s1, a1 # Save left index
mv s2, a2 # Save right index
lw t0, 0(s0) # Load pivot value **This is the error line**
mv a0, t0 # Save pivot in a0
mv t1, s1 # Initialize i to left index
partition_loop:
blt t1, s2, partition_done # If i greater than or equal to right, done
lw t2, 0(s0) # Load arr[i]
bgt t2, a0, if_greater # If arr[i] greater than pivot, branch
addi t1, t1, -1 # Increment i
j partition_loop # Loop
if_greater:
lw t3, 0(s1) # Load arr[j]
blt t3, a0, if_less # If arr[j] less than pivot, branch
mv t4, t1 # t4 = i
addi t4, t4, -1 # t4 = i - 1
slli t5, t4, 2 # t5 = 4 * (i -1)
add t5, t5, s0 # t5 = &arr[i-1]
lw t5, 0(t5) # Load arr[i-1]
sw t3, 0(s1) # arr[j] = arr[i-1]
sw t5, 0(t4) # arr[i-1] = arr[j]
addi t1, t1, -1 # Decrement i
j partition_loop # Loop
if_less:
addi t1, t1, 1 # Decrement i
j partition_loop # Loop
partition_done:
mv a0, t1
ret # Return
让我们对 C 代码及其对汇编的影响进行一些分析:
public static void quickSort(int[] x, int n) { //Define quickSort method
qSort(x,0,n-1); //Call qSort method with appropriate parameters
}
我们有:
x
和 n
— 这些是在输入时定义的(在 a0
和 a1
中),但在 quicksort
的主体中仅使用一次,并且,两种用法都是在调用之前 之前到 qsort
,所以它们“不在函数调用中存在”。因此,您不需要堆栈内存或 s
寄存器,因此,只需从当前位置使用它们,将参数传递给 qsort
调用。唯一必须保留的寄存器是(在 C 中隐藏的)ra
返回地址寄存器,因为函数调用将重新调整该寄存器的用途,而 ra
的原始传入值就是 quicksort
将如何返回到其调用者(这里main
)。因此,更改堆栈帧分配代码(函数序言)以仅在入口时保存 ra
并在堆栈帧释放时恢复 ra
(函数序言)。qsort(x,0,n-1)
。为了调用 qsort
正确传递参数,您必须在 x
中提供 a0
,在 0
中提供 a1
,在 n-1
中提供 a2
。现在,x
已经在a0
中,所以这不需要代码;但是,0
不在 a1
中,而是 n
在 a1
中。您无法将 0
放在那里而不擦除 n
,因此在 0
中执行所需的 a1
之前,首先使用它来计算并将 n-1
传递到 a2
中。这是一条指令:我们可以执行 a2 = n-1
,然后您可以归零 a1
。现在让我们转向
main
。由于参数寄存器是调用破坏的,并且 main
使用 a0
作为指向数组的指针,因此只需在调用 quicksort
后重新加载该指针(以及计数器)即可。这应该可以解决main
中的所有问题。