1. 程式人生 > >在C++中將浮點數強制轉換為整數,做了些什麼——ftol註釋

在C++中將浮點數強制轉換為整數,做了些什麼——ftol註釋

_ftol2:
0040142C 55                    push         ebp  
0040142D 8B EC                 mov          ebp,esp 
0040142F 83 EC 20              sub          esp,20h                    //堆疊上空出20h個位元組,用於儲存臨時變數
00401432 83 E4 F0              and          esp,0FFFFFFF0h             //將esp對齊到16位元組
00401435 D9 C0                 fld          st(0)                      //壓入st(0),原先的st(0)變為st(1),這樣st(1) == st(0)
00401437 D9 54 24 18           fst          dword ptr [esp+18h]        //將st(0)轉換為單精度(dword) 儲存倒[esp + 18h]位置

0040143B DF 7C 24 10           fistp        qword ptr [esp+10h]        //將st(0)取整儲存到[esp+10h]位置,這個結果是64位的(qword),結果偏0還是遠離0應該取決於協處理器msw。同時彈出st(0),原先的st(1)變為st(0)
0040143F DF 6C 24 10           fild         qword ptr [esp+10h]        //將剛才取整的結果load到st(0)。現在st(1)是原值,st(0)是取整後的值
00401443 8B 54 24 18           mov          edx,dword ptr [esp+18h]    //取原值單精度版到edx
00401447 8B 44 24 10           mov          eax,dword ptr [esp+10h]    //取64位取整結果的低32位
0040144B 85 C0                 test         eax,eax 
0040144D 74 3C                 je           integer_QnaN_or_zero (0040148B) //如果eax位0,則該浮點數可能是0或者NAN

arg_is_not_integer_QnaN:
0040144F DE E9                 fsubp        st(1),st    //原值減去取整後的結果,結果在st(0)中。取整結果如果偏0, 原值為正結果得正,原值為負結果得負; 取整結果如果遠離0, 原值為正結果得負,原值為負結果得正
00401451 85 D2                 test         edx,edx     //測試原浮點數的單精度格式
00401453 79 1E                 jns          positive (00401473)  //如果原值是非負數則跳轉,以下是負數的處理方法
00401455 D9 1C 24              fstp         dword ptr [esp]      //將減法結果儲存到[esp]位置,彈出棧頂元素,st(0)變為原值
00401458 8B 0C 24              mov          ecx,dword ptr [esp]  
0040145B 81 F1 00 00 00 80     xor          ecx,80000000h        //減法結果最高位取反,其餘位不變

00401461 81 C1 FF FF FF 7F     add          ecx,7FFFFFFFh        //如果減法結果為正,則最高為取反後為1,再加7FFFFFFFh必定CF=1,即遠離0;如果減法結果為0或者負數,則CF=0,即偏向0
00401467 83 D0 00              adc          eax,0                //對於負浮點數,取整結果遠離0(CF=1)就是多減了1,需要加1,讓結果偏0;取整結果如果偏向0(CF=0),結果eax加上CF和0,值仍然不變
0040146A 8B 54 24 14           mov          edx,dword ptr [esp+14h]

0040146E 83 D2 00              adc          edx,0 
00401471 EB 2C                 jmp          localexit (0040149F)

positive:
00401473 D9 1C 24              fstp         dword ptr [esp]      //註釋同上

00401476 8B 0C 24              mov          ecx,dword ptr [esp] 
00401479 81 C1 FF FF FF 7F     add          ecx,7FFFFFFFh

0040147F 83 D8 00              sbb          eax,0                //對於正浮點數,取整遠離0(CF=1)就是多加了1,需要減1,讓結果偏0;取整結果如果偏向0(CF=0),結果減去CF和0,值仍然不變
00401482 8B 54 24 14           mov          edx,dword ptr [esp+14h]

00401486 83 DA 00              sbb          edx,0 
00401489 EB 14                 jmp          localexit (0040149F)

integer_QnaN_or_zero:      //對於0或者NAN
0040148B 8B 54 24 14           mov          edx,dword ptr [esp+14h]  //取64位取整結果的高32位
0040148F F7 C2 FF FF FF 7F     test         edx,7FFFFFFFh            //測試高字的低31位,
00401495 75 B8                 jne          arg_is_not_integer_QnaN (0040144F)
00401497 D9 5C 24 18           fstp         dword ptr [esp+18h]
0040149B D9 5C 24 18           fstp         dword ptr [esp+18h]

localexit:
0040149F C9                    leave
004014A0 C3                    ret          //結果在eax中