Why are there 12 bytes for parameters and locales on the stack in C on Ubuntu?

I look at how the memory is laid out on the stack, but I do not understand why it looks like there is a space of 12 bytes to store each of the variables. Here is a simple C program that displays the location of various variables:

#include <stdio.h>
#include <stdlib.h>

int test (long p1, long p2){
    int l1 = 9999;
    int l2 = 99993333;

    printf("%p p1\n", &p1);
    printf("%p p2\n", &p2);
    printf("%p l1\n", &l1);
    printf("%p l1\n", &l2);
}

int main(int argc, const char** argv)
{
    register void* stack asm("esp");
    int x = 22;
    int y = 1000;
    printf("%p stack\n", stack);
    printf("%p argv\n", &argv);
    printf("%p argc\n", &argc);
    printf("%p l1\n", &x);
    printf("%p l2\n", &y);
    test(1, 888);
    return 0;
}

At startup, here is the output:

~/gc$ ./a.out
0x7fff5496b200 stack
0x7fff5496b200 argv
0x7fff5496b20c argc
0x7fff5496b218 l1
0x7fff5496b21c l2
0x7fff5496b1d8 p1
0x7fff5496b1d0 p2
0x7fff5496b1e8 l1
0x7fff5496b1ec l1

Why are there 12 spaces between argv and argc and 12 spaces between l1 and l2? I was expecting 8 for longs and pointers, and for the int main parameter, I would understand either 4 or 8 characters, but I see no reason why this should be 12.

Someone mentioned that the build code would be useful, so I got this as well:

Dump of assembler code for function main:
   0x0000000000400614 <+0>: push   %rbp
   0x0000000000400615 <+1>: mov    %rsp,%rbp
   0x0000000000400618 <+4>: sub    $0x20,%rsp
   0x000000000040061c <+8>: mov    %edi,-0x14(%rbp)
   0x000000000040061f <+11>:    mov    %rsi,-0x20(%rbp)
   0x0000000000400623 <+15>:    movl   $0x16,-0x8(%rbp)
   0x000000000040062a <+22>:    movl   $0x3e8,-0x4(%rbp)
   0x0000000000400631 <+29>:    mov    %rsp,%rax
   0x0000000000400634 <+32>:    mov    %rax,%rsi
   0x0000000000400637 <+35>:    mov    $0x40079c,%edi
   0x000000000040063c <+40>:    mov    $0x0,%eax
   0x0000000000400641 <+45>:    callq  0x400410 <printf@plt>
   0x0000000000400646 <+50>:    lea    -0x20(%rbp),%rax
   0x000000000040064a <+54>:    mov    %rax,%rsi
   0x000000000040064d <+57>:    mov    $0x4007a6,%edi
   0x0000000000400652 <+62>:    mov    $0x0,%eax
   0x0000000000400657 <+67>:    callq  0x400410 <printf@plt>
   0x000000000040065c <+72>:    lea    -0x14(%rbp),%rax
   0x0000000000400660 <+76>:    mov    %rax,%rsi
   0x0000000000400663 <+79>:    mov    $0x4007af,%edi
   0x0000000000400668 <+84>:    mov    $0x0,%eax
   0x000000000040066d <+89>:    callq  0x400410 <printf@plt>
   0x0000000000400672 <+94>:    lea    -0x8(%rbp),%rax
   0x0000000000400676 <+98>:    mov    %rax,%rsi
   0x0000000000400679 <+101>:   mov    $0x400780,%edi
   0x000000000040067e <+106>:   mov    $0x0,%eax
   0x0000000000400683 <+111>:   callq  0x400410 <printf@plt>
   0x0000000000400688 <+116>:   lea    -0x4(%rbp),%rax
   0x000000000040068c <+120>:   mov    %rax,%rsi
   0x000000000040068f <+123>:   mov    $0x400787,%edi
   0x0000000000400694 <+128>:   mov    $0x0,%eax
   0x0000000000400699 <+133>:   callq  0x400410 <printf@plt>
   0x000000000040069e <+138>:   mov    $0x14d,%ecx
   0x00000000004006a3 <+143>:   mov    $0x1589e,%edx
   0x00000000004006a8 <+148>:   mov    $0x378,%esi
   0x00000000004006ad <+153>:   mov    $0x1,%edi
   0x00000000004006b2 <+158>:   callq  0x40052c <test>
   0x00000000004006b7 <+163>:   mov    $0x0,%eax
   0x00000000004006bc <+168>:   leaveq 
   0x00000000004006bd <+169>:   retq   
