想想下面递归定义的 C 函数:
int f(int n)
{
if(n<3)
{
return n+4;
}
else
{
return f(n-1)+f(n-2);
}
}
你打电话给f(20)。
会发生以下情况:
最初返回地址位于寄存器$ra。
函数使用函数参数f(19) 调用自身,并返回f(19)。到目前为止,一切都很好。一些寄存器现在将包含f(19) 返回的值。
现在该函数使用参数f(18) 调用自身。
f(19) 返回的值已存储在某个寄存器中。 f(19) 正在那里写入值;在这种情况下,f(18) 正在覆盖该寄存器,因为 f(19) 和 f(18) 是相同的功能。或者f(20) 正在那里写入值......好吧f(20) 和f(18) 是相同的功能。
寄存器无论如何都会被覆盖。
因此将返回的值存储在寄存器中是行不通的。存储在全局变量中怎么样?
int intermediate;
int f(int n)
{
...
intermediate = f(n-1);
return f(n-2) + intermediate;
}
我们也会遇到同样的问题:调用f(18) 会覆盖变量intermediate,所以我们不能再做加法了...
...当我们想从函数返回时,我们遇到了下一个问题:通过调用f(19),我们覆盖了$ra ...
使用局部变量只会移动问题:
int f(int n)
{
int local;
...
}
=> 我们应该将变量local 存储在哪里?在固定内存地址(= 全局变量)还是在寄存器中?在这两种情况下,我们都会遇到与上述相同的问题。
现在我们可以想到以下解决方案:
int intermediate[100];
int f(int n, int level)
{
...
intermediate[level] = f(n-1, level+1);
intermediate[level] += f(n-2, level+1);
...
}
所以f(20) 将使用intermediate[0],从f(20) 调用的函数使用intermediate[1],从该函数调用的函数使用intermediate[2] 等等...
没错这就是“堆栈”的概念!
但是您不必自己实现它,但已经预定义了寄存器$sp 指向您可以使用的内存(示例中为level)。