gpt4 book ai didi

assembly - 是否真的需要RBP/EBP寄存器来支持可变大小堆栈帧?

转载 作者:行者123 更新时间:2023-12-02 19:40:01 25 4
gpt4 key购买 nike

CSAPP第三版说:


要管理可变大小的堆栈帧,x86-64代码使用寄存器%rbp
到服务器作为框架指针。


但是,我很好奇这个%rbp寄存器是否真的必要。尽管编译器不知道必须为该函数的堆栈帧分配多少空间,但在调用subq xxxx, %rsp之后,它可以始终将堆栈帧的当前分配大小保存到任何寄存器中,因此它不需要依赖< cc>恢复%rbp的值。这是真的吗?如果是这样,这是否意味着%rsp完全没有必要,只是一个约定?

最佳答案

没错如果保留在可变大小sub xxx, %rsp中使用的大小,则可以在末尾添加add(或使用lea fixed_size(%rsp,%rdi,4), %rsp进行反转)以取消分配任何固定大小的堆栈空间预留。

正如@Ross指出的那样,这不能很好地扩展到同一函数中的多个可变长度分配。即使只有一个VLA,它也不比函数结尾处的mov %rbp, %rsp(或leave)快。这将使编译器浪费空间,并具有15个可用寄存器,而不是函数的14个可用寄存器,当将其用作帧指针时,它永远不会选择与%rbp一起使用。无论如何,这意味着gcc仍然希望在复杂情况下使用帧指针。 (默认值为-fomit-frame-pointer,但不用担心它不会强制gcc永远不要使用它)。

%rbp作为帧指针具有一些次要的优点,尤其是在代码大小方面:将%rsp作为基址寄存器的addressing mode始终需要一个SIB字节(标度/索引/基数),因为Mod / RM编码这意味着(%rsp)实际上是一个转义序列,表示有一个SIB字节。同样,表示(%rbp)没有位移的编码实际上意味着根本没有基址寄存器,因此您总是需要像disp8这样的0(%rbp)字节。

例如,mov %eax, 16(%rsp)mov %eax, -8(%rbp)长1B。 Jan Hubicka suggested如果gcc具有启发式功能以在不导致性能下降的情况下节省代码大小的函数中启用帧指针,那将是一件好事,并认为通常是这种情况。它还可以保存一些堆栈同步的指令,以避免在具有堆栈引擎的Intel CPU上直接使用%e/rsp(在推/弹出或调用之后)。

在具有C99可变大小数组的任何函数中,gcc始终将%rbp用作帧指针。可能是gcc开发人员发现,弄清楚这种功能何时没有帧指针仍然可以保持效率,并在gcc中有很多代码用于那些罕见的特殊情况,是不值得的。



但是,如果我们真的想避免在具有VLA的函数中使用帧指针该怎么办?

第7个及以后的整数参数(在SysV ABI中,请参见标签wiki)将位于返回地址上方的堆栈中。通过disp(%rsp)访问它们是不可能的,因为在编译时不知道位移。

disp(%rsp, %rcx, 1)是可能的,其中%rcx保存可变长度数组的大小。 (或所有VLA的总大小)。与disp(%rsp)相比,这不会花费任何额外的代码大小,因为以%rsp作为基址寄存器的寻址模式已经必须使用SIB字节。但这意味着VLA大小需要全时保持在寄存器中,使用帧指针不会给我们带来任何好处。 (并且丢失代码大小)。

另一种方法是将标量/固定大小的局部变量保持在任何可变长度分配以下,因此我们始终可以相对于%rsp的固定位移访问它们。这对于代码大小很有用,因为我们可以使用disp8(1B)代替disp32(4B)在%rsp的[-128,+ 127]字节内进行访问。

但是,只有在您需要向当地人泄漏任何东西之前尽早确定VLA大小时,此方法才有效。因此,再次有一个复杂的特殊情况供编译器检查,对于这种特殊情况,它需要在gcc中使用一堆代码生成代码。

如果溢出VLA大小并在ret urn之前重新加载/使用它,则使%rsp的值取决于从内存重新加载。无序执行可能会掩盖额外的延迟,但是在某些情况下,额外的延迟会延迟使用%rsp的所有其他操作,包括恢复调用方的寄存器。

这种样式的代码生成可能还会为gcc处理一些极端情况,以制作正确而有效的代码。由于它很少使用,因此其中的“有效”部分可能不会引起太多关注。

很容易看出为什么gcc选择在任何情况下都只是简单地退回到帧指针模式。通常,它几乎免费为您提供额外的注册,因此,即使您确实引用了很多本地语言,也值得放弃代码大小的优势。在32位代码中尤其如此,从6个通用寄存器到7个通用寄存器(不包括esp)。在64位代码中,这种差异通常较小,其中14与15的差异小得多。仍然将推/移动/弹出指令保存在不需要它们的功能中,这是一个单独的好处。 (将%rbp用作通用寄存器仍然需要压入/弹出。)

关于assembly - 是否真的需要RBP/EBP寄存器来支持可变大小堆栈帧?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37583449/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com