0

我是 MIPS 的新手,我有一个给定的 MIPS 递归代码,我必须将它应用到一个特定的数字(例如数字 3) Bellow 是给定的 MIPS 代码,如果我要通过 ex,我应该写。函数中的数字 3 对于所述数字 3 的递归,注册表和缓存中的变化是什么?我试图在一张纸上一步一步地做,但一无所获。

    fact: 
addi $sp, $sp, -8
sw $ra, 4($sp)  
sw $a0, 0($sp)  
slti $t0,$a0,1
beq $t0,$zero,L1 
addi $v0,$zero,1 
addi $sp,$sp,8 
jr $ra 
Ll:addi $a0,$a0,-1 
jal fact 
lw $a0, 0($sp) 
lw $ra, 4($sp) 
addi $sp, $sp, 8 
mul $v0,$a0,$v0 
jr $ra
4

1 回答 1

2

始终首先使用尽可能少的输入来测试您的代码。如果您尝试使用 0,并且单步执行大约 8 条指令,您可以观察到您的代码不会使用正确的堆栈指针值返回给它的调用者——函数的一个重要部分是保留必须为调用者,其中包括堆栈指针。通常,恢复堆栈指针的方法是释放任何分配的空间,只要这是平衡的,就$sp可以遵守保留规则。

由于堆栈指针不正确,调用者搞砸了。这会咬你,然后是当调用者试图返回到它的调用者时。可能这对于 MARS 上的 b/c 来说不是问题main,例如,我们通常main通过 exit 系统调用退出。但是,如果你这样做fact(2),你会看到它执行的第一个 return 工作正常,但之后调用者(事实本身,递归调用者)不起作用 - 它无法返回其调用者,因为它无法正确恢复它以前保留$ra,因为堆栈指针已被终端情况不平衡。

我们需要平衡序幕和尾声:不仅是静态的,而且是动态的。

您的代码在所有情况下都在分配堆栈空间,尽管在终端情况下,您的代码忽略了堆栈的释放,因此它变得不平衡。

将堆栈调整(释放)添加到终端案例,或者在分配堆栈空间之前测试终端案例(因此您不必在该终端案例中分配或释放)。

于 2021-03-14T17:50:55.910 回答