跳至内容

MIPS 汇编/子程序

来自维基教科书,自由的教科书

本页将讨论在 MIPS 汇编中使用子程序结构。此外,本页还将讨论将高级语言结构和子程序转换为 MIPS 汇编代码的一些常见方法。

子程序机制

[编辑 | 编辑源代码]

在 MIPS 中,通用寄存器通常被用作函数参数和函数变量,根据需要。通用寄存器的先前值存储在堆栈中。在子程序结束时,所有以这种方式存储的寄存器值都从堆栈中恢复。

MIPS 使用堆栈来保存这些寄存器。堆栈指针指向堆栈的底部,但帧指针指向局部帧的顶部。从堆栈或帧指针偏移可以根据需要检索各种保存的值和函数参数。

茎和叶

[编辑 | 编辑源代码]

在函数层次结构中,调用其他函数的函数称为函数。不调用任何其他函数的函数称为函数。茎函数必须将$ra的值保存在堆栈上,以便其内容在其他函数调用中得以保留,以便被调用函数可以返回到调用函数或其父函数。

重要的是要注意,叶函数不需要保存$ra寄存器的值,因为它不调用任何其他子函数,因此其返回地址保存在$ra中。

堆栈帧

[编辑 | 编辑源代码]

函数可以设置堆栈帧,其中$sp寄存器指向堆栈的底部,$fp寄存器指向子程序开始时堆栈的顶部。通过这种方式,$fp将指向函数的输入参数(如果任何参数都在堆栈上),而$sp将指向函数的局部变量。

$fp的值需要在函数调用中保留,茎函数需要在调用子函数之前保存$fp的值,并在调用子函数之后从堆栈中恢复它。

$sp的值不需要存储在堆栈上,但函数需要确保在函数返回之前将$sp返回到函数开始时它所具有的值。这意味着在子程序开始时,可以将值压入堆栈,并且在子程序结束时,所有这些值都需要从堆栈中弹出。如果操作不正确,它将破坏父函数的堆栈帧,并可能导致计算机崩溃。

保存的寄存器

[编辑 | 编辑源代码]

有一些寄存器必须在子程序调用期间保留。这意味着如果子程序想要使用这些寄存器,它必须将先前的值保存到堆栈(或其他地方),然后在函数结束时重新加载这些值。$tx寄存器都是临时寄存器,不需要保存。同样,$ax寄存器都是函数参数,也不需要保存。$v0$v1寄存器都是函数返回值,也不需要保存。

以下寄存器需要在函数调用期间保留,如果函数要使用它们,则应由函数保存

$sx
"已保存的临时"寄存器

MIPS 和 C 语言链接

[编辑 | 编辑源代码]

进一步阅读

[编辑 | 编辑源代码]
华夏公益教科书