I am trying to understand some basic assembly code concepts and am getting stuck on how the assembly code determines where to place things on the stack and how much space to give it.
To start playing around with it, I entered this simple code in godbolt.org's compiler explorer.
int main(int argc, char** argv) {
int num = 1;
num++;
return num;
}
and got this assembly code
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-20], edi
mov QWORD PTR [rbp-32], rsi
mov DWORD PTR [rbp-4], 1
add DWORD PTR [rbp-4], 1
mov eax, DWORD PTR [rbp-4]
pop rbp
ret
So a couple questions here:
Shouldn't the parameters have been placed on the stack before the call? Why are argc and argv placed at offset 20 and 32 from the base pointer of the current stack frame? That seems really far down to put them if we only need room for the one local variable num. Is there a reason for all of this extra space?
The local variable is stored at 4 below the base pointer. So if we were visualizing this in the stack and say the base pointer currently pointed at 0x00004000 (just making this up for an example, not sure if that's realistic), then we place the value at 0x00003FFC, right? And an integer is size 4 bytes, so does it take up the memory space from 0x00003FFC downward to 0x00003FF8, or does it take up the memory space from 0x00004000 to 0x00003FFC?
It looks like stack pointer was never moved down to allow room for this local variable. Shouldn't we have done something like
sub rsp, 4
to make room for the local int?
And then if I modify this to add more locals to it:
int main(int argc, char** argv) {
int num = 1;
char *str1 = {0};
char *str2 = "some string";
num++;
return num;
}
Then we get
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-36], edi
mov QWORD PTR [rbp-48], rsi
mov DWORD PTR [rbp-4], 1
mov QWORD PTR [rbp-16], 0
mov QWORD PTR [rbp-24], OFFSET FLAT:.LC0
add DWORD PTR [rbp-4], 1
mov eax, DWORD PTR [rbp-4]
pop rbp
ret
So now the main arguments got pushed down even further from base pointer. Why is the space between the first two locals 12 bytes but the space between the second two locals 8 bytes? Is that because of the sizes of the types?