почему он использует movl вместо push?

обратите внимание на этот код:

#include  void a(int a, int b, int c) { char buffer1[5]; char buffer2[10]; } int main() { a(1,2,3); } 

после этого :

 gcc -S ac 

эта команда показывает наш исходный код в сборке.

теперь мы можем видеть в основной функции, мы никогда не используем команду «push», чтобы вставить аргументы функции a в стек. и вместо этого он использовал «movel»

 main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $16, %esp movl $3, 8(%esp) movl $2, 4(%esp) movl $1, (%esp) call a leave 

почему это происходит? в чем разница между ними?

    Вот что должно сказать об этом руководство gcc:

     -mpush-args -mno-push-args Use PUSH operations to store outgoing parameters. This method is shorter and usually equally fast as method using SUB/MOV operations and is enabled by default. In some cases disabling it may improve performance because of improved scheduling and reduced dependencies. -maccumulate-outgoing-args If enabled, the maximum amount of space required for outgoing arguments will be computed in the function prologue. This is faster on most modern CPUs because of reduced dependencies, improved scheduling and reduced stack usage when preferred stack boundary is not equal to 2. The drawback is a notable increase in code size. This switch implies -mno-push-args. 

    По -maccumulate-outgoing-args видимому -maccumulate-outgoing-args включен по умолчанию, переопределяя -mpush-args . Явная компиляция с -mno-accumulate-outgoing-args возвращает здесь метод PUSH .

    Этот код просто непосредственно помещает константы (1, 2, 3) в позиции смещения из (обновленного) указателя стека (esp). Компилятор выбирает «push» вручную с тем же результатом.

    «push» как устанавливает данные, так и обновляет указатель стека. В этом случае компилятор сокращает это только до одного обновления указателя стека (по сравнению с тремя). Интересный эксперимент состоял бы в том, чтобы попытаться изменить функцию «а», чтобы принять только один аргумент, и посмотреть, изменяется ли шаблон инструкции.

    gcc выполняет всевозможные оптимизации, включая выбор инструкций, основанных на скорости выполнения конкретного процессора, для которого оптимизирован. Вы заметите, что такие вещи, как x *= n , часто заменяются сочетанием SHL, ADD и / или SUB, особенно когда n является константой; в то время как MUL используется только тогда, когда средняя продолжительность выполнения (и кеш / etc. footprints) комбинации SHL-ADD-SUB будет превышать значение MUL, или n не является константой (и, следовательно, использование циклов с shl-add-sub будет дороже).

    В случае аргументов функции: MOV может распараллеливаться аппаратным обеспечением, а PUSH – не может. (Второй PUSH должен ждать завершения первого PUSH из-за обновления регистра esp.) В случае аргументов функции MOV могут запускаться параллельно.

    Возможно ли это на OS X? Я где-то читал, что требуется, чтобы указатель стека был выровнен по 16-байтовым границам. Возможно, это объяснит такое генерирование кода.

    Я нашел статью: http://blogs.embarcadero.com/eboling/2009/05/20/5607

    Набор инструкций Pentium не имеет инструкции для нажатия константы в стек. Таким образом, использование push будет медленным: программа должна будет поместить константу в регистр и нажать на регистр:

     ... movl $1, %eax pushl %eax ... 

    Таким образом, компилятор обнаруживает, что использование movl выполняется быстрее. Я думаю, вы можете попробовать назвать свою функцию переменной вместо константы:

     int x; scanf("%d", &x); // make sure x is not a constant a(x, x, x); 
    Interesting Posts

    Что означает пробел в селекторе CSS? т.е. в чем разница между .classA.classB и .classA .classB?

    Использовать загрузочный vhd с Virtualbox

    Использование MySQL “IF EXISTS”

    Существует ли альтернатива ANSI SQL для ключевого слова MYSQL LIMIT?

    Как я могу использовать PHP, чтобы проверить, пуст ли каталог?

    Изменить UUID под Linux?

    Почему большой кусок объекта и почему мы заботимся?

    USB-накопитель, не отображающий полный размер

    Проверьте, существует ли значение в dataTable?

    Узнайте, прокручивается ли ListView до конца?

    Почему мое соединение отказалось при переадресации портов?

    Как слить скаляр в вектор без компилятора, теряющего инструкцию обнуления верхних элементов? Ограничение дизайна в встроенных средах Intel?

    Как я могу получить тело ответа HTTP как строку в Java?

    Почему мой загруженный диск не будет сохранен для пользователя после перезагрузки?

    Общественная безопасность WiFi

    Давайте будем гением компьютера.