2016-10-12 12 views
0

Я пытаюсь выучить язык ассемблера на примере, или компиляции простых файлов C с GCC, используя опцию -S, синтаксиса интел и CFI вызовы инвалидов (любой другой свободный путь чрезвычайно запутаннымGCC компилируется сборки

My C файл буквально int main() {return 0;}, но GCC выплевывает это:

.file "simpleCTest.c" 
    .intel_syntax noprefix 
    .def ___main; .scl 2; .type 32; .endef 
    .text 
    .globl _main 
    .def _main; .scl 2; .type 32; .endef 
_main: 
    push ebp 
    mov ebp, esp 
    and esp, -16 
    call ___main 
    mov eax, 0 
    leave 
    ret 
    .ident "GCC: (GNU) 5.3.0" 

Мой реальный вопрос почему основная функция имеет каких-либо инструкций процессора (push edp, mov edp, esp и т.д.) Являются ли эти даже нужно (я предполагаю, что это будет? способ управления данными для подготовки/закрытия программ, но я не уверен)? Почему? Sn't это просто выпустить заявление ret после основной функции? Также почему существуют две основные функции (_main & ___main)?

Подводя итог, почему это не так?

.def _main 
_main: 
mov eax, 0 ;(for return integer) 
ret 
+2

Включить оптимизацию ('-O2'). Обратите внимание, что 'main' является особенным, вам может быть лучше, если вы делаете' int foo() {return 0;} 'Также, попытка понять код, сгенерированный компилятором, не всегда легко. – Jester

+1

Похоже, вы на Windows? Причина в том, что '___ main' вызывается - это вызов любых зарегистрированных статических конструкторов. 'и esp, -16' состоит в том, чтобы убедиться, что стек равен 16 байтам до вызова' ___ main'. Esp/ebp/leave часто являются стандартными кодовыми табличками для стековых кадров. Может пригодиться при отсутствии данных об удалении стека при использовании с отладчиком, но не требуется. –

+0

Есть несколько хороших ссылок в [x86 tag wiki] (http://stackoverflow.com/tags/x86/info), которые могут показаться вам интересными. –

ответ

0

GCC выплевывает это

Это, вероятно, будет немного понятнее, если вы на самом деле была ваша основная функция сделать некоторые вещи, как ни странно, в том числе вызывая другую функцию.

Скомпилированный код настраивает кадр, с помощью которого можно ссылаться на его переменные стека с первым кодом операции, mov ebp, esp. Это было бы полезно, если бы у вас были переменные, к которым можно было бы ссылаться, например, с ebp и константой. Затем он выравнивает стек с кратным 16 байтам с инструкцией AND, то есть он говорит, что он не будет использовать от 0 до 15 байт предоставленного стека, так что [esp] выравнивается с кратным 16 байт. Это было бы важно из-за использования используемых конвенций.

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

Мой реальный вопрос почему основная функция имеет процессорные инструкции

Это установка материала для вещей, которые вы не делаете (но что нетривиальные программы будут делать), и не делает самую оптимизированную программу «return 0», которую он мог бы сделать. Имея базовый указатель, который в основном представляет собой резервную копию исходного указателя стека, программа может ссылаться на локальные переменные как смещение плюс базовый указатель (включая подразумеваемые вещи, которые вы не используете, как количество аргументов, указатель на указатели на список аргументов и указатель на среду), и имея указатель стека, который является кратным 16, программа может совершать вызовы функций в соответствии со своим стандартом вызова.

+0

По-прежнему, почему в программе есть две сети? – user2624583

 Смежные вопросы

  • Нет связанных вопросов^_^