MIPS堆栈可视化

时间:2016-09-27 03:44:00

标签: assembly stack mips

以下是阶乘函数的c代码。 我清楚地了解递归函数的工作原理。 但我无法想象或不知道如何在MIPS堆栈上工作。

enter image description here

MIPS CODE

enter image description here

我的问题是, 我们如何在递归的每一步中保存堆栈中的递归函数(保存返回地址和参数)?

我知道对于每个递归函数,我们保存参数并返回地址,然后重新调整堆栈指针。

有人可以帮助我想象这个过程是如何运作的。

1 个答案:

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

注意堆栈如何返回到递归链末尾的原始位置。