bar*_*ler 3 c++ assembly gcc clang compiler-optimization
我有一个带有两个64位整数成员的struct X和一个构造函数:
struct X
{
X(uint64_t a, uint64_t b)
{
a_ = a; b_ = b;
}
uint64_t a_, b_;
};
Run Code Online (Sandbox Code Playgroud)
当我查看编译器输出(在64位Linux上为x86-64 gcc 8.3和x86-64 clang 8.0.0)时,未启用任何优化,我看到了以下针对构造函数的代码。
x86-64 gcc 8.3:
X::X(unsigned long, unsigned long):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov QWORD PTR [rbp-16], rsi
mov QWORD PTR [rbp-24], rdx
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax], 0
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax+8], 0
mov rax, QWORD PTR [rbp-8]
mov rdx, QWORD PTR [rbp-16]
mov QWORD PTR [rax+8], rdx
mov rax, QWORD PTR [rbp-8]
mov rdx, QWORD PTR [rbp-24]
mov QWORD PTR [rax], rdx
nop
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
x86-64铛8.0.0:
X::X(unsigned long, unsigned long):
push rbp
mov rbp, rsp
mov qword ptr [rbp - 8], rdi
mov qword ptr [rbp - 16], rsi
mov qword ptr [rbp - 24], rdx
mov rdx, qword ptr [rbp - 8]
mov qword ptr [rdx], 0
mov qword ptr [rdx + 8], 0
mov rsi, qword ptr [rbp - 16]
mov qword ptr [rdx + 8], rsi
mov rsi, qword ptr [rbp - 24]
mov qword ptr [rdx], rsi
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么输出如此复杂?我希望有两个简单的“ mov”语句,即使没有启用优化也是如此。
未经优化的代码总是将所有C ++变量(包括函数args)存储到语句之间的内存位置中,以便调试器可以读取甚至修改这些值。(并且因为它没有花时间进行寄存器分配。)这包括在函数的第一个C ++语句之前将寄存器args存储到内存中。
这是类似于from的Intel语法程序集gcc -masm=intel,因此它使用的是目标,源顺序。(我们可以根据使用的PTR,方括号和缺少的%寄存器名称来判断。)
前三个存储是根据(this, a, b)x86-64 System V ABI的调用约定在寄存器RDI,RSI和RDX中传递的函数参数。
mov QWORD PTR [rbp-8], rdi # this
mov QWORD PTR [rbp-16], rsi # a
mov QWORD PTR [rbp-24], rdx # b
Run Code Online (Sandbox Code Playgroud)
现在,它是装载this到rax,写零到a_和b_因为你没有使用正确的构造函数初始化。或者可能是使用未在此处显示的某些代码或奇数编译器选项将初始化添加为零。
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax], 0 # this->a_ = 0
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax+8], 0 # this->b_ = 0
Run Code Online (Sandbox Code Playgroud)
然后将this其rax再次a装入rdx,然后this->a_以rdxaka 写入a。再次相同b。
等等,实际上必须先写入b_然后再写入,a_因为需要结构来匹配声明和内存顺序。一定[rax+8]要这样b_,不是a_。
mov rax, QWORD PTR [rbp-8]
mov rdx, QWORD PTR [rbp-16] # reload a
mov QWORD PTR [rax+8], rdx # this->b_ = a
mov rax, QWORD PTR [rbp-8]
mov rdx, QWORD PTR [rbp-24] # reload b
mov QWORD PTR [rax], rdx # this->a_ = b
Run Code Online (Sandbox Code Playgroud)
因此,您的asm与问题中的C ++源不匹配。