假设我们正在检查只有一个局部变量x的函数f的MIPS汇编代码:
void f(void) {
int x;
...
}我有两个问题:
我的尝试:函数序言将寄存器$ra和$fp保存到调用堆栈中。函数后记通过将这些寄存器从堆栈中弹出并将控制返回到$ra中的地址来恢复这些寄存器。不确定MIPS如何访问变量x,但我知道局部变量也存储在堆栈中。
发布于 2012-06-14 22:44:49
(a) f的函数序言和结尾对寄存器$sp、$ra和$fp做了什么假设$ra和$fp是由函数编辑的唯一被调用保存寄存器modifi。
($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’(存储单词),‘’指令将是'lw‘('load word')。
而且,我知道MIPS是一种痛苦,这个参考单真的帮助了我。
发布于 2012-06-14 20:47:56
看看MIPS调用约定这里。通常,函数中的局部变量将保存在临时(调用方保存的)寄存器$t0 - $t9中。如果函数本身调用函数,则局部变量将保存在堆栈上。
MIPS中没有push或pop指令,因此函数序言将堆栈指针减少足够的单词,以满足函数的所有堆栈存储需求,而函数后记则取消了这一点。
发布于 2019-11-10 15:32:12
对于寄存器$sp、$ra和$fp,假设$ra和$fp是函数唯一保存的寄存器modifi,那么f的函数序言和结束符是如何实现的。
$sp -堆栈指针$fp -帧指针$ra -返回地址
函数序言和结语指的是在函数开始时将返回地址寄存器(和任何其他寄存器)保存到堆栈,并在函数结束时将值返回到它们各自的寄存器。
正如您可能已经注意到的,MIPS架构没有堆栈,您必须创建它(您可能需要检查模拟器或特定处理器的手册,因为它的召集地址不同)。
您将在主程序中保存$sp中指定的地址:
daddi $sp, $sp, 0x400 # this is the convention address for WinMIPS64's stack 您可能出于几个原因想要使用堆栈,例如:
$ra)$fp,如问题所示$s0-$s7寄存器,则保存它们。按照惯例,在使用时应该将它们保存到堆栈中(在这种情况下不适用,但可能有人正在阅读它)。要做到这一点,您可以像上面的用户一样使用代码(根据您使用的MIPS版本,代码可能略有不同,请检查手册)。
要推送到堆栈,您必须使用上面的代码来模拟堆栈函数(为数据腾出空间,将数据保存在堆栈上)。请记住,当您按上面的堆栈时,您还必须弹出相等的值,将$sp返回到它原来的位置。您可以按照相反的顺序(同样,如上面所示的用户所示)执行此操作。
另外:由于MIPS中函数的调用指令(jal跳转和链接)自动将返回地址保存在单个寄存器中($ra -返回地址,记得吗?),如果使用递归或从第一个函数调用第二个函数,则始终需要这样做,否则返回地址将丢失到主程序,因为在下一次调用时,返回地址将被“踩上”。
例如,如果您将有许多寄存器值保存到堆栈中,并且您希望访问不同的操作数,而不移动将始终指向堆栈顶部的$fp,则将使用框架指针$sp。为了做到这一点,您需要将$sp的值加载到$fp上,然后添加一个位移值来移动。
它允许您在保持$sp位于相同位置的同时从堆栈加载值,从而允许您跟踪push和pop操作。
F的MIPS程序集代码如何访问变量x。
按照惯例,MIPS拥有参数和返回值的特定寄存器。在MIPS中,要传递给函数的参数保存在寄存器$a0-$a3中,返回值保存在$v0-$v1中。可以在函数中使用的临时寄存器是$t0-$t9,但它们在函数返回时不保留其值。但是,由于可能没有寄存器,所以可能需要使用堆栈。按照约定,$s0-$s7保存寄存器,通过使用堆栈保存其值。
P.S. 重要:--我正在使用WinMIPS64模拟器。MIPS汇编语言在寄存器大小、指令集和堆栈地址方面各不相同,请参考您的特定版本手册,并检查哪些值适用于您的情况,因为这将影响您的代码。
https://stackoverflow.com/questions/11038606
复制相似问题