(a) f 的函数 prologue 和 epilogue 对寄存器 $sp、$ra 和 $fp 做了什么,假设 $ra 和 $fp 是函数修改的唯一被调用者保存的寄存器。
($fp是“帧指针”,也称为“基指针”,$sp是“堆栈指针”,$ra是“返回地址”)
要解释如何访问“ int x ”,了解它的存储方式和存储位置很重要。由于“ int x ”是一个局部变量,MIPS 将通过减去 32 位整数的字节数 (4) 为堆栈上的整数分配适当的空间(或者如果有空间,则使用 markgz 所说的方法)从堆栈指针。调用者的返回地址也被保存(另外 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) f 的 MIPS 汇编代码如何访问变量 x。
要访问“ int x ”,函数“ f ”可以将变量加载到临时寄存器中。
lw $t0, 0($sp) #it can be any temporary register
由于局部变量不会在函数调用之间保留,它们可以存储在临时寄存器中。本质上,“ push ”指令将是“ sw ”(“存储字”),而“ pop ”指令将是“ lw ”(“加载字”)。
另外,我知道 MIPS 可能会很痛苦,而这份参考表确实帮助了我。