【问题标题】:MIPS: Why do we need the stack? [duplicate]MIPS:为什么我们需要堆栈? [复制]
【发布时间】:2018-11-02 07:08:03
【问题描述】:

MIPS 中堆栈的用途是什么,我们为什么需要它?有人可以提供一个相关的示例代码吗?

【问题讨论】:

  • 在寄存器用完或跨函数调用时有效地实现 C 所谓的自动存储(局部变量)。
  • 你不需要堆栈。但它通常是使用计算机内存以 LIFO(后进先出)方式进行存储的最简单/有效的方式。
  • 为什么强调 MIPS?大多数处理器都使用类似的堆栈。
  • @LưuVĩnhPhúc:第三个链接(第二条评论中的第二个链接)似乎与“普通”堆栈无关,而是与 .NET 计算中使用的一些特殊“堆栈”有关。

标签: assembly stack mips


【解决方案1】:

想想下面递归定义的 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)。

【讨论】:

    猜你喜欢
    • 2012-05-30
    • 2017-02-08
    • 2020-09-26
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    相关资源
    最近更新 更多