我用gcc生成这样的汇编代码,gcc可以生成对堆栈框架具有ENTER键的代码吗?
.file "temp.c"
.text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
movl $0, -12(%rbp)
movl $0, -8(%rbp)
movl $0, -4(%rbp)
movl $0, %eax
popq %rbp
ret
.size main, .-main
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0"
.section .note.GNU-stack,"",@progbits
这是原始代码:
#include <stdio.h>
int main(){
int a;
int b;
int c;
a = 0;
b = 0;
c = 0;
}
答案 0 :(得分:3)
GCC永远不会发出enter
,因为与普通的2或3条单uup指令的帧指针设置相比,它的速度非常慢。
(如果它完全使帧指针; gcc -O1
及更高版本将启用-fomit-frame-pointer
。除了进行大小优化外,因为x(%rsp)
寻址模式与{{1 }}模式。)
x(%rbp)
具体来说,在Skylake # equivalent to enter $24, $0 (4 bytes)
push %rbp # 1 byte
mov %rsp, %rbp # 3 bytes
sub $24, %rsp # 4 bytes only for a non-zero immediate
上为12 oups,对于enter
(Agner Fog's instruction tables),每8周期吞吐量一个。嵌套级别为非零时,它非常缓慢,就像enter a, 0
。
在Ryzen上,87 cycles + 7 * nesting level
为12 oups,每16周期吞吐量为一个。
enter
很好,但是:在Intel CPU上只有3微秒。 (尽管这仍然比leave
/ mov %rbp, %rsp
多一个。3个不包含堆栈同步uop;即使堆栈引擎在pop %rbp
之前是同步的,它也是3个。)
使用leave
的唯一原因是以牺牲速度为代价来优化代码大小。但是,即使enter
也不在乎代码大小,无法为此选择一个选项。
即使gcc -Os
(将使用clang -Oz
/ push $1
来保存2个字节而不是pop %rax
)也不使用mov $1, %eax
。 (Godbolt compiler explorer)
但是enter
甚至都没有保存代码大小,因此简直太糟糕了。
我遵循一本手册,该手册说程序以ENTER开始输入
这是一个(过时且不推荐使用的)选项。
如果您想编写自己的编译器来编写慢速代码,请继续。