I’m trying to learn basic assembly. I wrote a simple program in C to translate to assembly:
void myFunc(int x, int y) {
int z;
}
int main() {
myFunc(20, 10);
return 0;
}
This is what I thought the correct translation of the function would be:
.text
.globl _start
.type myFunc, @function
myFunc:
pushl %ebp #Push old ebp register on to stack
movl %esp, %ebp #Move esp into ebp so we can reference vars
sub $4, %esp #Subtract 4 bytes from esp to make room for 'z' var
movl $2, -4(%ebp) #Move value 2 into 'z'
movl %ebp, %esp #Restore esp
popl %ebp #Set ebp to 0?
ret #Restore eip and jump to next instruction
_start:
pushl $10 #Push 10 onto stack for 'y' var
pushl $20 #Push 20 onto stack for 'x' var
call myFunc #Jump to myFunc (this pushes ret onto stack)
add $8, %esp #Restore esp to where it was before
movl $1, %eax #Exit syscall
movl $0, %ebx #Return 0
int $0x80 #Interrupt
Just to double check it I ran it in gdb and was confused by the results:
(gdb) disas myFunc
Dump of assembler code for function myFunc:
0x08048374 <myFunc+0>: push ebp
0x08048375 <myFunc+1>: mov ebp,esp
0x08048377 <myFunc+3>: sub esp,0x10
0x0804837a <myFunc+6>: leave
0x0804837b <myFunc+7>: ret
End of assembler dump.
Why at 0x08048377 did gcc subtract 0x10 (16 bytes) from the stack when an integer is 4 bytes in length?
Also, is the leave instruction equivalent to the following?
movl %ebp, %esp #Restore esp
popl %ebp #Set ebp to 0?
Using:
gcc version 4.3.2 (Debian 4.3.2-1.1)
GNU gdb 6.8-debian
Your GDB is configured to print out Intel instead of AT&T assembly syntax – turn that off before it confuses you more than it already has.
The stack pointer (
%esp) is required to always be aligned to a 16-byte boundary. That’s probably where thesub esp,0x10is coming from. (It’s unnecessary, but GCC has historically been bad at noticing that stack adjustments are unnecessary.) Also, your function doesn’t do anything interesting, so the body has been optimized out. You should have compiled this code:That’ll produce assembly language that’s easier to map back to the original C. GCC would still be allowed to produce
and nothing else, but it probably won’t unless you use
-O3 -fwhole-program😉