MIPS runtime error "line 31: Runtime exception at 0x00400038: address out of range 0x7fbffffc Go: execution terminated with errors."

34 views Asked by At

I am getting the error "line 31: Runtime exception at 0x00400038: address out of range 0x7fbffffc

Go: execution terminated with errors." whenever I input 2, when I input 3 it outputs 3, when I input 4 it outputs 4 instead of 8

the code is supposed to do

int Myfun (int N)
{
 if (N>3) return ( Myfun(N-2) + 2N );
 else return 0
}

my code is

          .data
input: .asciiz "Input: "
    .text
    .globl main
main:
    # Prompt user for input
    li $v0, 4
    la $a0, input
    syscall

    # Get user input
    li $v0, 5
    syscall
    move $a0, $v0

    # Call Myfun(N)
    jal Myfun

    # Print the result
    li $v0, 1
    syscall

    # Exit
    li $v0, 10
    syscall

Myfun:
    addi $sp, $sp, -8       # Reserve stack space for 2 items
    sw $ra, 4($sp)          # Save the return address
    sw $a0, 0($sp)          # Save the current value of N
    slti $t0, $a0, 3        # Test if N is less than 3
    beq $t0, $zero, Base_case     # If N < 3, jump to base_case
    addi $a0, $a0, -2       # Prepare the argument for the recursive 
    jal Myfun               # Recursive call
    lw $a0, 0($sp)          # After returning, load the original N
    add $t1, $a0, $a0     # Calculate 2N
    add $v0, $v0, $t1       # Add 2N to the result of the recursive 
    j Exit                  # Return from the function

Base_case:
    li $v0, 0         # Set the return value to 0 for the base case
    j Exit

Exit:
    lw $a0, 0($sp)
    lw $ra, 4($sp)          # Restore the return address
    addi $sp, $sp, 8        # Clean up the stack
    jr $ra                  # Return from the function
1

There are 1 answers

0
Erik Eidt On

You have two simple problems that can be identified by debugging.

First, in main you're printing $a0 instead of the return value from the function, which is in $v0.  So, in main after jal Myfun, you need to move $v0 (the return value) into $a0 for the syscall #1 to print an integer.

Second, in Myfun, you have reversed the if-statement condition so that the function won't converge when given an input less than 3 — classic stack overflow.

You have coded the following:

int Myfun (int N)
{
 if (N<3) return ( Myfun(N-2) + 2*N );
 else return 0;
}

Also, by the calling convention, there's no reason to reload $a0 in function epilog.

As you're doing, you do need to save $a0 at the beginning so that you can reload it (restore the N value) for the +2*N computation for your function's own benefit, but otherwise don't need to restore $a0 for the benefit of any callers, as $a0 is a call-clobbered register, so it would be inappropriate for callers to rely on that register having the same value after a function call as it might have before a function call (unless custom calling convention).