GCC никогда не будет излучать enter
, потому что он очень медленный по сравнению с обычной установкой указателя кадра, состоящей из 2 или 3 однопроходных инструкций.
(Если он вообще создает указатель кадра; gcc -O1
и выше включает -fomit-frame-pointer
. За исключением случаев оптимизации по размеру, поскольку в режимах адресации x(%rsp)
используется дополнительный байт по сравнению с режимами x(%rbp)
.)
# 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
В частности, на Skylake enter
составляет 12 мопов и по одному на 8-тактную пропускную способность для enter a, 0
( Таблицы команд Агнера Фога ). С ненулевым уровнем вложенности он безумно медленный, как 87 cycles + 7 * nesting level
.
На Райзене enter
равен 12 моп, с пропускной способностью по одному на 16 циклов.
leave
хорошо, хотя: это только 3 моп на процессорах Intel. (Тем не менее, это на единицу больше, чем mov %rbp, %rsp
/ pop %rbp
. 3 мопа не включают в себя синхронизацию стека; это 3, даже если механизм стека был синхронизирован до leave
.)
Единственная причина использования enter
- оптимизация под размер кода за счет скорости. Но даже gcc -Os
недостаточно заботится о размере кода, чтобы иметь возможность для этого.
Даже clang -Oz
(который будет использовать push $1
/ pop %rax
для сохранения 2 байтов против mov $1, %eax
) не использует enter
. ( Проводник компилятора Godbolt )
Но enter 0,0
даже не сохраняет размер кода, так что это просто плохо.
И я следую инструкции, в которой говорится, что запуск программы начинается с ENTER
Это один (устаревший и не рекомендуемый) вариант.
Если вы хотите написать свой собственный компилятор, который делает медленный код, продолжайте.