MIPS函数如何传入超过4个参数?含C++转MIPS实操疑问
MIPS中处理4个以上函数参数的方案及代码补全
先解答核心问题:MIPS中如何传递超过4个的函数参数?
在MIPS遵循的System V ABI标准调用约定里,函数参数的传递规则很明确:
- 前4个参数直接用
$a0到$a3这四个寄存器传递,这也是你已经完成的部分 - 当参数数量超过4个时,剩下的参数必须从右往左依次压入栈中(这是因为C/C++采用的cdecl调用约定要求参数从右到左求值入栈)
- 额外注意:压栈前一定要先调整栈指针
$sp,预留足够的栈空间,同时要保证栈是8字节对齐的(MIPS32环境下至少4字节对齐,64位则需8字节,根据你的场景调整)
针对你的代码补全:把C++调用转成完整MIPS汇编
你的目标调用是:
funcArr2(12, a2, a3, a4, used1, used2, &used3, &used4);
前4个参数已经处理完毕,剩下的第5到8个参数依次是used1、used2、&used3、&used4。按照规则,我们需要从最右边的&used4开始,往左依次压栈。
假设你的代码里:
used1、used2是栈上的局部变量(或你已用寄存器保存了它们的值)&used3、&used4是对应的地址(比如存在$t1、$t0寄存器里,或者是栈偏移地址)
完整的汇编代码如下(附详细注释):
# 前4个参数:你已经完成的部分 li $a0, 12 # 第一个参数:常量12 addi $a1, $sp, 280 # 第二个参数:a2的地址 addi $a2, $sp, 328 # 第三个参数:a3的地址 addi $a3, $sp, 376 # 第四个参数:a4的地址 # 步骤1:预留栈空间存储剩余4个参数(每个参数4字节,共16字节;同时保证栈对齐) addi $sp, $sp, -16 # 步骤2:从右往左压入剩余参数 # 第8个参数:&used4 → 存在栈的最高偏移位置(12($sp)) # 若&used4是栈上变量,可替换为 addi $t0, $sp, xxx(注意此时$sp已减16,偏移需调整) sw $t0, 12($sp) # 第7个参数:&used3 → 偏移8($sp) sw $t1, 8($sp) # 第6个参数:used2的值 → 偏移4($sp) # 若used2是栈变量,需先通过 lw $t2, offset($sp) 取出值再压栈 sw $t2, 4($sp) # 第5个参数:used1的值 → 偏移0($sp) sw $t3, 0($sp) # 调用目标函数 jal funcArr2 # 步骤3:调用完成后恢复栈指针(cdecl约定由调用者清理栈) addi $sp, $sp, 16
几个关键注意点:
- 压栈顺序绝对不能错:必须从最右边的参数开始往左压,否则函数内部取栈上参数时会拿到错误的值
- 栈对齐:如果你的栈原本不是8字节对齐,调整
$sp时要多减几个字节(比如减20而非16)来保证对齐,避免运行异常 - 参数类型区分:如果是指针(比如
&used3),压栈的是地址;如果是普通变量(比如used1),压栈的是变量的值,别搞混
内容的提问来源于stack exchange,提问作者gotj
相关产品推荐
相关产品推荐

