This question is about x86 assembly but I provide an example in C because I tried to check what GCC was doing.
As I was following various assembly guides, I have noticed that people, at least the few whose materials I have been reading, seem to be in a habit of allocating stack variables closer to rsp than rbp.
I then checked what GCC would do and it seems to be the same.
In the disassembly below, first 0x10 bytes are reserved and then the result of calling leaf goes via eax to rbp-0xc and the constant value 2 goes to rbp-0x8, leaving room between rbp-0x8 and rbp for variable "q".
I could imagine doing it in the other direction, first assigning to an address at rbp and then at rbp-0x4, i.e. doing it in the direction of rbp to rsp, then leaving some space between rbp-0x8 and rsp for "q".
What I am not sure about is whether what I am observing is as things should be because of some architectural constraints that I better be aware of and adhere to or is it purely an artifact of this particular implementation and a manifestation of habits of the people whose code I read that I should not assign any significance to, e.g. this needs to be done in one direction or the other and it does not matter which one as long it is consistent.
Or perhaps I am just reading and writing trivial code for now and this will go both ways as I get to something more substantial in some time?
I would just like to know how I should go about it in my own assembly code.
All of this is on Linux 64-bit, GCC version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04). Thanks.
00000000000005fa <leaf>:
5fa: 55 push rbp
5fb: 48 89 e5 mov rbp,rsp
5fe: b8 01 00 00 00 mov eax,0x1
603: 5d pop rbp
604: c3 ret
0000000000000605 <myfunc>:
605: 55 push rbp
606: 48 89 e5 mov rbp,rsp
609: 48 83 ec 10 sub rsp,0x10
60d: b8 00 00 00 00 mov eax,0x0
612: e8 e3 ff ff ff call 5fa <leaf>
617: 89 45 f4 mov DWORD PTR [rbp-0xc],eax ; // <--- This line
61a: c7 45 f8 02 00 00 00 mov DWORD PTR [rbp-0x8],0x2 ; // <-- And this too
621: 8b 55 f4 mov edx,DWORD PTR [rbp-0xc]
624: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8]
627: 01 d0 add eax,edx
629: 89 45 fc mov DWORD PTR [rbp-0x4],eax
62c: 8b 45 fc mov eax,DWORD PTR [rbp-0x4]
62f: c9 leave
630: c3 ret
Here is the C code:
int leaf() {
return 1;
}
int myfunc() {
int x = leaf(); // <--- This line
int y = 2; // <-- And this too
int q = x + y;
return q;
}
int main(int argc, char *argv[]) {
return myfunc();
}
How I compile it:
gcc -O0 main.c -o main.bin
How I disassemble it:
objdump -d -j .text -M intel main.bin