Я сам изучаю, как работают компиляторы. Я изучаю, читая разборку кода, созданного GCC, из небольших 64-разрядных программ Linux.
Я написал эту программу на C:
#include <stdio.h>
int main()
{
for(int i=0;i<10;i++){
int k=0;
}
}
После использования objdump я получаю:
00000000004004d6 <main>:
4004d6: 55 push rbp
4004d7: 48 89 e5 mov rbp,rsp
4004da: c7 45 f8 00 00 00 00 mov DWORD PTR [rbp-0x8],0x0
4004e1: eb 0b jmp 4004ee <main+0x18>
4004e3: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0
4004ea: 83 45 f8 01 add DWORD PTR [rbp-0x8],0x1
4004ee: 83 7d f8 09 cmp DWORD PTR [rbp-0x8],0x9
4004f2: 7e ef jle 4004e3 <main+0xd>
4004f4: b8 00 00 00 00 mov eax,0x0
4004f9: 5d pop rbp
4004fa: c3 ret
4004fb: 0f 1f 44 00 00 nop DWORD PTR [rax+rax*1+0x0]
Теперь у меня есть некоторые сомнения.
-
Что это за NOP в конце, и почему он там? (Выравнивание?)
-
Я компилирую с
gcc -Wall <program.c>
. Почему я не получаю предупреждениеcontrol reaches end of non-void function
? -
Почему компилятор не выделяет пространство в стеке с помощью
sub rsp,0x10
? Почему он не использует регистрrbp
для ссылки на данные локального стека?PS: Если я вызываю функцию (например,
printf
) в циклеfor
, почему компилятор неожиданно генерируетsub rsp,0x10
? Почему он все еще ссылается на локальные данные с регистромrsp
. Я ожидаю, что сгенерированный код ссылается на локальные данные стека с помощьюrbp
!