Reputation: 391
By way of learning more about assembly language / computer architecture, I wrote the following C code:
int my_caller() {
int a = my_callee(0xbaba);
return a;
}
int my_callee(int a) {
return a;
}
This disassembles (on my machine; with some added comments) to the following:
; my_caller function
push ebp
mov ebp,esp
sub esp,byte +0x18
sub esp,byte +0xc
push dword 0xbaba
call dword 0x1e
add esp,byte +0x10
mov [ebp-0xc],eax
mov eax,[ebp-0xc]
leave
ret
; my_callee function
push ebp
mov ebp,esp
mov eax,[ebp+0x8]
pop ebp
ret
Regarding treatment of esp
in my_caller
:
sub esp
by 0x18 and then 0xc; why not just a single sub of 0x24?my_callee
, what is the point of add esp,byte 0x10
? The leave
instruction is going to annul this anyway with the implicit mov esp,ebp
.Thanks.
Upvotes: 2
Views: 179
Reputation: 364200
You told the compiler you'd like it to compile fast, not to make good code, and to make code that was easy for a debugger like gdb
to interact with. In -O0
mode, gcc doesn't optimize much between different parts of the same function, hence the add esp, 0x10
to pop the stack after the call, and then leave
separately.
-O0
is terribly noisy (full of stores/reloads), so it sucks to read as a human.
You'll have better luck looking at functions that take a couple int
args and return an int
. You can use __attribute__((noinline))
on functions to stop them from inlining.
Have a look at a simple function on the Godbolt compiler explorer, for example. See also the x86 tag wiki.
Upvotes: 2