我理解在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