如果没有 %rbp 寄存器,堆栈帧的释放是如何发生的?
How does deallocation of stack frame takes place without the %rbp register?
我读到过使用基址寄存器来跟踪堆栈帧并不是真正必要的。我不明白编译器是如何实现这一点的,它是否将堆栈帧大小存储在某处并读取它并将其添加到 %rsp?
这通常也不是必需的,只要您属于以下两种情况之一:
rsp
仅改变了已知数量
rsp
永远不会改变(你可以说这是一个已知数量,数量为 0)
通常在 x64 代码中,rsp
仅在序言、结语中更改,并且隐含地与 calls/returns 一起更改。任何临时 space 都是预先分配的,并通过索引到堆栈帧中进行寻址(通常与往常一样,除了偏移量来自 rsp
而不是基指针 - 如果 rsp
不会改变),而不是通过推和弹出。在那种情况下很容易恢复旧的rsp
,只需添加在序言中减去的相同内容即可。
或者,这尤其适用于有红区的 linux,对于许多叶函数,您可以完全不更改 rsp
。在这种情况下,您甚至可能不需要序言或结语,只需要一堆正常代码后跟 ret
.
显然alloca
(以及分配可变数量堆栈的其他构造space)打破了这一点,并且将再次使用帧指针。
我读到过使用基址寄存器来跟踪堆栈帧并不是真正必要的。我不明白编译器是如何实现这一点的,它是否将堆栈帧大小存储在某处并读取它并将其添加到 %rsp?
这通常也不是必需的,只要您属于以下两种情况之一:
rsp
仅改变了已知数量rsp
永远不会改变(你可以说这是一个已知数量,数量为 0)
通常在 x64 代码中,rsp
仅在序言、结语中更改,并且隐含地与 calls/returns 一起更改。任何临时 space 都是预先分配的,并通过索引到堆栈帧中进行寻址(通常与往常一样,除了偏移量来自 rsp
而不是基指针 - 如果 rsp
不会改变),而不是通过推和弹出。在那种情况下很容易恢复旧的rsp
,只需添加在序言中减去的相同内容即可。
或者,这尤其适用于有红区的 linux,对于许多叶函数,您可以完全不更改 rsp
。在这种情况下,您甚至可能不需要序言或结语,只需要一堆正常代码后跟 ret
.
显然alloca
(以及分配可变数量堆栈的其他构造space)打破了这一点,并且将再次使用帧指针。