I have a small program, written in C, echo():
/* Read input line and write it back */
void echo() {
    char buf[8];  /* Way too small! */
    gets(buf);
    puts(buf);
}
The corresponding assembly code:
1 echo:
2 pushl %ebp                //Save %ebp on stack
3 movl  %esp, %ebp          
4 pushl %ebx                //Save %ebx
5 subl  $20, %esp           //Allocate 20 bytes on stack
6 leal  -12(%ebp), %ebx     //Compute buf as %ebp-12
7 movl  %ebx, (%esp)        //Store buf at top of stack
8 call  gets                //Call gets
9 movl  %ebx, (%esp)        //Store buf at top of stack
10 call puts                //Call puts
11 addl $20, %esp           //Deallocate stack space
12 popl %ebx                //Restore %ebx
13 popl %ebp                //Restore %ebp
14 ret                      //Return
I have a few questions.
- Why does the %esp allocate 20 bytes? The buf is 8 bytes, why the extra 12? 
- The return address is right above where we pushed %ebp right? (Assuming we draw the stack upside down, where it grows downward) What is the purpose of the old %ebp (which the current %ebp is pointing at, as a result of line 3)? 
- If i want to change the return address (by inputting anything more than 12 bytes), it would change where echo() returns to. What is the consequence of changing the old %ebp (aka 4 bytes before the return address)? Is there any possibility of changing the return address or where echo returns to by just changing the old %ebp? 
- What is the purpose of the %ebp? I know its the frame pointer but, what is that? 
- Is it ever possible for the compiler to put the buffer somewhere that is not right next to where the old %ebp is stored? Like if we declare buf[8] but it stores it at -16(%ebp) instead of -12(%ebp) on line 6? 
*c code and assembly copied from Computer Systems - A programmer's Perspective 2nd ed.
** Using gets() because doing buffer overflows 
 
    