传统的 C/C 编译器通过增加堆栈指针来创建局部变量(ESP)一次。然而,使用入栈/出栈指令可以产生更紧凑且可能更快的代码。本文探讨了哪些编译器提供此优化。
研究表明所有四种主要 x86 编译器(GCC、Clang、ICC 和 MSVC)当前都不使用推送/弹出创建局部变量的指令。相反,他们更喜欢旧方法的变体,使用 sub rsp, c 来减少堆栈指针。
对局部变量使用 push/pop 有几个优点:
虽然 Push/Pop 可以是有益的,但不建议在所有情况下都这样做。例如,与 [rsp x] 寻址模式混合时,它可能会导致额外的堆栈同步 uops。
考虑以下函数:
int extfunc(int *,int *); void foo() { int a=1, b=2; extfunc(&a, &b); }
使用改进的编译push/pop:
# compiled for the x86-64 System V calling convention: # integer args in rdi, rsi (,rdx, rcx, r8, r9) push 2 # only 2 bytes lea rdi, [rsp + 4] mov dword ptr [rdi], 1 mov rsi, rsp # special case for lea rsi, [rsp + 0] call extfunc(int*, int*) pop rax # alternative to add rsp,8 ret
注意: 此示例通过将 push 指令的最后 4 个字节与 lea 指令的前 4 个字节重叠来优化紧凑性和速度.
虽然push/pop指令可以为创建本地代码提供代码大小和性能优势变量,目前主流 C/C 编译器尚未使用它们。这可能是由于可能存在额外的堆栈同步微指令以及管理堆栈偏移的复杂性。然而,随着硬件和编译器优化的发展,局部变量的推送/弹出将来可能会得到更广泛的采用。
以上是C/C 编译器是否使用 Push/Pop 指令来创建局部变量?的详细内容。更多信息请关注PHP中文网其他相关文章!