帧指针的优点是什么? [英] What are the advantages of a frame pointer?

查看:73
本文介绍了帧指针的优点是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在学习MIPS汇编器(我想这个问题可以适用于一般汇编),老师向我们介绍了帧指针.

We're studying the MIPS assembler (I guess this question can apply to assembly in general though), and the teacher introduced us to the frame pointer.

如果我有函数序言,我以前直接做堆栈指针:

If I have a function prologue, I used to do directly the stack pointer:

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

老师说在我们用汇编写函数的时候,使用帧指针对我们人类很有用:

The teacher said that using frame pointer is useful for us humans when we write functions in assembly:

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

老师也说有时候栈指针会继续分配其他空间,在函数内引用激活帧比较困难,因为我们需要注意.使用帧指针,我们将有一个指向激活帧的静态指针.

The teacher also said that sometimes the stack pointer goes on allocating other space and refering to the activation frame within the function is harder since we need to pay attention. Using frame pointer we'll have a static pointer to the activation frame.

是的,但是我是否永远需要在函数内使用激活,因为它只包含调用者函数的保存数据?

Yes, but will I ever need to use the activation within the function, since it just contains the saved data of the caller function?

我认为这让事情更难实施.有没有一个实际的例子,其中帧指针对程序员来说是一个很大的优势?

I think it makes just things harder to implement. Is there a real practical example where the frame pointer is a great advantage to the programmer?

推荐答案

当动态分配堆栈上的可变空间量时,您只需要一个框架指针.在 C 中使用可变长度数组和/或 alloca 的函数是需要帧指针的函数的示例.由于函数使用的堆栈数量是可变的,因此您不能使用堆栈指针的常量偏移量来访问变量,并且您需要一种在函数返回时撤消可变长度分配的方法.使用帧指针可以解决这两个问题.您可以使用它来使用常量偏移量寻址堆栈变量,并将堆栈指针恢复到它在函数开始时的值.

You only absolutely need a frame pointer when dynamically allocating variable amounts of space on the stack. Functions that use variable length arrays and/or alloca in C are examples of functions that need a frame pointer. Because the amount stack the function uses is variable you can't use constant offsets from the stack pointer to access variables and you need a way to undo the variable length allocations when the function returns. Using a frame pointer solves both problems. You can use it to both address stack variables using constant offsets and restore the stack pointer to the value it had at the start of the function.

在 MIPS 上,如果总堆栈分配超过 32k,在仅使用固定大小堆栈分配的函数中使用帧指针作为优化也是有意义的.MIPS 支持的有限寻址模式仅允许相对于堆栈指针或任何其他寄存器的 16 位符号扩展偏移.由于堆栈指针指向堆栈底部,堆栈指针只能使用非负偏移量,因此在单个指令中只能寻址堆栈上的 32k.通过使用帧指针并将其指向堆栈帧的中间(而不是帧的顶部),它可以用于在单个指令中寻址多达 64k 的堆栈.

On MIPS, it would also make sense to use a frame pointer as an optimization in a function using only fixed size stack allocations, if the total stack allocation is more than 32k. The limited addressing modes supported by MIPS only allow for a 16-bit sign extended offset relative to the stack pointer or any other register. Since the stack pointer points to the bottom of the stack, only non-negative offsets can be used with the stack pointer, and so only 32k on the stack can be addressed in a single instruction. By using frame pointer and by pointing it at the middle of the stack frame (instead of the top of the frame) it can be used to address up to 64k of the stack in a single instruction.

否则使用帧指针只会使程序员受益,而不是程序.如果程序中的所有函数都使用带有帧指针的标准堆栈帧,则帧指针和所有保存在堆栈中的已保存帧指针值形成堆栈帧的链表.这个链表可以很容易地在调试时创建一个函数调用的引用.但是,使用合适的现代调试器,即使未使用帧指针,也可以将元数据(展开信息)嵌入到调试器可用于遍历堆栈帧的可执行文件中.这是现代编译器可以自动完成的事情,但在汇编语言中,包含所有必要的额外指令以使其正常工作可能会非常痛苦.

Otherwise using the frame pointer is something that only benefits the programmer, not the program. If all functions in your program use a standard stack frame with a frame pointer then the frame pointer and all the saved frame pointer values stored in the stack form a linked list of stack frame. This linked list can easily be transversed to create a trackback of function calls when debugging. However, with a suitable modern debugger it's also possible to embed metadata (unwind info) into executables that the debugger can use to walk the stack frames even if a frame pointer isn't used. This something modern compilers can do automatically, but in assembly language it can be quite a pain to include all the necessary extra directives to make it work.

如果堆栈指针可以在函数期间通过固定大小的分配和释放多次更改,那么在程序中的任何给定点跟踪变量相对于堆栈指针的位置可能会很痛苦.虽然它总是在任何给定位置的固定偏移量,但会根据位置而变化.确定偏移量可能很棘手且容易出错.使用帧指针会给每个变量一个相对于永远不会改变的帧指针的偏移量,因为帧指针值不会改变.

If the stack pointer can change multiple times through fixed size allocations and deallocations during a function then it can be a pain to keep track of a variable's location relative to the stack pointer at any given point in the program. While it would always be at a fixed offset at any given location, that would change depending on the location. Determining that offset can be tricky and error prone. Using the a frame pointer would give each variable a offset relative to the frame pointer that never changes, since the frame pointer value doesn't change.

请注意,如果您觉得需要使用帧指针,因为最后两个原因之一,您必须首先考虑为什么要在汇编中编程.在这些情况下,现代编译器不需要使用帧指针,因此可以生成更好的代码.

Note that if you feel you need to use a frame pointer because one of the last two reasons you have to consider why you're programming in assembly in the first place. These are situations where a modern compiler wouldn't need to use a frame pointer, so would generate better code.

这篇关于帧指针的优点是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