For the record, I've read all stackexchange relevant answers on the topic (here and here) plus other articles to fully grasp the concepts of memory alignment and CPU natural boundaries.
But for some reason, I just can't understand the meaning of the following main preamble (given out by radare2
)
(fcn) sym.main 99
| sym.main (int argc, char **argv, char **envp);
| ; var int local_78h @ ebp-0x78
| ; arg int arg_10h @ ebp+0x10
| ; var int local_4h @ esp+0x4
| ; DATA XREF from entry0 (0x8048417)
| 0x0804867d 55 push ebp
| 0x0804867e 89e5 mov ebp, esp
| 0x08048680 81ec88000000 sub esp, 0x88
| 0x08048686 83e4f0 and esp, 0xfffffff0
| 0x08048689 b800000000 mov eax, 0
| 0x0804868e 83c00f add eax, 0xf
| 0x08048691 83c00f add eax, 0xf
| 0x08048694 c1e804 shr eax, 4
| 0x08048697 c1e004 shl eax, 4
| 0x0804869a 29c4 sub esp, eax
Breakdown
There seems to be a local array on the stack frame that takes up 78h = 120d bytes on the stack, indicated by this line :
| ; var int local_78h @ ebp-0x78
So far so good.
Now the stack pointer is moved to make space for such an array on the stack, manipulating esp
to make sure the stack is aligned on 16-bytes boundaries :
| 0x08048680 81ec88000000 sub esp, 0x88
| 0x08048686 83e4f0 and esp, 0xfffffff0
Which effectively makes esp
a multiple of at least 16 (least significant nibble zeroed out), but let's for the sake of mathematical rigor say that esp
is now a multiple of 16k, with k an arbitrary integer.
All this makes perfect sense (see here and here to fully understand the need for 16-bytes stack alignment, having to do with SSE and whatnot).
Now what I really can't seem to wrap my head around is the relevance of the subsequent instructions :
| 0x08048689 b800000000 mov eax, 0
| 0x0804868e 83c00f add eax, 0xf
| 0x08048691 83c00f add eax, 0xf
| 0x08048694 c1e804 shr eax, 4
| 0x08048697 c1e004 shl eax, 4
| 0x0804869a 29c4 sub esp, eax
Which as far as I could understand :
1 - Made eax
equal to 10h (by the way why all these instructions to get to such a simple result for eax
? Why not just make a mov eax, 0x10
?)
2 - Subtract that quantity from esp
, which is just gonna zero out the least significant 1 bit in esp
(given that the first nibble is null anyway) which is just gonna make esp
a multiple of 16(k+1), thus making the stack aligned on 32-bytes boundaries if it was aligned on 16-bytes boundaries, or make it aligned on 64-bytes boundaries if it was aligned on 32-bytes boundaries, and so on and so forth.
What do we need that for ?
Is there something I got wrong in this whole analysis ?