我们正在研究MIPS汇编(我想这个问题可以适用于装配虽然在一般),老师向我们介绍了帧指针。帧指针的优点是什么?
如果我有一个函数序言,我用来直接做堆栈指针:
addiu $sp, $sp, -8 ; alloc 2 words in the stack
sw $s0, 4($sp) ; save caller function $s0 value in the stack
sw $ra, ($sp) ; save the return address for the callee function
而在函数尾声:
move $v0, $0 ; set 0 as return value
lw $s0, 4($sp) ; pick up caller $s0 value from the stack
lw $ra, ($sp) ; pick up return address to return to the caller
addiu $sp, $sp, 8 ; dealloc the stack words I used
jr $ra ; return back to caller
老师说,使用帧指针当我们在装配中编写功能时对我们人类有用:
addiu $sp, $sp, -12 ; alloc 3 words in the stack
sw $fp, 8($sp) ; save caller frame pointer in the stack
addiu $fp, $sp, 8 ; set $fp to the uppermost address of the activation frame
sw $ra, -4($fp) ; saving like the first example, but relative
sw $s0, -8($fp) ; to the frame pointer
老师还说,有时候堆栈指针会继续分配其他空间,因为我们需要注意,所以在函数内部引用激活帧是很困难的。 使用帧指针我们将有一个指向激活帧的静态指针。
是的,但我会永远需要使用函数内的激活,因为它只包含调用者函数保存的数据?
我认为它只是使事情更难实现。有没有一个真实的例子,帧指针对程序员来说是一个很大的优势?
对于许多指令集,你不需要使用帧指针,最多它使编译器作者更容易调试,这不是一个真正有效的借口,好像浪费了一个寄存器给我。 gcc等可能允许你选择不使用帧指针,不建立使用它的代码来节省开销。一些默认值,一些默认不带。它使该函数内的偏移量固定,对于该函数,变量X始终为fp-N。您可以为整个功能制作X sp + M,或者可以根据需要移动SP以保留空间。 –
不管老师说什么,结束的时候,对于那个班级来说,通过班级,怀疑一切,然后(重新)发现它,看看你是否相信。是否只是让老师对作业进行评分更容易一些,还是这种编程规则在某种意义上被教导得“更好”?我同意它使人类更容易,但同时编译器或人类,如果你移动sp来覆盖函数的所有用法,没有帧指针也同样容易。 –
试试这个:在你的脑海中定义一个C结构,包含5个或更多字段。在堆栈中为它分配空间。初始化它。将其成员作为堆栈中的参数传递给其他函数。做和没有框架指针。 –