假设我们正在检查只有一个局部变量 x 的函数 f 的 MIPS 汇编代码:
void f(void) {
int x;
...
}
我有两个问题:
假设 $ra 和 $fp 是唯一被函数修改的被调用者保存的寄存器,f 的函数序言和结尾对寄存器 $sp、$ra 和 $fp 做了什么。
f 的 MIPS 汇编代码如何访问变量 x。
我的尝试: 函数序言将寄存器 $ra 和 $fp 保存到调用堆栈中。函数 epilogue 通过将它们从堆栈中弹出并将控制返回到 $ra 中的地址来恢复这些寄存器。不确定 MIPS 如何访问变量 x,但我知道局部变量也存储在堆栈中。
最佳答案
(a) What does the function prologue and epilogue for f do to the registers $sp, $ra and $fp assuming $ra and $fp are the only callee-saved registers modified by the function.
($fp 是“帧指针”也称为“基指针”,$sp 是“堆栈指针”,$ra 是“返回地址”)
要解释如何访问“int x”,了解它的存储方式和存储位置很重要。由于 'int x' 是局部变量,MIPS 将通过减去字节数 ( 4) 从堆栈指针中获取 32 位整数。调用者的返回地址也被保存(另外 4 个字节),以便函数可以链接回调用者:
sub $sp, $sp, 8 #4 bytes for $ra + 4 bytes for 'int x' = 8 bytes allocated
sw $ra, 4($sp) #note the order, $ra is always first
sw [int x], 0($sp)
或
addi $sp, $sp, -8 #an alternate to the code above
sw $ra, 4($sp)
sw [int x], 0($sp)
同样,在函数调用结束时,函数将通过释放堆栈空间将寄存器恢复给调用者:
lw [int x], 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
我没有太多使用帧指针 ($fp) 的经验,但是如果堆栈指针 ($sp) 在一个过程中改变了值它不能再用作引用点,因此 ($fp) 取而代之($sp 只是另一个寄存器)。
(b) How does the MIPS assembly code for f accesses the variable x.
要访问“int x”,函数“f”可以将变量加载到临时寄存器中。
lw $t0, 0($sp) #it can be any temporary register
由于局部变量不会跨函数调用保留,因此可以将它们存储在临时寄存器中。本质上,“push”指令是“sw”(“store word”),“pop”指令是“” lw' ('加载词').
此外,我知道 MIPS 可能会很痛苦,而这 reference sheet真的帮助了我。
关于c - 函数调用 mip,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11038606/