Search code examples
assemblyrecursionstackfibonaccimips32

MIPS Assembly - Fibonacci Registers


I am writing a recursive Fib function for MIPS. I need help understanding the $a0 register. I want to call the function with n-1, and n-2, but after you call it with n-1, the $a0 register changes. So say you want fib(2), even though after it jal's, it should keep the original value of 2, however it is still 1 from the n-1 call before. And 1-2 = -1, which makes it endless. I have tried loading $a0 before I call n-2, but that also throws everything off. Here is the code. Thank you

# switch to the Text segment
.text
# the program is defined here

.globl  main
main:


add $a0, $zero, 2
add $a1, $zero, 0
jal fib

j print_end


fib:
addi    $sp, $sp, -12
sw  $ra, 0($sp)
sw  $a0, 4($sp)
sw  $a1, 8($sp)

addi    $t5, $zero, 1
beq $a0, $zero, end_fib
beq $a0, $t5, end_fib
j   not_base
end_fib:
addi    $v0, $a0, 0     #base return 0 or 1
addi    $sp, $sp, 12
jr  $ra


not_base:
addi    $a0, $a0, -1
jal fib
addi    $a1, $v0, 0 #a1 = fib(n-1)
addi    $a0, $a0, -2
jal fib

b_k:
lw  $ra, 0($sp)
lw  $a0, 4($sp)
lw  $a1, 8($sp)
add $v0, $v0, $a1           #fibn = fib n-1 + fib n-2
addi    $sp, $sp, 12
jr  $ra

print_end:
addi    $a0,$v0, 0
jal Print_integer


bottom:

la  $a0, done   # mark the end of the program
jal Print_string

jal Exit0   # end the program, default return status


.data
# global data is defined here




.text

.globl  Print_integer
Print_integer:  # print the integer in register $a0 (decimal)
li  $v0, 1
syscall
jr  $ra

Solution

  • There's no need to save and restore $a0 in the middle of the function. You're saving/restoring $a0 upon entry/exit, so when fib(n-1) returns $a0 will be n-1, so to get n-2 you just subtract 1 again:

    # In:  $a0 = n
    # Out: $v0 = fib(n)
    fib:
        addiu $sp,$sp,-8
        sw $a0,0($sp)
        sw $ra,4($sp)
    
        sltiu $t0,$a0,2
        beq $t0,$zero,recurse
    
        # Base case: return n
        move $v0, $a0
        j return
    
    recurse:
        # Compute fib(n-1)
        addiu $a0,$a0,-1
        jal fib
    
        # Save fib(n-1) on the stack    
        addiu $sp,$sp,-4
        sw $v0,($sp)
    
        # Compute fib(n-2)
        addiu $a0,$a0,-1
        jal fib
    
        # Return fib(n-1) + fib(n-2)
        lw $t0,($sp)
        addiu $sp,$sp,4
        addu $v0,$v0,$t0
    
    return:
        lw $ra,4($sp)
        lw $a0,0($sp)
        addiu $sp,$sp,8
        jr $ra