为什么VS确实是imul rax,rax,0而不是简单的移动?

时间:2016-06-04 10:49:11

标签: c++ assembly 64-bit

我正在查看为这个简单的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 ?如果有的话,如何提高效率呢?

1 个答案:

答案 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非常了解偏移并在默认优化期间解决寻址问题。