c++ - 为什么 VS 做 imul rax,rax,0 而不是简单的移动?

标签 c++ assembly 64-bit

我正在查看为这个简单的 x64 程序生成的程序集 Visual Studio:

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;
}

当它遇到 arr[0].b = 2 时,它会生成:

mov eax, 8
imul rax, rax, 0
mov dword ptr [rbp+rax+4],2

为什么它执行 imul rax, rax, 0 而不是简单的 mov rax, 0,甚至 xor rax, rax? imul 如何更有效?

最佳答案

卡马克

原因是因为程序集正在计算数组中 Point 对象的偏移量,它恰好在堆栈上,以及变量 b< 的偏移量.

具有三 (3) 个操作数状态的 imul 的英特尔文档:

Three-operand form — This form requires a destination operand (the first operand) and two source operands (the second and the third operands). Here, the first source operand (which can be a general-purpose register or a memory location) is multiplied by the second source operand (an immediate value). The intermediate product (twice the size of the first source operand) is truncated and stored in the destination operand (a general-purpose register).

在您的情况下,它正在计算数组中对象的偏移量,这导致寻址堆栈上的第一个(第零个)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 在默认优化期间对偏移和解析寻址非常聪明。

关于c++ - 为什么 VS 做 imul rax,rax,0 而不是简单的移动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37629283/

相关文章:

audio - 在程序集 8086 中生成声音

c++ - 使用模板和 vector 时出现编译错误

c++ - 如果传递 long 类型,32 位客户端如何与 64 位服务器通信?

c++ - 一行输入。整数而不是整数

c++ - 循环将执行分为几个线程(1-N-1-N-1…)

c++ - 连续调用临时对象的方法

c++ - QT_VERSION 不正确?

assembly - How to check an "array' s length"in Assembly Language (ASM),

java - 需要帮助分析 Java 崩溃

visual-studio-2008 - Visual Studio 2008 项目属性生成配置缺少选项