Mips 递归函数流

Mips 递归函数流,mips,mips32,mips64,Mips,Mips32,Mips64,我是MIPS新手,我有一个给定的MIPS递归代码,我必须将其应用于特定的数字(例如数字3) 下面是给定的MIPS代码,如果我要在函数中传递ex.number 3,我应该写下,对于所述number 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

我是MIPS新手,我有一个给定的MIPS递归代码,我必须将其应用于特定的数字(例如数字3) 下面是给定的MIPS代码,如果我要在函数中传递ex.number 3,我应该写下,对于所述number 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

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

由于堆栈指针不正确,调用者会出错。这会让你感到不适,然后调用者会试图返回调用者。例如,火星上的
main
b/c可能没有问题,我们通常通过exit syscall退出
main
。但是,如果你这样做
fact(2)
,您将看到它执行的第一次返回正常工作,但之后调用方(事实本身,递归调用方)不工作-它无法返回到其调用方,因为它无法正确恢复其先前保留的
$ra
,因为堆栈指针已被终端大小写失衡

我们需要平衡开场白和尾声:不仅仅是静态的,而是动态的

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


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

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

由于堆栈指针不正确,调用者会出错。这会让你感到不适,然后调用者会试图返回调用者。例如,火星上的
main
b/c可能没有问题,我们通常通过exit syscall退出
main
。但是,如果你这样做
fact(2)
,您将看到它执行的第一次返回正常工作,但之后调用方(事实本身,递归调用方)不工作-它无法返回到其调用方,因为它无法正确恢复其先前保留的
$ra
,因为堆栈指针已被终端大小写失衡

我们需要平衡开场白和尾声:不仅仅是静态的,而是动态的

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

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