0

I wrote below code.

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

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

  exec("echo", uargv);

  exit();
}

And compiled with gcc 5.4.

Below is assembly code of above program.

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>

I can't understand three part of above assembly code.

First, in the code that is in 0x00, 0x04, 0x07, 0x0a, 0x0b, 0x0d works as follows.

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.

I wonder why it push return address again and why it push address of argc.

It was my first question.

Second, it allocate stack in 0x0e instruction for local variable, uargv.

However, the size of uargv is only 12 byte.

But it allocate 20 byte.

If it is because of 16 byte alignment, why local variables are saved in esp+4, not esp (ebp+0x14 is same with esp+4).

Third, why 0x26 instruction allocate more 8 byte for stack?

More space in stack is no needed, because arguments of exec are saved in stack by push instruction.

Thank you.

melpomene
  • 84,125
  • 8
  • 85
  • 148
Joontaek Oh
  • 152
  • 9
  • The compiler is allowed to do whatever it wants for its local variables, especially if you forgot to enable optimizations. When calling other functions it must follow the calling convention which indeed prescribes 16 byte alignment. The pushing of the return address is only done in `main` because the compiler can not rely on incoming stack pointer being aligned so it does the alignment itself and puts the return address on top. – Jester Nov 07 '18 at 01:02
  • Thank you very much! Then, reason of all my questions is 16 byte alignment. But, why the local variables are saved in esp+4, not esp? And why the address of argc is pushed above old ebp? Is that start address of parameter? Could you tell me? – Joontaek Oh Nov 07 '18 at 01:14
  • 1
    `ecx` is pushed because it's a caller-saved register and it's normally needed to restore the stack. Since your code invokes `exit` that isn't used here. The layout of locals is left to the compiler. – Jester Nov 07 '18 at 01:18
  • re: the 2nd part: gcc does sometimes reserve an extra 16 bytes of space for no apparent reason, even when you compile with optimization enabled. But without optimization it's not even trying to be efficient. – Peter Cordes Nov 07 '18 at 01:28

0 Answers0