1.16. LOOPS
pop ebp
ret 0
_main ENDP
As we see, nothing special.
GCC 4.4.1 emits almost the same code, with one subtle difference:
Listing 1.163: GCC 4.4.1
main proc near
var_20 = dword ptr -20h
var_4 = dword ptr -4
push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 20h
mov [esp+20h+var_4], 2 ; (i) initializing
jmp short loc_8048476
loc_8048465:
mov eax, [esp+20h+var_4]
mov [esp+20h+var_20], eax
call printing_function
add [esp+20h+var_4], 1 ; (i) increment
loc_8048476:
cmp [esp+20h+var_4], 9
jle short loc_8048465 ; if i<=9, continue loop
mov eax, 0
leave
retn
main endp
Now let’s see what we get with optimization turned on (/Ox):
Listing 1.164: Optimizing MSVC
_main PROC
push esi
mov esi, 2
$LL3@main:
push esi
call _printing_function
inc esi
add esp, 4
cmp esi, 10 ; 0000000aH
jl SHORT $LL3@main
xor eax, eax
pop esi
ret 0
_main ENDP
What happens here is that space for theivariable is not allocated in the local stack anymore, but uses
an individual register for it,ESI. This is possible in such small functions where there aren’t many local
variables.
One very important thing is that thef()function must not change the value inESI. Our compiler is sure
here. And if the compiler decides to use theESIregister inf()too, its value would have to be saved
at the function’s prologue and restored at the function’s epilogue, almost like in our listing: please note
PUSH ESI/POP ESIat the function start and end.
Let’s try GCC 4.4.1 with maximal optimization turned on (-O3option):
Listing 1.165: Optimizing GCC 4.4.1
main proc near
var_10 = dword ptr -10h