2

I understand the convention of decrementing %rsp to reserve space for local variables at the beginning of a function in x86-64 assembly. However, in the below function, %rsp is decremented but the reserved space of 8 bytes on the stack is never used in the function. So why would the compiler decrement %rsp at the beginning? Source code and compiler information are not available.

0000000000400ef0 <phase_1>:
    0x0000000000400ee0 <+0>:    sub    $0x8, %rsp 
    0x0000000000400ee4 <+4>:    mov    $0x402400, %esi 
    0x0000000000400ee9 <+9>:    callq  0x401338 <strings_not_equal>
    0x0000000000400eee <+14>:   test   %eax, %eax
    0x0000000000400ef0 <+16>:   je     0x400ef7 <phase_1+23>
    0x0000000000400ef2 <+18>:   callq  0x40143a <explode_bomb>
    0x0000000000400ef7 <+23>:   add    $0x8, %rsp
    0x0000000000400efb <+27>:   retq  

Any help would be much appreciated.

EDIT: If the reason is to give the stack 16-byte alignment, here is another example that seems to be a contradiction. Doesn't subq $16, %rsp at the beginning of call_incr break the 16-bit alignment of stack prior to call incr? Why not just decrement %rsp by 8 bytes?

Source:

long incr(long *p, long val) {
    long x = *p;
    long y = x + val;
    *p = y;
    return x;
}

long call_incr() {
    long v1 = 1000;
    long v2 = incr(&v1, 3000);
    return v1+v2;
}

Assembly (compiled with gcc -Og -fno-stack-protector -S)

incr:
.LFB0:
    .cfi_startproc
    movq    (%rdi), %rax
    addq    %rax, %rsi
    movq    %rsi, (%rdi)
    ret
    .cfi_endproc

call_incr:
.LFB1:
    .cfi_startproc
    subq    $16, %rsp   # why decrement by 16 bytes here?
    .cfi_def_cfa_offset 24
    movq    $1000, 8(%rsp)
    movl    $3000, %esi
    leaq    8(%rsp), %rdi
    call    incr
    addq    8(%rsp), %rax
    addq    $16, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
Qin Yixiao
  • 113
  • 7
  • 8
    To give the stack 16 byte alignment. Calling the function pushes an 8 byte return address on the stack so the function needs to allocate 8 more bytes to align the stack again. – Ross Ridge Sep 07 '16 at 03:51
  • 1
    @RossRidge: Make that an answer. Also mention that the reason alignment is mandatory here is to meet the ABI calling other functions (`strings_not_equal`, `explode_bomb`). – R.. GitHub STOP HELPING ICE Sep 07 '16 at 04:14
  • @RossRidge: Thanks for pointing out the 16-byte alignment. But in the additional example in my edit, why does the compiler decrement `%rsp` by 16 instead of 8 bytes in `call_incr`? – Qin Yixiao Sep 09 '16 at 05:12
  • The `subq $16, %rsp` is optimised out on my machine at `-O2` – tangrs Sep 09 '16 at 06:04
  • 1
    It's probably allocating 16 bytes on the stack because you have 16 bytes of local variables (`v1` and `v2`) and it's not bothering to align the stack because it determined that `incr` doesn't actually need the stack to be aligned. If you remove the definition of `incr` then the compiler allocates 24 bytes on the stack which results in a correctly aligned stack in case `incr` needs it. – Ross Ridge Sep 09 '16 at 06:52
  • @RossRidge: Thank you for being helpful. – Qin Yixiao Sep 09 '16 at 08:27

0 Answers0