我正在查看为这个简单的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
。
imul
具有三(3)个操作数的英特尔文档状态:
三操作数形式—此形式需要一个目标操作数(第一个操作数)和两个源操作数(第二个和第三个操作数)。在此,将第一源操作数(可以是通用寄存器或存储位置)乘以第二源操作数(立即数)。中间乘积(第一个源操作数的大小的两倍)被截断并存储在目标操作数(通用寄存器)中。
在您的情况下,它正在计算对象在数组中的偏移量,从而导致寻址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
。
我认为您没有使用积极的优化进行编译。在进行直接编译(不进行优化,调试等)时,编译器不会对寻址进行任何假设。
与c比较
在clang 3.9.0
没有优化标志且没有优化标志的OS X(El Capitan)上,一旦Point
在数组中实例化了对象,就.b = 2
可以简单地分配:
mov dword ptr [rbp - 44], 2
在这种情况下,clang
对偏移量非常了解,并且可以在默认优化过程中解决寻址问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句