在下面的 C++ 源代码汇编中。为什么RAX被压入堆栈?
据我从 ABI 的了解,RAX 可以包含调用函数中的任何内容。但我们将其保存在这里,然后将堆栈向后移动 8 个字节。所以我认为堆栈上的 RAX 只与std::__throw_bad_function_call()
手术 ... ?
代码:-
#include <functional>
void f(std::function<void()> a)
{
a();
}
输出,来自gcc.godbolt.org
,使用 Clang 3.7.1 -O3:
f(std::function<void ()>): # @f(std::function<void ()>)
push rax
cmp qword ptr [rdi + 16], 0
je .LBB0_1
add rsp, 8
jmp qword ptr [rdi + 24] # TAILCALL
.LBB0_1:
call std::__throw_bad_function_call()
我确信原因很明显,但我正在努力找出答案。
这是一个没有的尾调用std::function<void()>
用于比较的包装:
void g(void(*a)())
{
a();
}
琐碎的:
g(void (*)()): # @g(void (*)())
jmp rdi # TAILCALL
The 64 位 ABI http://www.x86-64.org/documentation.html要求堆栈在 a 之前对齐到 16 个字节call
操作说明。
call
将 8 字节返回地址压入堆栈,这会破坏对齐,因此编译器需要在下一个之前将堆栈再次对齐到 16 的倍数call
.
(ABI 设计选择要求在call
而不是 after 的一个小优点是,如果在堆栈上传递任何参数,此选择会使第一个参数 16B 对齐。)
推动不关心的价值效果很好,并且可以more效率比sub rsp, 8
on 具有堆栈引擎的 CPU https://stackoverflow.com/questions/36631576/what-is-the-stack-engine-in-the-sandybridge-microarchitecture。 (见评论)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)