MIPS 坏地址/异常

MIPS bad address/ Exception

该代码是一个递归块,用于计算一个数的阶乘。我在 PC 上遇到异常(文本地址错误)。我正在查看跟踪记录,但不确定真正的问题出在哪里,除了我的 PC 显示垃圾值这一事实。我在下面附上代码。

.data
    prompt: .asciiz "Enter the n"
.text
    main:
        #User I/O
        li $v0, 4
        la $a0, prompt
        syscall
        li $v0, 5
        syscall
        add $a0, $v0, $zero
        jal fact
        j finish
    fact:
        addi $sp, $sp, -8  #adding two elements (reserve space), since stacks start from higher mem address
        sw $ra, 0($sp)
        sw $a0, 4($sp)

        slti $t0, $a0, 1
        beq $t0, $zero, loop

        addi $sp, $sp, 8
        addi $v0, $zero, 1

        jr $ra

    loop:
        addi $a0, $a0, -1
        jal fact    #stores address of the lw instruction and goes to label-->fact

    lw $a0, 0($sp)
    lw $ra, 4($sp)
    addi $sp, $sp, 8 #deleting 2 elements

    mul $v0, $v0, $a0
    jr $ra #until main ra, recursively go through fact(n)=fact(n-1)*n

    finish:

使用的模拟器:QtSpim

感谢任何帮助。谢谢!如果有帮助,我还会附加 PC 和寄存器值。 Register values at the time of the error

使用调试器单步执行,找出 lw $ra, 4($sp) 时出了什么问题,以及 实际上 使用 jr $ra 加载和跳转的内容。该指令只是跳转到 $ra 中的任何地址,并且最有可能将 PC 设置为伪造的地址。

您似乎将 $ra 保存到 0($sp),但从 4($sp) 恢复了它,因此您交换了 arg 和 return 地址。

此外,您的 main 根本没有在输入时保存其 $ra,因此您将无法从 main 中 return。你在保存$ra之前运行一个jal,所以只有save/restore在fact里面(它的定义和main混在一起了?别不要那样做。不要跳过另一个函数的定义,只需将代码从 main 放入 return 或在 main 的底部进行退出系统调用。)

此外,当您 j finish 时,您可能会崩溃,这会从您的程序末尾掉落到非指令中。