【发布时间】:2020-11-01 13:21:18
【问题描述】:
阅读程序的反汇编,我注意到了一个模式。在设置函数的框架时,很少使用指令enter。我还将编译器资源管理器与最新的 GCC 一起使用——GCC 不使用 enter,而是使用 leave。
为什么不使用指令enter?为什么编译器使用两条或更多指令来执行可以在一条指令中完成的操作? (推送 rbp,保存 rsp,并使用sub rsp 在堆栈上分配,而不是使用enter 0x20, 0)。但是leave 被使用了……还有什么我不知道的leave 吗?据我所知,leave 相当于
mov ebp, esp
pop ebp
GCC 使用 leave 而 MSVC 没有。我不明白为什么从未使用过enter 而有时使用leave。
【问题讨论】:
-
tl;dr:一条指令而不是两条并不总是意味着更快。
-
好的,谢谢。
-
问题不在于
leave所做的,而是enter所做的。enter是 insane,它应该为块结构高级语言中的嵌套堆栈帧提供汇编支持。因为enter的一般形式不能被现代处理器快速处理,所以即使是不那么疯狂的版本,它只为当前堆栈帧保留堆栈空间,也被忽略了处理器实现者。如果您查看 Agner Fog 的指令表,您会发现enter a, 0比push; mov; sub慢约 3-4 倍,而enter a,b有效地占用了永恒。 -
此外,现代编译器通常可以避免使用帧指针(因为现代调试和展开表使帧指针变得多余),因此帧指针大多是过去的遗物,尤其是在寄存器匮乏的架构上,如 x86( _64),其中编译器的寄存器分配器的额外寄存器非常有价值。
-
哦?我还有两个问题。如果我们不使用
enter,为什么有时会使用leave?另外,我在哪里可以了解有关展开表的更多信息? (例如示例)@EOF
标签: assembly x86 x86-64 compiler-optimization