Memory allocation on the stack

Here is a sample function reverse engineered from an easy program:

main            proc near
var_70          = dword ptr -70h
var_6C          = dword ptr -6Ch
var_68          = dword ptr -68h
i_2             = dword ptr -54h
i               = dword ptr -4
push    ebp
mov     ebp, esp
and     esp, 0FFFFFFF0h
sub     esp, 70h
mov     [esp+70h+i], 0
jmp     short loc_804840A
￼￼￼loc_80483F7:
mov     eax, [esp+70h+i]
mov     edx, [esp+70h+i]
mov     [esp+eax*4+70h+i_2], edx
loc_804840A:
cmp     [esp+70h+i], 13h
jle     short loc_80483F7
mov     [esp+70h+i], 0
jmp     short loc_8048441
loc_804841B:
mov    eax, [esp+70h+i]
mov    edx, [esp+eax*4+70h+i_2]
mov    eax, offset aADD ; "a[%d]=%d\n"
mov    [esp+70h+var_68], edx
mov    edx, [esp+70h+i]
mov    [esp+70h+var_6C], edx
mov    [esp+70h+var_70], eax
call   _printf
loc_8048441:
cmp    [esp+70h+i], 13h
jle     short loc_804841B
mov    eax, 0
leave
retn
main   endp

C code

#include <stdio.h>
int main() {
int a;
int i;
for (i=0; i<20; i++)
a[i]=i*2;
for (i=0; i<20; i++)
printf ("a[%d]=%d\n", i, a[i]);
return 0;
}

My questions are:

1. Why is memory not allocated consecutively and why are some parts of the memory in between esp + 70h -54h and esp + 70h -68h not used?

2. In sub esp, 70h, the number 70h seems to be a random number in a different program, and it is often larger than we need. Why don't the compiler just allocate what we need?

In your case because int is 4 bytes and you want 20 element

int a // --> 20 * 4 = 0x50

so it is very normal for i and i_2

The other thing is that your compiler didn't push printf arguments into stack. It pre-allocated the stack location in

var_70 = dword ptr -70h
var_6C = dword ptr -6Ch
var_68 = dword ptr -68h

and called the function like this

mov    edx, [esp+eax*4+70h+i_2]
mov    eax, offset aADD ; "a[%d]=%d\n"
mov    [esp+70h+var_68], edx
mov    edx, [esp+70h+i]
mov    [esp+70h+var_6C], edx
mov    [esp+70h+var_70], eax
call   _printf

But there is 2 reason for such a thing (not your case)...

1. The Compiler align the buffer for performance reasons and ease of cache. in addition unaligned buffers cause failure in some cases like Windows API calls and make debugging hard, so the compilers align every buffer to avoid this kind of failure.

2. Some safe compilation allocate random number after buffers to prevent successful exploitation of buffer overruns. for example:

and esp, 0FFFFFFF0h

yeap! as @DCoder commented, you asked it Here before.

• In that question, the answers says the temporary variables, like var_70 ,generated due to copy params are not local variables. But I think that's not correct. May 21 '14 at 3:12