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
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