Assembly - why is% rsp so reduced, and why are the arguments stored at the top of the stack?

Assembly assembler here ... I wrote the following simple C program:

void fun(int x, int* y)
{
  char arr[4];
  int* sp;
  sp = y;
}

int main()
{
  int i = 4;
  fun(i, &i);
  return 0;
}

I compiled it with gcc and ran objdump with -S, but the output from the assembly code confused me:

000000000040055d <fun>:
void fun(int x, int* y)
{
  40055d:       55                      push   %rbp
  40055e:       48 89 e5                mov    %rsp,%rbp
  400561:       48 83 ec 30             sub    $0x30,%rsp
  400565:       89 7d dc                mov    %edi,-0x24(%rbp)
  400568:       48 89 75 d0             mov    %rsi,-0x30(%rbp)
  40056c:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
  400573:       00 00
  400575:       48 89 45 f8             mov    %rax,-0x8(%rbp)
  400579:       31 c0                   xor    %eax,%eax
  char arr[4];
  int* sp;
  sp = y;
  40057b:       48 8b 45 d0             mov    -0x30(%rbp),%rax
  40057f:       48 89 45 e8             mov    %rax,-0x18(%rbp)
}
  400583:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  400587:       64 48 33 04 25 28 00    xor    %fs:0x28,%rax
  40058e:       00 00
  400590:       74 05                   je     400597 <fun+0x3a>
  400592:       e8 a9 fe ff ff          callq  400440 <__stack_chk_fail@plt>
  400597:       c9                      leaveq
  400598:       c3                      retq

0000000000400599 <main>:

int main()
{
  400599:       55                      push   %rbp
  40059a:       48 89 e5                mov    %rsp,%rbp
  40059d:       48 83 ec 10             sub    $0x10,%rsp
  int i = 4;
  4005a1:       c7 45 fc 04 00 00 00    movl   $0x4,-0x4(%rbp)
  fun(i, &i);
  4005a8:       8b 45 fc                mov    -0x4(%rbp),%eax
  4005ab:       48 8d 55 fc             lea    -0x4(%rbp),%rdx
  4005af:       48 89 d6                mov    %rdx,%rsi
  4005b2:       89 c7                   mov    %eax,%edi
  4005b4:       e8 a4 ff ff ff          callq  40055d <fun>
  return 0;
  4005b9:       b8 00 00 00 00          mov    $0x0,%eax
}
  4005be:       c9                      leaveq
  4005bf:       c3                      retq

First in the line:

  400561:       48 83 ec 30             sub    $0x30,%rsp

Why did the stack pointer decrease significantly in the "fun" call (48 bytes)? I suppose this is due to alignment problems, but I can’t imagine why it would take so much space (I only count 12 bytes for local variables (suppose 8 byte pointers))?

-, , x86_64 , , "" ( ) ,% rbp. http://en.wikipedia.org/wiki/Call_stack#Structure, "".

:

  400565:       89 7d dc                mov    %edi,-0x24(%rbp)
  400568:       48 89 75 d0             mov    %rsi,-0x30(%rbp)

, (% rsi % edi, , "fun", 0x30 % rbp - , ...). , , , , :

  sp = y;
  40057b:       48 8b 45 d0             mov    -0x30(%rbp),%rax
  40057f:       48 89 45 e8             mov    %rax,-0x18(%rbp)

... ?! , , , , , " ", , . , , , , , ?

+4
3

, , , , , .

  • , - .
  • ( )
  • "" , ( ).

, .

+1

- , . , . . , .

, , . , , __stack_chk_fail.

. -, . - , , , . .

+4

64- . 0x30 6 . , :

  • 2 ( )
  • 2
  • 1 AX
  • 1 , , DEBUG.

It’s best to experiment and not ask questions. Try compiling in different modes (DEBUG, optimization, etc.) and with different numbers and types of arguments and variables. Sometimes asking other people is just too easy - you learn better by doing your own experiments.

0
source

All Articles