我研究了32位机器,我知道低于$ 12,%esp等同于弹出%eax和mov $ 0,%eax的三倍。
但是我不知道为什么我们在x86-64机器上使用添加$ 18,%rsp进行启动过程调用,或者使用$ 18,%rsp起始以过程调用开始。
为什么编译器使用此规则进行过程调用?争论规则?
0x0000000000400df3 <main+191>: mov $0x402227,%edi
0x0000000000400df8 <main+196>: callq 0x400ab8 <puts@plt>
0x0000000000400dfd <main+201>: callq 0x4014c0 <read_line>
0x0000000000400e02 <main+206>: mov %rax,%rdi
0x0000000000400e05 <main+209>: callq 0x401139 <phase_3>
-----------------------------------------------------------------------
example:
0x0000000000401139 <example+0>: sub $0x18,%rsp
0x000000000040113d <example+4>: lea 0x8(%rsp),%rcx
0x0000000000401142 <example+9>: lea 0xc(%rsp),%rdx
0x0000000000401147 <example+14>: mov $0x40248a,%esi
0x000000000040114c <example+19>: mov $0x0,%eax
0x0000000000401151 <example+24>: callq 0x400ac8 <__isoc99_sscanf@plt>
0x0000000000401156 <example+29>: cmp $0x1,%eax
Run Code Online (Sandbox Code Playgroud)
“我知道sub $12, %esp
是相同的三个时间pop %eax
和mov $0, %eax
。” 你知道错了。sub $12, %esp
不会发生变化eax
,既不会弹出,也不会移动0。
使用类似sub $12, %esp
方法的主要/直接原因是在堆栈上保留一些空间。可以用来给子例程的局部变量留一些空间。如果出于性能或其他原因需要堆栈指针,也可以使用它来对齐堆栈指针。
add $18, %rsp
反之,则释放先前在堆栈上分配的空间。这可用于释放局部变量或先前已传递给另一个子例程且不再需要堆栈的参数所占用的空间。