了解MSVS C ++编译器优化

时间:2014-07-08 09:57:34

标签: c++ c visual-studio optimization assembly

我不明白这段代码中发生了什么。 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

2 个答案:

答案 0 :(得分:11)

处理器不是很擅长划分,一个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

答案 1 :(得分:0)

51EB851Fh似乎是分频器的magic number,用于除以100

来源:http://masm32.com/board/index.php?topic=1906.0回复#2