堆栈分配太大

时间:2018-11-07 00:52:22

标签: c gcc assembly x86 calling-convention

我写了下面的代码。

int main (int argc, char *argv[])
{
  char *uargv[3];

  uargv[0] = "echo";
  uargv[1] = "hello!";
  uargv[2] = 0;

  exec("echo", uargv);

  exit();
}

并使用gcc 5.4进行编译。

下面是上面程序的汇编代码。

0x00: lea    0x4(%esp),%ecx
0x04: and    $0xfffffff0,%esp
0x07: pushl  -0x4(%ecx)
0x0a: push   %ebp 
0x0b: mov    %esp,%ebp
0x0d: push   %ecx 
0x0e: sub    $0x14,%esp
0x11: movl   $0x7c3,-0x14(%ebp)
0x18: movl   $0x7c8,-0x10(%ebp)
0x1f: movl   $0x0,-0xc(%ebp)
0x26: sub    $0x8,%esp
0x29: lea    -0x14(%ebp),%eax
0x2c: push   %eax 
0x2d: push   $0x7c3
0x32: call   2ce <exec>
0x37: add    $0x10,%esp
0x3a: call   296 <exit>

我不明白上面的汇编代码的三部分。

首先,在0x00、0x04、0x07、0x0a,0x0b,0x0d的代码中,其工作方式如下。

0x00: save ebp+4 to ecx, and it is address of argc.
0x04: align esp with 16 byte
0x07: push ecx-4 to stack, and it is return address.
0x0a ~ 0x0b: setup ebp
0x0d: push ecx to stack, and it is address of argc.

我想知道为什么它再次推送返回地址,为什么还要推送argc地址。

这是我的第一个问题。

其次,它在0x0e指令中为局部变量uargv分配堆栈。

但是,uargv的大小只有12个字节。

但是它分配了20个字节。

如果是由于16字节对齐,为什么将局部变量保存在esp + 4中,而不是esp中(ebp + 0x14与esp + 4相同)。

第三,为什么0x26指令为堆栈分配更多的8个字节?

不需要更多的堆栈空间,因为exec的参数通过push指令保存在堆栈中。

谢谢。

0 个答案:

没有答案