MIPS编译器局部变量

时间:2015-07-23 16:26:47

标签: compiler-construction mips local-variables

我正在编写一个转换为MIPS汇编的tinyc编译器。我坚持如何实现局部变量处理的问题。以下示例使您很难想到一个合适的解决方案:

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

它会在标记的行中崩溃,因为目标寄存器没有存储内容的地址。一个想法是为每个局部变量创建一个数据段,但这将是一个开销,它不适用于递归函数。

有没有人有一个正确的解决方案如何处理局部变量,特别是如果你从局部变量返回一个地址而不是一个值?

感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

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

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

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

int main (void)
{
    int * myPointer;

    myPointer = funcA();

    return 0;
}

编译器会产生此警告:

  

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