我正在编写一个转换为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
它会在标记的行中崩溃,因为目标寄存器没有存储内容的地址。一个想法是为每个局部变量创建一个数据段,但这将是一个开销,它不适用于递归函数。
有没有人有一个正确的解决方案如何处理局部变量,特别是如果你从局部变量返回一个地址而不是一个值?
感谢任何帮助!
答案 0 :(得分:2)
您遇到的主要问题是您开始使用的示例C不是好代码。尝试在MIPS中实现代码的相同问题存在于原始的C代码中。您永远不应该在函数中创建局部变量并尝试返回其地址。该局部变量可以保存在寄存器或堆栈中,其数据可能会被清除。
举个例子,我在C中编写了这段代码,用mingw32-gcc来说明和编译它:
int* funcA()
{
int a = 3;
return &a;
}
int main (void)
{
int * myPointer;
myPointer = funcA();
return 0;
}
编译器会产生此警告:
警告:函数返回局部变量的地址