我正在开发一个程序,它使用堆栈帧来递归地调用函数,以帮助计算fibonnacci序列的第n项。这是我目前所拥有的,但输出(程序停止运行时,它将位于寄存器$t7中)返回1。这是我目前的进展
.text
.globl main
main:
li $v0, 4
la $a0, prompt
syscall
li $v0, 5
syscall
addiu $sp, $sp, -4
sw $t0, ($sp)
addiu $sp, $sp, -4
sw $t1, ($sp)
addiu $sp, $sp, -4 # space for parameters
sw $v0, ($sp) # pushing parameter
jal fib
addiu $sp, $sp, 4
lw $t1, ($sp)
addiu $sp, $sp, 4
lw $t0, ($sp)
addiu $sp, $sp, 4
move $t7, $v0
li $v0, 10
syscall
fib:
addiu $sp, $sp, -4
sw $ra, ($sp)
addiu $sp, $sp, -4
sw $fp, ($sp)
addiu $sp, $sp, -4
sw $s0, ($sp)
addiu $sp, $sp, -4
sw $s1, ($sp)
addiu $fp, $sp, -8
move $sp, $fp
lw $t3, 24($fp) # t3 = n of fib(int n)
move $s0, $t3
li $v0, 1 # return value
ble $s0, 1, epilog #
addi $s0, $s0, -1 # setting up fib(n-1)
jal fib
move $s0, $v0 # store fib(n-1)
addi $s0, $s0, -2 # set up fib(n-2)
jal fib
add $v0, $s1, $v0 # add fib(n-1) and fib(n-2)
epilog:
addiu $sp, $fp, 8 #
lw $s1, ($sp)
addiu $sp, $sp, 4
lw $s0, ($sp)
addiu $sp, $sp, 4
lw $fp, ($sp)
addiu $sp, $sp, 4
lw $ra, ($sp)
jr $ra
li $v0, 10
syscall
.data
prompt: .asciiz "enter a number dingus \n"
我觉得这是我的递归函数在身体的子例程,但我一直盯着这个过去几个小时,仍然不知道我做错了什么,任何提示将不胜感激,谢谢。
1条答案
按热度按时间gmxoilav1#
第一次输入
fib
时,在函数序言中压入寄存器后,堆栈如下所示:这张图表并没有在任何地方被标准化,但是它是我喜欢用来可视化函数的堆栈帧的工具。
然后,函数从
24(fp)
加载$s0
,24(fp)
对应于开始时推的$t0
。这一切都很好,但fib(n-1)
的情况会发生什么?函数被再次调用,第二次执行序言。现在堆栈如下所示:你现在看到问题了吗?偏移量
24(fp)
不再指向你的前一个参数。所以当你递归时,你不再加载你推的$s0
。相反,你加载的是谁知道的东西。现在,如果将这一部分移到函数 * 内部 *,则将从临时变量的正确偏移量加载。