End of assembler dump.
(gdb) disassemble test
Dump of assembler code for function test:
   0x000000000040052c <+0>: push   %rbp
   0x000000000040052d <+1>: mov    %rsp,%rbp
   0x0000000000400530 <+4>: sub    $0x40,%rsp
   0x0000000000400534 <+8>: mov    %rdi,-0x28(%rbp)
   0x0000000000400538 <+12>:    mov    %rsi,-0x30(%rbp)
   0x000000000040053c <+16>:    mov    %rdx,-0x38(%rbp)
   0x0000000000400540 <+20>:    mov    %rcx,-0x40(%rbp)
   0x0000000000400544 <+24>:    movl   $0x270f,-0x18(%rbp)
   0x000000000040054b <+31>:    movq   $0x5f5c6f5,-0x10(%rbp)
   0x0000000000400553 <+39>:    movl   $0x63,-0x14(%rbp)
   0x000000000040055a <+46>:    movq   $0x371,-0x8(%rbp)
   0x0000000000400562 <+54>:    lea    -0x28(%rbp),%rax
   0x0000000000400566 <+58>:    mov    %rax,%rsi
   0x0000000000400569 <+61>:    mov    $0x400764,%edi
   0x000000000040056e <+66>:    mov    $0x0,%eax
   0x0000000000400573 <+71>:    callq  0x400410 <printf@plt>
   0x0000000000400578 <+76>:    lea    -0x30(%rbp),%rax
   0x000000000040057c <+80>:    mov    %rax,%rsi
   0x000000000040057f <+83>:    mov    $0x40076b,%edi
   0x0000000000400584 <+88>:    mov    $0x0,%eax
   0x0000000000400589 <+93>:    callq  0x400410 <printf@plt>
   0x000000000040058e <+98>:    lea    -0x38(%rbp),%rax
   0x0000000000400592 <+102>:   mov    %rax,%rsi
   0x0000000000400595 <+105>:   mov    $0x400772,%edi
   0x000000000040059a <+110>:   mov    $0x0,%eax
   0x000000000040059f <+115>:   callq  0x400410 <printf@plt>
   0x00000000004005a4 <+120>:   lea    -0x40(%rbp),%rax
   0x00000000004005a8 <+124>:   mov    %rax,%rsi
   0x00000000004005ab <+127>:   mov    $0x400779,%edi
   0x00000000004005b0 <+132>:   mov    $0x0,%eax
   0x00000000004005b5 <+137>:   callq  0x400410 <printf@plt>
   0x00000000004005ba <+142>:   lea    -0x18(%rbp),%rax
   0x00000000004005be <+146>:   mov    %rax,%rsi
   0x00000000004005c1 <+149>:   mov    $0x400780,%edi
   0x00000000004005c6 <+154>:   mov    $0x0,%eax
   0x00000000004005cb <+159>:   callq  0x400410 <printf@plt>
   0x00000000004005d0 <+164>:   lea    -0x10(%rbp),%rax
   0x00000000004005d4 <+168>:   mov    %rax,%rsi
   0x00000000004005d7 <+171>:   mov    $0x400787,%edi
   0x00000000004005dc <+176>:   mov    $0x0,%eax
   0x00000000004005e1 <+181>:   callq  0x400410 <printf@plt>
   0x00000000004005e6 <+186>:   lea    -0x14(%rbp),%rax
   0x00000000004005ea <+190>:   mov    %rax,%rsi
   0x00000000004005ed <+193>:   mov    $0x40078e,%edi
   0x00000000004005f2 <+198>:   mov    $0x0,%eax
   0x00000000004005f7 <+203>:   callq  0x400410 <printf@plt>
   0x00000000004005fc <+208>:   lea    -0x8(%rbp),%rax
   0x0000000000400600 <+212>:   mov    %rax,%rsi
   0x0000000000400603 <+215>:   mov    $0x400795,%edi
   0x0000000000400608 <+220>:   mov    $0x0,%eax
   0x000000000040060d <+225>:   callq  0x400410 <printf@plt>
   0x0000000000400612 <+230>:   leaveq 
   0x0000000000400613 <+231>:   retq   
End of assembler dump.
+4
source share
1 answer

64- ( ), , , , x86-64.

ABI x86-64 , . , C, . , &argc, .

. argc . , , .

, 12 , , x86-64. , argc , 4 , argv , 4 , , 8 argv . , , put argv argc .

C-:

void otherfunc(int *ptr);
int func(int value)
{
    otherfunc(&value);
    return 0;
}

:

func:
    subq    $24, %rsp       ; Allocate 24 bytes on the stack
    movl    %edi, 12(%rsp)  ; Store 'value' on the stack
    leaq    12(%rsp), %rdi  ; Calculate the address of 'value'
    call    otherfunc       ; Call 'otherfunc'
    xorl    %eax, %eax      ; Return value 0
    addq    $24, %rsp       ; Deallocate stack
    ret                     ; Return

, %rsp - , %edi/%rdi - , %eax - .

+3

All Articles