我正在查看为这个简单的x64程序生成的Visual Studio程序集:
SELECT * FROM MaterializedView
WHERE User = @CurrentlyAuthenticatedUser
当它遇到 arr [0] .b = 2 时,它会生成:
struct Point {
int a, b;
Point() {
a = 0; b = 1;
}
};
int main(int argc, char* argv[])
{
Point arr[3];
arr[0].b = 2;
return 0;
}
为什么 imul rax,rax,0 而不是简单的 mov rax,0 ,甚至 xor rax,rax ?如果有的话,如何提高效率呢?
答案 0 :(得分:3)
Kamac
原因是因为程序集正在计算数组中Point
对象的偏移量,该对象恰好位于堆栈上,以及变量b
的偏移量。
具有三(3)个操作数的imul
的英特尔文档:
三操作数表单 - 此表单需要一个目标操作数( 第一个操作数)和两个源操作数(第二个和第三个) 操作数)。这里,第一个源操作数(可以是一个 通用寄存器或存储器位置)乘以 第二个源操作数(立即值)。中间产品 (截断并存储第一个源操作数大小的两倍) 在目标操作数(通用寄存器)中。
在您的情况下,它正在计算数组中对象的偏移量,从而导致寻址堆栈上的第一个(第0个)Point
位置。解决后,然后添加.b
的偏移量+4
。所以细分:
mov eax,8 ; prepare to offset into the Point array
imul rax, rax, 0 ; Calculate which Point object is being referred to
mov dword ptr [rbp+rax+4],2 ; Add the offset to b and move value 2 in
指令。所有这些都解析为arr[0].b = 2
。
我认为你没有用积极的优化进行编译。当进行直接编译(没有优化,调试等)时,编译器不会对寻址做出任何假设。
与clang的比较
在带有clang 3.9.0
且没有优化标志的OS X(El Capitan)上,一旦Point
对象在数组中实例化,.b = 2
的分配就是:
mov dword ptr [rbp - 44], 2
在这种情况下,clang
非常了解偏移并在默认优化期间解决寻址问题。