I've written a basic C program that defines an integer variable x, sets it to zero and returns the value of that variable:
#include <stdio.h>
int main(int argc, char **argv) {
int x;
x = 0;
return x;
}
When I dump the object code using objdump (compiled on Linux X86-64 with gcc):
0x0000000000400474 <main+0>: push %rbp
0x0000000000400475 <main+1>: mov %rsp,%rbp
0x0000000000400478 <main+4>: mov %edi,-0x14(%rbp)
0x000000000040047b <main+7>: mov %rsi,-0x20(%rbp)
0x000000000040047f <main+11>: movl $0x0,-0x4(%rbp)
0x0000000000400486 <main+18>: mov -0x4(%rbp),%eax
0x0000000000400489 <main+21>: leaveq
0x000000000040048a <main+22>: retq
I can see the function prologue, but before we set x to 0 at address 0x000000000040047f
there are two instructions that move %edi and %rsi onto the stack. What are these for?
In addition, unlike where we set x to 0, the mov instruction as shown in GAS syntax does not have a suffix.
If the suffix is not specified, and there are no memory operands for the instruction, GAS infers the operand size from the size of the destination register operand.
In this case, are -0x14(%rsbp)
and -0x20(%rbp)
both memory operands and what are their sizes? Since %edi is a 32 bit register, are 32 bits moved to -0x14(%rsbp)
whereas since %rsi is a 64 bit register, 64 bits are moved to %rsi,-0x20(%rbp)
?