第 76 行中的 RISC-V 汇编错误:0x004000bc 处的运行时异常:地址超出范围 0x00000000

问题描述 投票:0回答:1

我已经研究这个代码好几天了,但我完全没有修复它的想法。无论我做什么,这个运行时异常都不会发生任何变化。我该如何修复它? 对于上下文,我尝试将此 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

java assembly runtime-error riscv rars-simulator
1个回答
0
投票

让我们对 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
中的所有问题。

© www.soinside.com 2019 - 2024. All rights reserved.