为什么编译器不使用ENTER和LEAVE指令?

4
阅读程序的反汇编代码后,我注意到一个模式。当设置函数的框架时,指令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


1
简而言之:一条指令代替两条并不总是更快。 - Joseph Sible-Reinstate Monica
问题不在于 leave 做了什么,而是 enter 做了什么。enter疯狂的,它应该为块结构化高级语言中的嵌套堆栈帧提供汇编支持。由于现代处理器无法使 enter 的一般形式变得快速,即使是仅为当前堆栈帧保留堆栈空间的较不疯狂版本也被处理器实现者所忽视。如果您查看 Agner Fog 的指令表,您会发现 enter a, 0push; mov; sub 慢约3-4倍,而 enter a,b 实际上需要很长时间。 - EOF
此外,现代编译器通常可以避免使用帧指针(因为现代调试和解开表格使帧指针变得多余),因此帧指针大多是过去的遗物,特别是在像x86(_64)这样寄存器资源匮乏的架构上,为编译器的寄存器分配器提供额外的寄存器非常有价值。 - EOF
“leave”命令非常简单,它只有“mov; pop”的操作。编译器在以下情况下使用“leave”:1)函数使用可变长度数组,“alloca()”,目标ABI需要帧指针或程序员明确要求编译器通过使用帧指针产生更差的代码;2)代码密度优势(一个指令和一个字节的操作码与多个指令相比,其中一个指令需要多个字节来编码)大于执行速度缺陷(这相当小)。 - EOF
谢谢,特别是关于 leave 的解释 @EOF - Arush Agarampur
显示剩余3条评论
1个回答

3

为什么编译器不使用ENTER和LEAVE指令?

这些指令曾在i286i386时代使用,即1999年之前。

今天,这些机器指令通常比较简单的等效指令慢。编译器作者知道这一点,因此避免发出这些机器指令。


它已经在i186中可用了。真的很老! - Alexis Wilke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接