我不明白这段代码中发生了什么。 C代码是:
#include <stdio.h>
int main()
{
const int mul = 100;
int x;
printf_s("Input a number\r\n");
scanf_s("%i", &x);
printf_s("%i/%i = %i\r\n", x, mul, x / mul);
return 0;
}
我预计生成的程序集将是一些简单的移位和加/减操作,但有一些神奇的常量,如 51EB851Fh
、乘法等。这里发生了什么?
; int __cdecl main()
_main proc near
x= dword ptr -8
var_4= dword ptr -4
push ebp
mov ebp, esp
sub esp, 8
mov eax, ___security_cookie
xor eax, ebp
mov [ebp+var_4], eax
push offset Format ; "Input a number\r\n"
call ds:__imp__printf_s
lea eax, [ebp+x]
push eax
push offset aI ; "%i"
call ds:__imp__scanf_s
mov ecx, [ebp+x]
mov eax, 51EB851Fh
imul ecx
sar edx, 5
mov eax, edx
shr eax, 1Fh
add eax, edx
push eax
push 64h
push ecx
push offset aIII ; "%i/%i = %i\r\n"
call ds:__imp__printf_s
mov ecx, [ebp+var_4]
add esp, 1Ch
xor ecx, ebp ; cookie
xor eax, eax
call @__security_check_cookie@4 ; __security_check_cookie(x)
mov esp, ebp
pop ebp
retn
_main endp
最佳答案
处理器不太擅长除法,一个 idiv 可能需要 11 到 18 个周期。与移位和乘法相反,它们通常只需要一个周期。
因此优化器使用定点数学乘法代替了您的除法,利用 32 位乘法将 64 位结果生成到 edx:eax。信封背面:n/100 == n * 0.32/32 == n * (0.32 * pow(2,32))/32/pow(2,32)。这些部门非常便宜,只是右移。乘数变为 0.32 * pow(2,32) ~= 1374389535 == 0x51EB851F
关于c++ - 了解 MSVS C++ 编译器优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24628899/