【问题标题】:MIPS Compiler local variablesMIPS 编译器局部变量
【发布时间】:2015-07-23 16:26:47
【问题描述】:

我正在编写一个 tinyc 编译器,它可以转换为 MIPS 程序集。我被困在如何实现局部变量处理的问题上。下面的例子让人很难想出一个合适的解决方案:

int* funcA() {
    int a = 3;
    return &a;
}

int main() {
    return *(funcA());
}

通常您会在堆栈上创建局部变量。所以在这种情况下,'int a' 将在堆栈上创建。问题是最后我们要返回 'a' 的地址,而不是 &a 的值。但是在我们离开 'funcA()' 的那一刻,我们将堆栈重置为旧状态,最后我们返回的指针不再有效,以后可能会显示为必杀技。

我的第一次尝试是使用寄存器来处理所有事情,但是使用 &-Operator 我们将其转换为如下内容:

    .globl funcA
funcA:
    addiu   $sp, $sp, -4  # save return address
    sw      $ra, ($sp)
    addiu   $sp, $sp, -4  # save the reg we will use for further processing
    sw      $s0, ($sp)
    addiu   $t0, $zero, 3 # $t0 = a and add 3
    la      $s0, ($t0)
    la      $t0, ($s0)
    sw      $t1, ($t0)    # crashes here
    la      $v0, ($t1)    # put the result in $v0
    lw      $s0, ($sp)
    addiu   $sp, $sp, 4   # restore the stack
    lw      $ra, ($sp)
    addiu   $sp, $sp, 4
    jr      $ra           # jump back

它会在标记的行中崩溃,因为目标寄存器没有地址来存储某些东西。一种想法是为每个局部变量创建一个数据段,但这会产生开销,并且不适用于递归函数。

有没有人有适当的解决方案来处理局部变量,尤其是当你从局部变量返回地址而不是值时?

感谢任何帮助!

【问题讨论】:

  • 我认为您遇到的第一个问题是您从一个错误的 C 示例开始。您将遇到与尝试在 MIPS 中实现 C 代码相同的问题...将 int a 放在堆栈上并返回指向它的指针。例如,mingw32-gcc 编译器会警告您 int* funcA() - 警告:函数返回局部变量的地址
  • 哇哦,非常感谢!这个问题让我睡不着觉,解决起来很简单!
  • 我很高兴它有帮助 - 我没有意识到这是您正在寻找的解决方案。我将其添加为答案。

标签: compiler-construction mips local-variables


【解决方案1】:

您遇到的主要问题是您开始使用的示例 C 不是好的代码。尝试在 MIPS 中实现代码的相同问题存在于原始 C 代码中。您永远不应该在函数中创建局部变量并尝试返回其地址。该局部变量可以保存在寄存器或堆栈中,其数据可能会被清除。

举个例子,我用C写了这段代码来说明,用mingw32-gcc编译:

int* funcA()
{
    int a = 3;
    return &a;
}

int main (void)
{
    int * myPointer;

    myPointer = funcA();

    return 0;
}

编译器产生这个警告:

警告:函数返回局部变量的地址

【讨论】:

  • 感谢您的进一步解释!它已经是解决方案,因为我的编译器不必涵盖这种情况。我一直试图为这个案例寻找解决方案,但没有意识到我的前提是错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-18
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
相关资源
最近更新 更多