堆栈是怎么被使用的?

堆栈是如何被使用的???
#include   <string.h>
int   main()
{
      char   str1[10];
      strcpy(str1,   "okhaha12345678901234567890123456789 ");
      return   0;
}
以上源程序,以下是反汇编的代码
编译使用gcc   3.4.2
gcc   -c   test.c   -g  
反汇编使用IDA   Pro

public   _main
_main proc   near

var_38 =   dword ptr   -38h
var_34 =   dword ptr   -34h
var_1C =   dword ptr   -1Ch
var_18 =   dword ptr   -18h

push ebp
mov ebp,   esp
sub esp,   38h     //这里为什么是38呢???
and esp,   0FFFFFFF0h
mov eax,   0
add eax,   0Fh
add eax,   0Fh
shr eax,   4
shl eax,   4
mov [ebp+var_1C],   eax   //为什么这里从1C开始???
mov eax,   [ebp+var_1C]
call __alloca
call ___main
mov [esp+38h+var_34],   offset   aOkhaha12345678   ;   "okhaha12345678901234567890123456789 "
lea eax,   [ebp+var_18]   //18里面到底有什么?
mov [esp+38h+var_38],   eax
call _strcpy
mov eax,   0
leave
retn
_main endp

详细问题见上面注释中的。
那个esp   -   38h然后在与上一个FFFFFF0h我一直不明白,为什么这么搞??
还有从ebp-4开始,到ebp-1C之前,还有很多的堆栈空间呢,为什么都不用,正好要用ebp-1C呢?
还有就是后面调strcpy的时候,需要传两个参数,一个参数是常量字符串,没什么疑问,那个参数在data段,而另一个,目的地址到底在哪里呢?
为什么正好在ebp-18h那个地方呢?
那个里面有什么呢?

我想从反汇编代码中看出strcpy的两个参数的实际长度,也就是要依此判断是否产生缓冲区溢出,上面给出的是最最简单的情况,但是那个ebp-18h让我百思不得其解啊~~

------解决方案--------------------
你先把下面一行去掉,编译一下,看看是什么情况?嵌套的函数共享程序的堆栈,所以情况就负责了。
strcpy(str1, "okhaha12345678901234567890123456789 ");