Компилятор: MinGW 5.1.4. Компилятор запускал без ключей. Исходный текст программы: Код (Text): #include <stdio.h> main() { int a=5,b=6; int sum=a+b; printf("Summary is: %d\n",sum); return 0; } Полученный дизассемблерный листинг для процедуры main: Код (Text): main proc near var_18= dword ptr -18h var_14= dword ptr -14h var_10= dword ptr -10h c = dword ptr -0Ch b = dword ptr -8 a = dword ptr -4 push ebp mov ebp, esp sub esp, 18h ; выделение памяти под локальные переменные and esp, 0FFFFFFF0h ; (1) mov eax, 0 add eax, 0Fh add eax, 0Fh shr eax, 4 shl eax, 4 mov [ebp+var_10], eax mov eax, [ebp+var_10] call sub_401860 call sub_4013E0 ; (2) mov [ebp+a], 5 ;a=5 mov [ebp+b], 6 ;b=6 mov eax, [ebp+b] add eax, [ebp+a] mov [ebp+c], eax ;c = a + b mov eax, [ebp+c] mov [esp+18h+var_14], eax mov [esp+18h+var_18], offset aSummaryIsD ; "Summary is: %d\n" call printf ; printf("Summary is: %d\n",c) mov eax, 0 leave retn main endp Объясните, пожалуйста, код от (1) до (2).
Приведи код sub_401860 и sub_4013E0. Или лучше бинарник выложи. На первый взгляд - просто скомпилировано вообще без какой-либо оптимизации.
Да, это без оптимизации. Код (Text): sub_401860 proc near ; CODE XREF: main+20p push ecx mov ecx, esp add ecx, 8 loc_401866: cmp eax, 1000h jb short loc_40187D sub ecx, 1000h or dword ptr [ecx], 0 sub eax, 1000h jmp short loc_401866 ; --------------------------------------------------------------------------- loc_40187D: sub ecx, eax or dword ptr [ecx], 0 mov eax, esp mov esp, ecx mov ecx, [eax] mov eax, [eax+4] jmp eax sub_401860 endp Код (Text): sub_4013E0 proc near ; CODE XREF: sub_401150+D5p main+25p push ebp mov eax, ds:dword_404020 mov ebp, esp test eax, eax jz short loc_4013F0 pop ebp retn ; --------------------------------------------------------------------------- align 10h loc_4013F0: ; CODE XREF: sub_4013E0+Aj pop ebp mov eax, 1 mov ds:dword_404020, eax jmp short sub_401380 sub_4013E0 endp Извините, но файл прикрепить не могу, поэтому привожу листинги.
Arman sub esp, 18h ; выделение памяти под локальные переменные Не только, тут место и для аргументов, в данном случае, printf'а. and esp, 0FFFFFFF0h ; (1) gcc хочет чтобы указатель стека был выровнен по ближайшей (нижней) 16-тибайтной границе. call sub_4013E0 ; (2) Это вызов viod __main(void). Например, вот что по этому поводу написано в GNU Compiler Collection Internals For gcc version 4.4.0 (pre-release): "The __main function is defined in ‘libgcc2.c’ and runs the global constructors." Полный текст смотри/ищи в gccint.pdf). ps чтобы увидеть __main вместо sub_4013E0 достаточно указать компилятору, генерировать asm-листинг при помощи ключа -S.