Reputation: 27
I've been working on this code for days and I am completely out of ideas for fixing it. No matter what I've done nothing changes with this runtime exception. How can I fix it? For context I'm trying to convert this Java code (The first code block) to RISC-V assembly code (the second code block). My error is occurring in line 76 of the assembly code (lw t0, 0(s0) # Load pivot 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
Upvotes: 1
Views: 187
Reputation: 26646
Let's do some analysis on the C code and implications on assembly:
public static void quickSort(int[] x, int n) { //Define quickSort method
qSort(x,0,n-1); //Call qSort method with appropriate parameters
}
Here we have:
x
, and n
— these defined upon entry (in a0
, and a1
) but only used once each within the body of quicksort
, and, both usages are before the call to qsort
, so they are "not live across a function call". Thus, you don't need stack memory or s
registers for them, so, just use them from their current location, to pass parameters to the qsort
call. The only register that must be preserved is the (hidden from C) ra
return address register, since the function call will repurpose that register — and ra
's original incoming value is how quicksort
will return to its caller (here main
). So, change the stack frame allocation code (function prologue) to save only ra
on entry and restore ra
upon stack frame release (function epilog).qsort(x,0,n-1)
. In order to call qsort
properly passing parameters, you must supply x
in a0
, 0
in a1
, and n-1
in a2
. Now, x
is already in a0
, so this requires no code; however, 0
is not in a1
, instead n
is in a1
. You can't put 0
there without wiping out n
, so before doing the required 0
in a1
first use it to compute and pass n-1
in a2
. That is one instruction: we can do a2 = n-1
, then after that you can zero a1
.Now let's turn to main
. Since the parameter registers are call-clobbered, and main
is using a0
as a pointer to the array, just reload that pointer (and counter as well) after the call to quicksort
. That should address all the issues in main
.
Upvotes: 1