以下是阶乘函数的c代码。 我清楚地了解递归函数的工作原理。 但我无法想象或不知道如何在MIPS堆栈上工作。
MIPS CODE
我的问题是, 我们如何在递归的每一步中保存堆栈中的递归函数(保存返回地址和参数)?
我知道对于每个递归函数,我们保存参数并返回地址,然后重新调整堆栈指针。
有人可以帮助我想象这个过程是如何运作的。
答案 0 :(得分:1)
前提 MIPS中的堆栈与任何其他架构中的堆栈一样,因此您只需谷歌即可。
假设堆栈指向内存的任意位置:
| xxx | xxx = Undefined
| xxx | <- $sp
| |
| | | Free area, stack moves down
| | V
现在只需模拟对fact(3)
的呼叫
您粘贴了代码的图像,因此此处不会显示任何代码。可复制的代码可以使这个答案更加清晰。
fact
的每次调用都按此顺序推送返回地址和参数
我们假设fact
位于0x1000,而fact
的调用位于0x1ffc。
fact(3)
| xxx |
| xxx |
| 0x2000 | Return address to caller of fact(3)
| 3 | <- $sp Argument of fact(3)
| |
fact(2) called from fact(3)
| xxx |
| xxx |
| 0x2000 | Return address to caller of fact(3)
| 3 | Argument of fact(3)
| 0x1028 | Return address to L1+8 label
| 2 | <- $sp Argument of fact(2)
fact(1) called from fact(2)
| xxx |
| xxx |
| 0x2000 | Return address to caller of fact(3)
| 3 | Argument of fact(3)
| 0x1028 | Return address to L1+8 label
| 2 | Argument of fact(2)
| 0x1028 | Return address to L1+8 label
| 1 | <- $sp Argument of fact(1)
fact(0) called from fact(1)
| xxx |
| xxx |
| 0x2000 | Return address to caller of fact(3)
| 3 | Argument of fact(3)
| 0x1028 | Return address to L1+8 label
| 2 | Argument of fact(2)
| 0x1028 | Return address to L1+8 label
| 1 | Argument of fact(1)
| 0x1028 | Return address to L1+8 label
| 0 | <- $sp Argument of fact(0)
fact(0)
返回1并从堆栈中删除两个项目
fact(0)
是叶子调用,即最后一次调用,因此没有其他调用更改$ra
,而且不需要$a0
(参数),因此保存在堆栈中的这两个值只是通过递增$sp
来丢弃。
Just before "jr $ra" in fact(0)
| xxx |
| xxx |
| 0x2000 | Return address to caller of fact(3)
| 3 | Argument of fact(3)
| 0x1028 | Return address to L1+8 label
| 2 | Argument of fact(2)
| 0x1028 | Return address to L1+8 label
| 1 | <- $sp Argument of fact(1)
其他返回从堆栈中恢复$a0
和$ra
的值以计算n*fact(n-1)
并返回其调用者。
Just before "jr $ra" in fact(1)
| xxx |
| xxx |
| 0x2000 | Return address to caller of fact(3)
| 3 | Argument of fact(3)
| 0x1028 | Return address to L1+8 label
| 2 | <- $sp Argument of fact(2)
Just before "jr $ra" in fact(2)
| xxx |
| xxx |
| 0x2000 | Return address to caller of fact(3)
| 3 | <- $sp Argument of fact(3)
Just before "jr $ra" in fact(3)
| xxx |
| xxx | <- $sp
注意堆栈如何返回到递归链末尾的原始位置。