MIPS架构中栈指针$sp与帧指针$fp地址相同是否合法?
根据《Computer Organization and Design MIPS 5th ed》第103页内容,我原本认为帧指针$fp应指向栈的第一个字。但MIPS GCC 12.2.0为如下C代码生成的汇编中,$fp与$sp地址完全相同:
int func(int g) { int f = 9; return g+f; }
生成的汇编代码:
func: addiu $sp,$sp,-24 sw $fp,20($sp) move $fp,$sp sw $4,24($fp) li $2,9 # 0x9 sw $2,8($fp) lw $3,24($fp) lw $2,8($fp) nop addu $2,$3,$2 move $sp,$fp lw $fp,20($sp) addiu $sp,$sp,24 jr $31 nop
我疑惑这种$fp与$sp地址相同的情况是否合法?我原本认为$fp应指向栈的第一个字,比如这样编写汇编:
func: addiu $sp,$sp,-24 sw $fp,20($sp) addiu $fp,$sp,20 #let $fp point to the first word on the stack
想请教$fp指向栈的位置是否有明确规则,还是完全由开发者/编译器自行决定?
解答
这种$fp与$sp地址相同的情况完全合法。
MIPS的*应用二进制接口(ABI)*并没有强制规定$fp必须固定指向栈的某个特定位置,其核心要求是:通过$fp能够正确寻址栈帧内的局部变量、保存的寄存器以及函数参数。只要满足这个前提,编译器或手写汇编的开发者可以灵活选择$fp的指向。
你在教材里看到的“$fp指向栈的第一个字”是一种常见的教学范式——通常是让$fp指向旧$fp的存储位置(栈帧的“底部”),这样访问局部变量用正偏移、访问函数参数用负偏移,逻辑清晰,便于初学者理解栈帧结构。但编译器会根据函数的实际情况做优化,比如你提供的这个简单函数,局部变量数量少,直接让$fp等于$sp,同样可以通过偏移量正确访问栈内数据,还能简化栈帧的维护操作。
你自己手写的汇编写法也是合法的,本质上只是对$fp指向的选择不同,只要能正确完成栈帧内的寻址,就符合要求。
总结来说:$fp的指向没有绝对固定的规则,只要符合MIPS ABI中“正确寻址栈帧元素”的核心要求,具体指向完全由开发者或编译器自行决定,不同实现都是合法的。
内容的提问来源于stack exchange,提问作者African_king

