为什么即使从不使用堆栈上的保留空间也会减少%rsp?

时间:2016-09-07 03:45:02

标签: c assembly stack x86-64

我理解在x86-64程序集中函数开头的递减%rsp为局部变量保留空间的约定。但是,在下面的函数中,%rsp递减,但堆栈中8字节的保留空间从不在函数中使用。那么为什么编译器会在开始时递减%rsp?源代码和编译器信息不可用。

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  

非常感谢任何帮助。

修改 如果原因是给堆栈16字节对齐,这里是另一个似乎是矛盾的例子。 subq $16, %rsp开头的call_incr是否会在call incr之前中断堆栈的16位对齐?为什么不将%rsp减少8个字节?

来源:

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;
}

程序集(使用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

0 个答案:

没有答案