除法与模运算的识别-大量除法推导过程

Debug版本总结:

有符号 2的幂 和无符号除2的幂作了优化, 其它情况都是 直接运用div,idiv指令

 

4:    #include "stdafx.h"

5:    #include "stdio.h"

6:

7:    int main(unsigned int argc, char* argv[])

8:    {

00401010   push         ebp

00401011   mov          ebp,esp

00401013   sub          esp,4Ch //预留局部变量空间

00401016   push         ebx //保存环境

00401017   push         esi //保存环境

00401018   push         edi //保存环境

00401019   lea          edi,[ebp-4Ch] 

0040101C   mov         ecx,13h

00401021   mov         eax,0CCCCCCCCh

00401026   rep stos     dword ptr [edi] //预留空间全部初始化为0xCC

9:        int x = 0;

00401028   mov         dword ptr [ebp-4],0 //变量初始化为0

10:       int y = 0;

0040102F   mov         dword ptr [ebp-8],0

11:       unsigned u = 0;

00401036   mov         dword ptr [ebp-0Ch],0

12:

13:       scanf("%d %d %u", &x, &y ,&u);

0040103D    lea          eax,[ebp-0Ch]

00401040    push         eax

00401041    lea          ecx,[ebp-8]

00401044    push         ecx

00401045    lea          edx,[ebp-4]

00401048    push         edx

00401049    push         offset string "%d %d %u" (00425364)

0040104E    call         scanf (00401740)

00401053    add          esp,10h

14:

15:       printf("x/y = %d \r\n", x/y);   //有符号变量/有符号变量

00401056    mov        eax,dword ptr [ebp-4]

00401059    cdq

0040105A    idiv         eax,dword ptr [ebp-8]

0040105D    push         eax

0040105E    push         offset string "x/y = %d \r\n" (00425354)

00401063    call         printf (004016c0)

00401068    add          esp,8

分析1: 有符号两变量相除,直接运用指令idiv,不存在优化.对于编译器来讲都是未知的值.

 

16:       printf("x/u = %d \r\n", x/u);   //有符号变量/无符号变量

0040106B   mov         eax,dword ptr [ebp-4]

0040106E   xor          edx,edx

00401070   div          eax,dword ptr [ebp-0Ch]

00401073   push         eax

00401074   push         offset string "x/u = %d \r\n" (00425344)

00401079   call         printf (004016c0)

0040107E   add          esp,8

分析2:有符号分母与无符号分子 混除,直接用无符号div处理.有符号数当无符号处理.同样两个变量对于编译器来讲是未知的值,无法忧化.

 

17:       printf("u/x = %d \r\n", u/x);   //无符号变量/有符号变量

00401081   mov          eax,dword ptr [ebp-0Ch]

00401084   xor          edx,edx

00401086   div          eax,dword ptr [ebp-4]

00401089   push         eax

0040108A   push         offset string "u/x = %d \r\n" (00425334)

0040108F   call         printf (004016c0)

00401094   add          esp,8

分析3:有符号分子与无符号分母 混除,直接用无符号div处理.有符号数当无符号处理.同样两个变量对于编译器来讲是未知的值,无法忧化.

 

19:       printf("x/2 = %d \r\n", x/2);   //有符号变量/常量2

00401097   mov          eax,dword ptr [ebp-4] //1. x

0040109A   cdq

0040109B   sub         eax,edx //2. x+1x+0 负数调整

0040109D   sar          eax,1 //3.  x /2

0040109F   push         eax

004010A0   push         offset string "x/2 = %d \r\n" (00425324)

004010A5   call         printf (004016c0)

004010AA   add         esp,8

分析4: 代码功能 x/2  2处代码是不是很诡秘,原因如下

x > 0

x < 0 = (x+1) >> 1  这步根据推导7

2处利用x符号位,巧妙的做了调整,避免了分支.

 

20:       printf("x/-2 = %d \r\n", x/-2); //有符号变量/常量-2

004010AD   mov         eax,dword ptr [ebp-4] //1. x

004010B0    cdq

004010B1    sub          eax,edx //2. 调整

004010B3    sar          eax,1 //3.  x / 2

004010B5   neg          eax //4. -x

004010B7   push         eax

004010B8   push         offset string "x/-2 = %d \r\n" (00425314)

004010BD   call         printf (004016c0)

004010C2   add          esp,8

分析5: 编译器这样做了 ;先求括号里的值,分析过程 同 分析4 ,最后第4步 结果来个求补.

 

21:       printf("u/2 = %d \r\n", u/2);   //无符号变量/常量2

004010C5   mov         eax,dword ptr [ebp-0Ch] //1.

004010C8   shr          eax,1 //2.直接逻辑移位

004010CA   push         eax

004010CB   push         offset string "u/2 = %d \r\n" (00425304)

004010D0   call         printf (004016c0)

004010D5   add          esp,8

分析6: 无符号 2的幂 直接逻辑移位;

 

22:       printf("u/-2 = %d \r\n", u/-2); //无符号变量/常量-2

004010D8   mov         eax,dword ptr [ebp-0Ch]

004010DB   xor          edx,edx

004010DD   mov         ecx,0FFFFFFFEh

004010E2   div          eax,ecx

004010E4   push         eax

004010E5   push         offset string "u/-2 = %d \r\n" (004252f4)

004010EA   call         printf (004016c0)

004010EF   add          esp,8

分析7: 无符号 负数,负数被当无符号处理,直接除.无忧化

 

24:       printf("x/3 = %d \r\n", x/3);   //有符号变量/常量3

004010F2   mov          eax,dword ptr [ebp-4]

004010F5   cdq

004010F6   mov          ecx,3

004010FB   idiv         eax,ecx

004010FD   push         eax

004010FE   push         offset string "x/3 = %d \r\n" (004252e4)

00401103   call         printf (004016c0)

00401108   add          esp,8

分析8: 太直观

 

25:       printf("x/-3 = %d \r\n", x/-3); //有符号变量/常量-3

0040110B   mov         eax,dword ptr [ebp-4]

0040110E   cdq

0040110F   mov         ecx,0FFFFFFFDh

00401114   idiv         eax,ecx

00401116   push         eax

00401117   push         offset string "x/-3 = %d \r\n" (004252d4)

0040111C   call         printf (004016c0)

00401121   add          esp,8

分析9: 太直观

 

26:       printf("u/3 = %d \r\n", u/3);   //无符号变量/常量3

00401124   mov          eax,dword ptr [ebp-0Ch]

00401127   xor          edx,edx

00401129   mov          ecx,3

0040112E   div          eax,ecx

00401130   push         eax

00401131   push         offset string "u/3 = %d \r\n" (004252c4)

00401136   call         printf (004016c0)

0040113B   add          esp,8

分析10: 太直观

 

27:       printf("u/-3 = %d \r\n", u/-3); //无符号变量/常量-3

0040113E   mov         eax,dword ptr [ebp-0Ch]

00401141   xor          edx,edx

00401143   mov          ecx,0FFFFFFFDh

00401148   div          eax,ecx

0040114A   push         eax

0040114B   push         offset string "u/-3 = %d \r\n" (004252b4)

00401150   call         printf (004016c0)

00401155   add          esp,8

分析11: 无符号 负数,负数被当无符号处理,直接除.无忧化

 

29:       printf("x/4 = %d \r\n", x/4);   //有符号变量/常量4

00401158   mov          eax,dword ptr [ebp-4]

0040115B   cdq

0040115C   and          edx,3 //.1调整

0040115F   add          eax,edx //.2调整

00401161   sar          eax,2

00401164   push         eax

00401165   push         offset string "x/4 = %d \r\n" (004252a4)

0040116A   call         printf (004016c0)

0040116F   add          esp,8

分析12: 代码功能 x/4

x > 0

x < 0 = (x+3) >> 1  这步根据推导7

12处利用x符号位,巧妙的做了调整,避免了分支.

 

30:       printf("x/-4 = %d \r\n", x/-4); //有符号变量/常量-4

00401172   mov          eax,dword ptr [ebp-4]

00401175   cdq

00401176   and          edx,3

00401179   add          eax,edx

0040117B   sar          eax,2

0040117E   neg          eax //1

00401180   push         eax

00401181   push         offset string "x/-4 = %d \r\n" (00425294)

00401186   call         printf (004016c0)

0040118B   add          esp,8

分析13: 编译器这样做了 ;先求括号里的值,分析过程 同 分析12 ,最后第1处 结果来个求补.

 

31:       printf("u/4 = %d \r\n", u/4);   //无符号变量/常量4

0040118E   mov          eax,dword ptr [ebp-0Ch]

00401191   shr          eax,2

00401194   push         eax

00401195   push         offset string "u/4 = %d \r\n" (00425284)

0040119A   call         printf (004016c0)

0040119F   add          esp,8

分析14: 无符号 2的幂 直接逻辑右移

 

32:       printf("u/-4 = %d \r\n", u/-4); //无符号变量/常量-4

004011A2   mov          eax,dword ptr [ebp-0Ch]

004011A5   xor          edx,edx

004011A7   mov          ecx,0FFFFFFFCh

004011AC   div          eax,ecx

004011AE   push         eax

004011AF   push         offset string "u/-4 = %d \r\n" (00425274)

004011B4   call         printf (004016c0)

004011B9   add          esp,8

分析15: 无符号 负数,负数被当无符号处理,直接除.无忧化

 

34:       printf("x/5 = %d \r\n", x/5);   //有符号变量/常量5

004011BC   mov         eax,dword ptr [ebp-4]

004011BF   cdq

004011C0   mov          ecx,5

004011C5   idiv         eax,ecx

004011C7   push         eax

004011C8   push         offset string "x/5 = %d \r\n" (00425264)

004011CD   call         printf (004016c0)

004011D2   add          esp,8

分析16: 有符号 2的幂 无忧化,直接除

 

35:       printf("x/-5 = %d \r\n", x/-5); //有符号变量/常量-5

004011D5   mov          eax,dword ptr [ebp-4]

004011D8   cdq

004011D9   mov          ecx,0FFFFFFFBh

004011DE   idiv         eax,ecx

004011E0   push         eax

004011E1   push         offset string "x/-5 = %d \r\n" (00425254)

004011E6   call         printf (004016c0)

004011EB   add          esp,8

分析17: 有符号 2的幂 无忧化,直接除

 

36:       printf("u/5 = %d \r\n", u/5);   //无符号变量/常量5

004011EE   mov          eax,dword ptr [ebp-0Ch]

004011F1   xor          edx,edx

004011F3   mov          ecx,5

004011F8   div          eax,ecx

004011FA   push         eax

004011FB   push         offset string "u/5 = %d \r\n" (00425244)

00401200   call         printf (004016c0)

00401205   add          esp,8

分析18: 无符号 2的幂 直接除.无忧化

 

37:       printf("u/-5 = %d \r\n", u/-5); //无符号变量/常量-5

00401208   mov          eax,dword ptr [ebp-0Ch]

0040120B   xor          edx,edx

0040120D   mov         ecx,0FFFFFFFBh

00401212   div          eax,ecx

00401214   push         eax

00401215   push         offset string "u/-5 = %d \r\n" (00425234)

0040121A   call         printf (004016c0)

0040121F   add          esp,8

分析19: 无符号 负数,负数被当无符号处理,直接除.无忧化

 

39:       printf("x/6 = %d \r\n", x/6);   //有符号变量/常量6

00401222   mov          eax,dword ptr [ebp-4]

00401225   cdq

00401226   mov          ecx,6

0040122B   idiv         eax,ecx

0040122D   push         eax

0040122E   push         offset string "x/6 = %d \r\n" (00425224)

00401233   call         printf (004016c0)

00401238   add          esp,8

分析20: 有符号 2的幂 无忧化,直接除

 

40:       printf("x/-6 = %d \r\n", x/-6); //有符号变量/常量-6

0040123B   mov          eax,dword ptr [ebp-4]

0040123E   cdq

0040123F   mov          ecx,0FFFFFFFAh

00401244   idiv         eax,ecx

00401246   push         eax

00401247   push         offset string "x/-6 = %d \r\n" (00425214)

0040124C   call         printf (004016c0)

00401251   add          esp,8

分析21: 有符号 2的幂 无忧化,直接除

 

 

41:       printf("u/6 = %d \r\n", u/6);   //无符号变量/常量6

00401254   mov         eax,dword ptr [ebp-0Ch]

00401257   xor         edx,edx

00401259   mov         ecx,6

0040125E   div         eax,ecx

00401260   push        eax

00401261   push        offset string "u/6 = %d \r\n" (00425204)

00401266   call        printf (004016c0)

0040126B   add         esp,8

分析22: 无符号 2的幂 直接除.无忧化

 

 

42:       printf("u/-6 = %d \r\n", u/-6); //无符号变量/常量-6

0040126E   mov         eax,dword ptr [ebp-0Ch]

00401271   xor         edx,edx

00401273   mov         ecx,0FFFFFFFAh

00401278   div         eax,ecx

0040127A   push        eax

0040127B   push        offset string "u/-6 = %d \r\n" (004251f4)

00401280   call        printf (004016c0)

00401285   add         esp,8

分析23: 无符号 负数,负数被当无符号处理,直接除.无忧化

 

44:       printf("x/7 = %d \r\n", x/7);   //有符号变量/常量7

00401288   mov         eax,dword ptr [ebp-4]

0040128B   cdq

0040128C   mov         ecx,7

00401291   idiv        eax,ecx

00401293   push        eax

00401294   push        offset string "x/7 = %d \r\n" (004251e4)

00401299   call        printf (004016c0)

0040129E   add         esp,8

分析24: 太直观

 

45:       printf("x/-7 = %d \r\n", x/-7); //有符号变量/常量-7

004012A1   mov         eax,dword ptr [ebp-4]

004012A4   cdq

004012A5   mov         ecx,0FFFFFFF9h

004012AA   idiv        eax,ecx

004012AC   push        eax

004012AD   push        offset string "x/-7 = %d \r\n" (004251d4)

004012B2   call        printf (004016c0)

004012B7   add         esp,8

分析25: 太直观

 

46:       printf("u/7 = %d \r\n", u/7);   //无符号变量/常量7

004012BA   mov         eax,dword ptr [ebp-0Ch]

004012BD   xor         edx,edx

004012BF   mov         ecx,7

004012C4   div         eax,ecx

004012C6   push        eax

004012C7   push        offset string "u/7 = %d \r\n" (004251c4)

004012CC   call        printf (004016c0)

004012D1   add         esp,8

分析26: 太直观

 

47:       printf("u/-7 = %d \r\n", u/-7); //无符号变量/常量-7

004012D4   mov         eax,dword ptr [ebp-0Ch]

004012D7   xor         edx,edx

004012D9   mov         ecx,0FFFFFFF9h

004012DE   div         eax,ecx

004012E0   push        eax

004012E1   push        offset string "u/-7 = %d \r\n" (004251b4)

004012E6   call        printf (004016c0)

004012EB   add         esp,8

分析27: 太直观

 

49:       printf("x/8 = %d \r\n", x/8);   //有符号变量/常量8

004012EE   mov         eax,dword ptr [ebp-4]

004012F1   cdq

004012F2   and         edx,7 //1

004012F5   add         eax,edx //2

004012F7   sar         eax,3

004012FA   push        eax

004012FB   push        offset string "x/8 = %d \r\n" (004251a4)

00401300   call        printf (004016c0)

分析28: 代码功能 x/8

x > 0

x < 0 = (x+7) >> 3  这步根据推导7

12处利用x符号位,巧妙的做了调整,避免了分支.

 

50:       printf("x/-8 = %d \r\n", x/-8); //有符号变量/常量-8

00401308   mov         eax,dword ptr [ebp-4]

0040130B   cdq

0040130C   and         edx,7

0040130F   add         eax,edx

00401311   sar         eax,3

00401314   neg         eax //1

00401316   push        eax

00401317   push        offset string "x/-8 = %d \r\n" (00425194)

0040131C   call        printf (004016c0)

00401321   add         esp,8

分析29: 编译器这样做了 ;先求括号里的值,分析过程 同 分析28 ,最后第1处 结果来个求补.

 

51:       printf("u/8 = %d \r\n", u/8);   //无符号变量/常量8

00401324   mov         eax,dword ptr [ebp-0Ch]

00401327   shr         eax,3

0040132A   push        eax

0040132B   push        offset string "u/8 = %d \r\n" (00425184)

00401330   call        printf (004016c0)

00401335   add         esp,8

分析30: 无符号 2的幂 直接逻辑右移

 

52:       printf("u/-8 = %d \r\n", u/-8); //无符号变量/常量-8

00401338   mov         eax,dword ptr [ebp-0Ch]

0040133B   xor         edx,edx

0040133D   mov         ecx,0FFFFFFF8h

00401342   div         eax,ecx

00401344   push        eax

00401345   push        offset string "u/-8 = %d \r\n" (00425174)

0040134A   call        printf (004016c0)

0040134F   add         esp,8

分析31: 无符号 2的幂 直接除.无忧化

 

54:       printf("x/9 = %d \r\n", x/9);   //有符号变量/常量9

00401352   mov         eax,dword ptr [ebp-4]

00401355   cdq

00401356   mov         ecx,9

0040135B   idiv        eax,ecx

0040135D   push        eax

0040135E   push        offset string "x/9 = %d \r\n" (00425164)

00401363   call        printf (004016c0)

00401368   add         esp,8

分析32: 太直观

 

55:       printf("x/-9 = %d \r\n", x/-9); //有符号变量/常量-9

0040136B   mov         eax,dword ptr [ebp-4]

0040136E   cdq

0040136F   mov         ecx,0FFFFFFF7h

00401374   idiv        eax,ecx

00401376   push        eax

00401377   push        offset string "x/-9 = %d \r\n" (00425154)

0040137C   call        printf (004016c0)

00401381   add         esp,8

分析33: 太直观

 

 

56:       printf("u/9 = %d \r\n", u/9);   //无符号变量/常量9

00401384   mov         eax,dword ptr [ebp-0Ch]

00401387   xor         edx,edx

00401389   mov         ecx,9

0040138E   div         eax,ecx

00401390   push        eax

00401391   push        offset string "u/9 = %d \r\n" (00425144)

00401396   call        printf (004016c0)

0040139B   add         esp,8

分析34: 无符号 2的幂 直接除.无忧化

 

57:       printf("u/-9 = %d \r\n", u/-9); //无符号变量/常量-9

0040139E   mov         eax,dword ptr [ebp-0Ch]

004013A1   xor         edx,edx

004013A3   mov         ecx,0FFFFFFF7h

004013A8   div         eax,ecx

004013AA   push        eax

004013AB   push        offset string "u/-9 = %d \r\n" (00425134)

004013B0   call        printf (004016c0)

004013B5   add         esp,8

分析35: 无符号 负数,负数被当无符号处理,直接除.无忧化

 

54:       printf("x/9 = %d \r\n", x/9);   //有符号变量/常量9

00401352   mov         eax,dword ptr [ebp-4]

00401355   cdq

00401356   mov         ecx,9

0040135B   idiv        eax,ecx

0040135D   push        eax

0040135E   push        offset string "x/9 = %d \r\n" (00425164)

00401363   call        printf (004016c0)

00401368   add         esp,8

分析36: 太直观

 

55:       printf("x/-9 = %d \r\n", x/-9); //有符号变量/常量-9

0040136B   mov         eax,dword ptr [ebp-4]

0040136E   cdq

0040136F   mov         ecx,0FFFFFFF7h

00401374   idiv        eax,ecx

00401376   push        eax

00401377   push        offset string "x/-9 = %d \r\n" (00425154)

0040137C   call        printf (004016c0)

00401381   add         esp,8

分析37: 太直观

 

56:       printf("u/9 = %d \r\n", u/9);   //无符号变量/常量9

00401384   mov         eax,dword ptr [ebp-0Ch]

00401387   xor         edx,edx

00401389   mov         ecx,9

0040138E   div         eax,ecx

00401390   push        eax

00401391   push        offset string "u/9 = %d \r\n" (00425144)

00401396   call        printf (004016c0)

0040139B   add         esp,8

分析38: 太直观

 

57:       printf("u/-9 = %d \r\n", u/-9); //无符号变量/常量-9

0040139E   mov         eax,dword ptr [ebp-0Ch]

004013A1   xor         edx,edx

004013A3   mov         ecx,0FFFFFFF7h

004013A8   div         eax,ecx

004013AA   push        eax

004013AB   push        offset string "u/-9 = %d \r\n" (00425134)

004013B0   call        printf (004016c0)

004013B5   add         esp,8

分析39: 太直观

 

59:       printf("x/10 = %d \r\n", x/10);     //有符号变量/常量10

004013B8   mov         eax,dword ptr [ebp-4]

004013BB   cdq

004013BC   mov         ecx,0Ah

004013C1   idiv        eax,ecx

004013C3   push        eax

004013C4   push        offset string "x/10 = %d \r\n" (00425124)

004013C9   call        printf (004016c0)

004013CE   add         esp,8

分析40: 太直观

 

60:       printf("x/-10 = %d \r\n", x/-10);   //有符号变量/常量-10

004013D1   mov         eax,dword ptr [ebp-4]

004013D4   cdq

004013D5   mov         ecx,0FFFFFFF6h

004013DA   idiv        eax,ecx

004013DC   push        eax

004013DD   push        offset string "x/-10 = %d \r\n" (00425114)

004013E2   call        printf (004016c0)

004013E7   add         esp,8

分析41: 太直观

 

61:       printf("u/10 = %d \r\n", u/10);     //无符号变量/常量10

004013EA   mov         eax,dword ptr [ebp-0Ch]

004013ED   xor         edx,edx

004013EF   mov         ecx,0Ah

004013F4   div         eax,ecx

004013F6   push        eax

004013F7   push        offset string "u/10 = %d \r\n" (00425104)

004013FC   call        printf (004016c0)

00401401   add         esp,8

分析42: 太直观

 

62:       printf("u/-10 = %d \r\n", u/-10);   //无符号变量/常量-10

00401404   mov         eax,dword ptr [ebp-0Ch]

00401407   xor         edx,edx

00401409   mov         ecx,0FFFFFFF6h

0040140E   div         eax,ecx

00401410   push        eax

00401411   push        offset string "u/-10 = %d \r\n" (004250f4)

00401416   call        printf (004016c0)

0040141B   add         esp,8

分析43: 太直观

 

64:       printf("x/17 = %d \r\n", x/17);     //有符号变量/常量17

0040141E   mov         eax,dword ptr [ebp-4]

00401421   cdq

00401422   mov         ecx,11h

00401427   idiv        eax,ecx

00401429   push        eax

0040142A   push        offset string "x/17 = %d \r\n" (004250e4)

0040142F   call        printf (004016c0)

00401434   add         esp,8

分析44: 太直观

 

65:       printf("x/-17 = %d \r\n", x/-17);   //有符号变量/常量-17

00401437   mov         eax,dword ptr [ebp-4]

0040143A   cdq

0040143B   mov         ecx,0FFFFFFEFh

00401440   idiv        eax,ecx

00401442   push        eax

00401443   push        offset string "x/-17 = %d \r\n" (004250d4)

00401448   call        printf (004016c0)

0040144D   add         esp,8

分析45: 太直观

 

66:       printf("u/17 = %d \r\n", u/17);     //无符号变量/常量17

00401450   mov         eax,dword ptr [ebp-0Ch]

00401453   xor         edx,edx

00401455   mov         ecx,11h

0040145A   div         eax,ecx

0040145C   push        eax

0040145D   push        offset string "u/17 = %d \r\n" (004250c4)

00401462   call        printf (004016c0)

00401467   add         esp,8

分析46: 太直观

 

67:       printf("u/-17 = %d \r\n", u/-17);   //无符号变量/常量-17

0040146A   mov         eax,dword ptr [ebp-0Ch]

0040146D   xor         edx,edx

0040146F   mov         ecx,0FFFFFFEFh

00401474   div         eax,ecx

00401476   push        eax

00401477   push        offset string "u/-17 = %d \r\n" (004250b4)

0040147C   call        printf (004016c0)

00401481   add         esp,8

分析46: 太直观

 

69:       printf("x/128 = %d \r\n", x/128);   //有符号变量/常量128

00401484   mov         eax,dword ptr [ebp-4]

00401487   cdq

00401488   and         edx,7Fh //1

0040148B   add         eax,edx //2

0040148D   sar         eax,7

00401490   push        eax

00401491   push        offset string "x/128 = %d \r\n" (004250a4)

00401496   call        printf (004016c0)

0040149B   add         esp,8

分析47: 代码功能 x/4

x > 0 =  x>>7

x < 0 = (x+127) >> 7  这步根据推导7    0x7f = 127

12处利用x符号位,巧妙的做了调整,避免了分支.

 

70:       printf("x/-128 = %d \r\n", x/-128); //有符号变量/常量-128

0040149E   mov         eax,dword ptr [ebp-4]

004014A1   cdq

004014A2   and         edx,7Fh

004014A5   add         eax,edx

004014A7   sar         eax,7

004014AA   neg         eax //1

004014AC   push        eax

004014AD   push        offset string "x/-128 = %d \r\n" (00425090)

004014B2   call        printf (004016c0)

004014B7   add         esp,8

分析48: 编译器这样做了 ;先求括号里的值,分析过程 同 分析47 ,最后第1处 结果来个求补.

 

 

71:       printf("u/128 = %d \r\n", u/128);   //无符号变量/常量128

004014BA   mov         eax,dword ptr [ebp-0Ch]

004014BD   shr         eax,7

004014C0   push        eax

004014C1   push        offset string "u/128 = %d \r\n" (00425080)

004014C6   call        printf (004016c0)

004014CB   add         esp,8

分析49: 无符号 2的幂 直接发逻辑右移.

 

72:       printf("u/-128 = %d \r\n", u/-128); //无符号变量/常量-128

004014CE   mov         eax,dword ptr [ebp-0Ch]

004014D1   xor         edx,edx

004014D3   mov         ecx,0FFFFFF80h

004014D8   div         eax,ecx

004014DA   push        eax

004014DB   push        offset string "u/-128 = %d \r\n" (0042506c)

004014E0   call        printf (004016c0)

004014E5   add         esp,8

分析50: 太直观

 

74:       printf("x/7000 = %d \r\n", x/7000);     //有符号变量/常量7000

004014E8   mov         eax,dword ptr [ebp-4]

004014EB   cdq

004014EC   mov         ecx,1B58h

004014F1   idiv        eax,ecx

004014F3   push        eax

004014F4   push        offset string "x/7000 = %d \r\n" (00425058)

004014F9   call        printf (004016c0)

004014FE   add         esp,8

分析51: 太直观

 

75:       printf("x/-7000 = %d \r\n", x/-7000);   //有符号变量/常量-7000

00401501   mov         eax,dword ptr [ebp-4]

00401504   cdq

00401505   mov         ecx,0FFFFE4A8h

0040150A   idiv        eax,ecx

0040150C   push        eax

0040150D   push        offset string "x/-7000 = %d \r\n" (00425044)

00401512   call        printf (004016c0)

00401517   add         esp,8

分析52: 太直观

 

76:       printf("u/7000 = %d \r\n", u/7000);     //无符号变量/常量7000

0040151A   mov         eax,dword ptr [ebp-0Ch]

0040151D   xor         edx,edx

0040151F   mov         ecx,1B58h

00401524   div         eax,ecx

00401526   push        eax

00401527   push        offset string "u/7000 = %d \r\n" (00425030)

0040152C   call        printf (004016c0)

00401531   add         esp,8

分析53: 太直观

 

77:       printf("u/-7000 = %d \r\n", u/-7000);   //无符号变量/常量-7000

00401534   mov         eax,dword ptr [ebp-0Ch]

00401537   xor         edx,edx

00401539   mov         ecx,0FFFFE4A8h

0040153E   div         eax,ecx

00401540   push        eax

00401541   push        offset string "u/-7000 = %d \r\n" (0042501c)

00401546   call        printf (004016c0)

0040154B   add         esp,8

分析54: 太直观

79:       return 0;

0040154E   xor         eax,eax

80:   }

00401550   pop         edi

00401551   pop         esi

00401552   pop         ebx

00401553   add         esp,4Ch

00401556   cmp         ebp,esp

00401558   call        __chkesp (004017a0)

0040155D   mov         esp,ebp

0040155F   pop         ebp

00401560   ret

; int __cdecl main(int argc, const char **argv, const char **envp)

main proc near                          ; CODE XREF: start+AFp

 

x= dword ptr -0Ch

u= dword ptr -8

y= dword ptr -4

argc= dword ptr  4

argv= dword ptr  8

envp= dword ptr  0Ch

 

sub     esp, 0Ch //预留局部变量空间

xor     eax, eax

lea     ecx, [esp+0Ch+y]

mov     [esp+0Ch+x], eax //变量们初始化为0

mov     [esp+0Ch+y], eax

mov     [esp+0Ch+u], eax

lea     eax, [esp+0Ch+u]

push    eax

lea     edx, [esp+10h+x]

push    ecx

push    edx

push    offset Format                   ; "%d %d %u"

call    _scanf

//下面这段代码见的比较少见所以提前放在这里

mov     ecx, [esp+4Ch+u] //1. u

mov     eax, 7 //2. m = 7

mul     ecx //3. um

sub     ecx, edx //4. u-um/232

add     esp, 40h

shr     ecx, 1 //5. ( u-um/232)/2

add     ecx, edx //6. ( u-um/232)/2+ um/232

shr     ecx, 1Fh //7.结果 (( u-um/232)/2+ um/232)/ 231

push    ecx

push    offset aU6D_0                   ; "u/-6 = %d \r\n"

call    sub_401570

分析0:  7步结果(( u-um/232)/2+ um/232)/ 231 =

 

向上面结果靠拢推: 如果有u/b 那么

:m = --->  m+= --->  b =  = FFFFFFF9 = -7

u/ FFFFFFF9. 源码中是 u/-6.原因详见分析11 .

如果源码中是printf(“%d”,u/0xFFFFFFFA)不管 debug版本还是realse版本都不会这样去忧化.都是直接

div 0xFFFFFFFA.所以上面这种情况也可以推断是用一个无符号数除一个负数 的重要依据.

 

mov     eax, [esp+1Ch+x]

cdq

idiv    [esp+1Ch+y]

push    eax

push    offset aXYD                     ; "x/y = %d \r\n"

call    sub_401570

分析1: x/y 两个变量相除,无忧化

 

mov     eax, [esp+24h+x]

xor     edx, edx

div     [esp+24h+u]

push    eax

push    offset aXUD                     ; "x/u = %d \r\n"

call    sub_401570

分析2: x/u 两个变量相除,无忧化.有符号x被当成无符号看待.

 

mov     eax, [esp+2Ch+u]

xor     edx, edx

div     [esp+2Ch+x]

push    eax

push    offset aUXD                     ; "u/x = %d \r\n"

call    sub_401570

分析3: u/x 两个变量相除,无忧化.有符号x被当成无符号看待.

 

mov     eax, [esp+34h+x]

cdq

sub     eax, edx //1

sar     eax, 1

push    eax

push    offset aX2D                     ; "x/2 = %d \r\n"

call    sub_401570

分析4:  x/2

x>0 = x >> 1  ;  x<0时   = (x+1) >> 1

1处巧妙的运用了x符号作了调整,避免分支了!

 

mov     eax, [esp+3Ch+x]

cdq

sub     eax, edx //1

sar     eax, 1

neg     eax //2

push    eax

push    offset aX2D_0                   ; "x/-2 = %d \r\n"

call    sub_401570

分析5:  x/-2

译器这样处理了  先求括号里的值,分析过程同 分析4. 然后第2处对结果求补.

 

mov     eax, [esp+44h+u]

shr     eax, 1 //无符号 除 2

push    eax

push    offset aU2D                     ; "u/2 = %d \r\n"

call    sub_401570

分析6:  u/2

 

mov     eax, [esp+4Ch+u]

xor     edx, edx

mov     ecx, 0FFFFFFFEh

add     esp, 40h

div     ecx

push    eax

push    offset aU2D_0                   ; "u/-2 = %d \r\n"

call    sub_401570

分析7:  u/0FFFFFFFEh 

 

mov     ecx, [esp+14h+x] //1.x

mov     eax, 55555556h //2.m=55555556h = 1431655766

imul    ecx //3.xm

mov     eax, edx

shr     eax, 1Fh //4. 拿符号位

add     edx, eax //5. 调整

push    edx //6. 结果: xc/2^32

push    offset aX3D                     ; "x/3 = %d \r\n"

call    sub_401570

分析8:  最终结果 xc/2^32  =    如果有x/b : =   

m =  -->  b =  = 2.9999999986030161387273035297509 x/3

mov     ecx, [esp+1Ch+x] //1. x

mov     eax, 55555555h //2. m = 55555555h

imul    ecx //3. xm

sub     edx, ecx //4. xm-232x  

sar     edx, 1 //5.

mov     ecx, edx //6以下为调整

shr     ecx, 1Fh //7.拿符号位

add     edx, ecx //8.调整

push    edx

push    offset aX3D_0                   ; "x/-3 = %d \r\n"

call    sub_401570

分析9:   5结果表达式:  =

向上面结果靠拢推: 如果有x/b 那么

:m = --->  m-= --->  b =  = -2.9999999 x/-3;

发现 b的表达 跟结果表达式有规律. b的分子 是结果表达式的分母,b的分母是结果表达式的分子.注意看!(分析8也是这种情况).暂时命名这个规律叫 颠倒规律. 

 

为什么第六步要调整呢?

根据5结果表达式: ,m是编译器生成的幻数.通过指令分析如有sar,imul  .x肯定是个整数.则整个表达式的值 则是个实数.根据推导3

x>0时 则:  

x<0时 则:  

7处与第8处巧妙的利用x的符号位决定要不要+1,避免了分支. 以下内容均以推出除数的值为重点,调整不再说明.

 

mov     eax, 0AAAAAAABh //1. m = 0AAAAAAABh = 2863311531

mul     [esp+24h+u] //2. um

shr     edx, 1 //3. um / 233

push    edx

push    offset aU3D                     ; "u/3 = %d \r\n"

call    sub_401570

分析10: 3步结果

向上面结果靠拢推: 如果有u/b 那么

:m = --> b =  = 2.9999 u/3. 也符合颠倒规律 !

mov     eax, 40000001h //1. m = 40000001h = 1073741825

mul     [esp+2Ch+u] //2. um

shr     edx, 1Eh //3. (um)/232+30            0x1E=30

push    edx

push    offset aU3D_0                   ; "u/-3 = %d \r\n"

call    sub_401570

分析11: 3步结果 (um)/232+30 =

若有u/b:    m =  -->

 b =  =  4294967292 = 0xFFFFFFFC = -4  

u/0xFFFFFFFC其实这里是u/-3

.为什么会出现这种情况呢? 

这段代码 源码中是u/-3. 但是我们把无符号u与有符号-3相除,编译器只认为是无符号相除,-3当成无符号数,从指令中mul,shr也可以看出这点. VC是向0取整的.所以无符号只能向下取整 .而不考虑负数向上调整,+1 .后面碰到此情况不再累述.

符合颠倒规律 !

 

mov     eax, [esp+34h+x] //1. x

cdq

and     edx, 3 //2.调整

add     eax, edx

sar     eax, 2 //3. x/22

push    eax

push    offset aX4D                     ; "x/4 = %d \r\n"

call    sub_401570

分析12:  x/22

x>0 = x >> 2  ;  x<0时   = (x+3) >> 2

2处巧妙的运用了x符号作了调整,避免分支了!

 

mov     eax, [esp+3Ch+x] //1. x

cdq

and     edx, 3 //2. 调整

add     eax, edx

sar     eax, 2 //3. x/22

neg     eax //4. x求补

push    eax

push    offset aX4D_0                   ; "x/-4 = %d \r\n"

call    sub_401570

 

分析13:  x/-22 

译器这样处理了  先求括号里的值,分析过程同 分析12. 然后第4处对结果求补. 

 

mov     edx, [esp+44h+u] //1. u

shr     edx, 2 //2. u/22

push    edx

push    offset aU4D                     ; "u/4 = %d \r\n"

call    sub_401570

分析14:  u/22 

 

mov     eax, [esp+4Ch+u] //1. u

xor     edx, edx

mov     ecx, 0FFFFFFFCh //2.-4

add     esp, 40h

div     ecx

push    eax

push    offset aU4D_0                   ; "u/-4 = %d \r\n"

call    sub_401570

分析15:  u/0FFFFFFFCh  不再累述.

 

mov     ecx, [esp+14h+x] //1. x

mov     eax, 66666667h //2. m = 66666667h = 1717986919

imul    ecx //3. xm

sar     edx, 1 //4. 结果 xm/232+1

mov     eax, edx //5. 开始调整

shr     eax, 1Fh

add     edx, eax

push    edx

push    offset aX5D                     ; "x/5 = %d \r\n"

call    sub_401570

分析16:  结果xm/232+1  =    如果有x/b : =   

m =  -->  b =  = 4.9999999982537701732058415050132x/5 .符合颠倒规律 !

 

mov     ecx, [esp+1Ch+x] //1. x

mov     eax, 99999999h //2. m = 99999999h = 2576980377

imul    ecx //3. x * -(232-m) = xm - 232x

sar     edx, 1 //4.结果 ( xm - 232x)/232+1

mov     ecx, edx //5. 开始调整

shr     ecx, 1Fh

add     edx, ecx

push    edx

push    offset aX5D_0                   ; "x/-5 = %d \r\n"

call    sub_401570

分析17:   4结果: ( xm - 232x)/232+1  =

向上面结果靠拢推: 如果有x/b 那么

:m = --->  m-= --->  b =  = -4.9999 x/-5; 符合颠倒规律 !

mov     eax, 0CCCCCCCDh //1. m = 0CCCCCCCDh = 3435973837

mul     [esp+24h+u] //2. um

shr     edx, 2 //3.结果um/232+2

push    edx

push    offset aU5D                     ; "u/5 = %d \r\n"

call    sub_401570

分析18: 3步结果 um/232+2  = 

向上面结果靠拢推: 如果有u/b 那么

:m = --> b =  = 4.9999 u/5. 也符合颠倒规律 !

 

mov     eax, 80000003h //1. m = 80000003h = 2147483651

mul     [esp+2Ch+u] //2. um  无符号mul不需要把80000003h转补码,这里当正数就是原码.

shr     edx, 1Fh //3. 结果 um /232+31

push    edx

push    offset aU5D_0                   ; "u/-5 = %d \r\n"

call    sub_401570

分析19: 3步结果 (um)/232+31 =   若有u/b:    m =  -->

 b =  = 4294967290 =  FFFFFFFA = -6 u/ FFFFFFFA

源码中是 u/-5 原因详见分析11 .符合颠倒规律 !

 

mov     ecx, [esp+34h+x] //1. x

mov     eax, 2AAAAAABh //2. m = 2AAAAAABh = 715827883

imul    ecx //3. xm

mov     eax, edx //4.开始调整

shr     eax, 1Fh

add     edx, eax

push    edx //5.结果xm/232

push    offset aX6D                     ; "x/6 = %d \r\n"

call    sub_401570

分析20:  结果xm/232  =    如果有x/b : =   

m =  -->  b =  = 5.9999999972060322774546070595018x/6 .符合颠倒规律 !

mov     ecx, [esp+3Ch+x] //1. x

mov     eax, 0D5555555h //2. m = 0D5555555h = 3579139413

imul    ecx //3. 有符号转真值 x(m-232) = xm - 232x

mov     ecx, edx //4. 开始调整

shr     ecx, 1Fh

add     edx, ecx

push    edx //5.结果(xm - 232x)/ 232

push    offset aX6D_0                   ; "x/-6 = %d \r\n"

call    sub_401570

分析21:   5结果表达式: (xm - 232x)/ 232 =  =

向上面结果靠拢推: 如果有x/b 那么

:m = --->  m-= --->  b =  = -5.9999999 x/-6;

符合颠倒规律 !

 

mov     eax, 0AAAAAAABh //1. m = 0AAAAAAABh = 2863311531

mul     [esp+44h+u] //2. um

shr     edx, 2 //3. 结果 um/232+2

push    edx

push    offset aU6D                     ; "u/6 = %d \r\n"

call    sub_401570

分析22: 3步结果um/232+2  =

向上面结果靠拢推: 如果有u/b 那么

:m = --> b =  = 5.9999 u/6. 也符合颠倒规律 !

 

mov     ecx, [esp+4Ch+u] //1. u

mov     eax, 7 //2. m = 7

mul     ecx //3. um

sub     ecx, edx //4. u-um/232

add     esp, 40h

shr     ecx, 1 //5. ( u-um/232)/2

add     ecx, edx //6. ( u-um/232)/2+ um/232

shr     ecx, 1Fh //7.结果 (( u-um/232)/2+ um/232)/ 231

push    ecx

push    offset aU6D_0                   ; "u/-6 = %d \r\n"

call    sub_401570

分析23: 7步结果(( u-um/232)/2+ um/232)/ 231 =

向上面结果靠拢推: 如果有u/b 那么

:m = --->  m+= --->  b =  = FFFFFFF9 = -7

u/ FFFFFFF9. 源码中是 u/-6.原因详见分析11 .符合颠倒规律 !

 

 

mov     ecx, [esp+14h+x] //1. x

mov     eax, 92492493h //2. m = 92492493h = 2454267027

imul    ecx //3. xm-232x 有符号imul 数学公式要 还原真值

add     edx, ecx //4. (xm-232x) +232x  = xm  edx相加相当于x>>32

sar     edx, 2 //5.结果 xm/232+2 

mov     eax, edx //6.开始调整

shr     eax, 1Fh

add     edx, eax

push    edx

push    offset aX7D                     ; "x/7 = %d \r\n"

call    sub_401570

分析24:  结果 xm/232+2  =    如果有x/b : =   

m =  -->  b =  = 6.9999999986 x/7 .符合颠倒规律 !

 

mov     ecx, [esp+1Ch+x] //1. x

mov     eax, 6DB6DB6Dh //2. m = 6DB6DB6Dh = 1840700269

imul    ecx //3. xm

sub     edx, ecx //4. xm-232x edx相减相当于x>>32,再减

sar     edx, 2 //5.( xm-232x)/ 232+2

mov     ecx, edx //6. 开始调整

shr     ecx, 1Fh

add     edx, ecx

push    edx

push    offset aX7D_0                   ; "x/-7 = %d \r\n"

call    sub_401570

分析25:   5结果表达式: ( xm-232x)/ 232+2  =  =

向上面结果靠拢推: 如果有x/b 那么

:m = --->  m-= --->  b =  = -6.9999 x/-7符合颠倒规律 !

 

mov     ecx, [esp+24h+u] //1. u

mov     eax, 24924925h //2. m = 24924925h = 613566757

mul     ecx //3. um

sub     ecx, edx //4. 232u-um edx相减 u>>32再减

shr     ecx, 1 //5. ( 232u-um)/ 232+1

add     ecx, edx //6. ( 232u-um)/ 233 + um/232

shr     ecx, 2 //7.结果 ( ( 232u-um)/ 233 + um/232 ) /22

push    ecx

push    offset aU7D                     ; "u/7 = %d \r\n"

call    sub_401570

分析26:   结果 ( ( 232u-um)/ 233 + um/232 ) / 22=

 

向上面结果靠拢推: 如果有u/b 那么

:m = --->  m+= --->  b =  = 6.9999 = 7

u/ 7.符合颠倒规律 !

 

mov     eax, 20000001h //1. m = 536870913

mul     [esp+2Ch+u] //2. um

shr     edx, 1Dh //3.结果 um/232+29

push    edx

push    offset aU7D_0                   ; "u/-7 = %d \r\n"

call    sub_401570

分析27: 3步结果um/232+29 =   若有u/b:    m =  -->

 b =  = 4294967290 =  FFFFFFF8= -8  还原 源码中则是 u/-7 原因详见分析11 .符合颠倒规律 !

 

mov     eax, [esp+34h+x]

cdq

and     edx, 7

add     eax, edx

sar     eax, 3

push    eax

push    offset aX8D                     ; "x/8 = %d \r\n"

call    sub_401570

分析28:  x/23

x>0 = x >> 3  ;  x<0时   = (x+7) >>3

mov     eax, [esp+3Ch+x]

cdq

and     edx, 7

add     eax, edx

sar     eax, 3

neg     eax

push    eax

push    offset aX8D_0                   ; "x/-8 = %d \r\n"

call    sub_401570

分析29:  x/-23 

译器这样处理了  先求括号里的值,分析过程同 分析28. 然后第4处对结果求补. 

 

mov     edx, [esp+44h+u] //1. u

shr     edx, 3 //2. u/23

push    edx

push    offset aU8D                     ; "u/8 = %d \r\n"

call    sub_401570

分析30:  u/8 太直观

 

mov     eax, [esp+4Ch+u] //1. u

xor     edx, edx

mov     ecx, 0FFFFFFF8h //2.

add     esp, 40h

div     ecx

push    eax

push    offset aU8D_0                   ; "u/-8 = %d \r\n"

call    sub_401570

分析30:  u/0FFFFFFF8h 太直观

 

mov     ecx, [esp+14h+x] //1. x

mov     eax, 38E38E39h //2. m = 38E38E39h = 954437177

imul    ecx //3. xm

sar     edx, 1 //4.结果 xm/232+1

mov     eax, edx //5. 开始调整

shr     eax, 1Fh

add     edx, eax

push    edx

push    offset aX9D                     ; "x/9 = %d \r\n"

call    sub_401570

分析31:  最终结果xm/232+1  =    如果有x/b : =   

m =  -->  b =  = 8.999999998603016 x/9 .符合颠倒规律 !

 

mov     ecx, [esp+1Ch+x] //1. x

mov     eax, 0C71C71C7h //2. m = C71C71C7h = 3340530119

imul    ecx //3. xm – x232

sar     edx, 1 //4.结果 (xm – x232)/232+1

mov     ecx, edx //5.调整

shr     ecx, 1Fh

add     edx, ecx

push    edx

push    offset aX9D_0                   ; "x/-9 = %d \r\n"

call    sub_401570

分析32:   结果: (xm – x232)/232+1 =  =

向上面结果靠拢推: 如果有x/b 那么

:m = --->  m-= --->  b =  = -8.99999 x/-9; 符合颠倒规律 !

 

mov     eax, 38E38E39h //1. m = 38E38E39h = 954437177

mul     [esp+24h+u] //2. um

shr     edx, 1 //3. um/232+1 

push    edx

push    offset aU9D                     ; "u/9 = %d \r\n"

call    sub_401570

分析33: 3步结果um/232+1  =

向上面结果靠拢推: 如果有u/b 那么

:m = --> b =  = 8.9999 u/9. 也符合颠倒规律 !

 

mov     eax, 80000005h //1. m = 80000005h = 2147483653

mul     [esp+2Ch+u] //2. um

shr     edx, 1Fh //3. 结果 um/232+31

push    edx

push    offset aU9D_0                   ; "u/-9 = %d \r\n"

call    sub_401570

分析34: 3步结果 (um)/232+31 =   若有u/b:    m =  -->

 b =  = 4294967290 =  FFFFFFF6= -10 u/ FFFFFFF6

源码中是 u/-9 原因详见分析11 .符合颠倒规律 !

 

mov     ecx, [esp+34h+x] //1. x

mov     eax, 66666667h //2. m = 66666667h = 1717986919

imul    ecx //3. mx

sar     edx, 2 //4. 结果mx/232+2

mov     eax, edx //5.开始调整

shr     eax, 1Fh

add     edx, eax

push    edx

push    offset aX10D                    ; "x/10 = %d \r\n"

call    sub_401570

分析35:  结果 xm/232+2  =    如果有x/b : =   

m =  -->  b =  = 9.9999999即x/10 .符合颠倒规律 !

 

mov     ecx, [esp+3Ch+x] //1. x

mov     eax, 99999999h //2.m = 99999999h = 2576980377

imul    ecx //3. x(m-232)

sar     edx, 2 //4. x(m-232)/232+2

mov     ecx, edx //5. 开始调整

shr     ecx, 1Fh

add     edx, ecx

push    edx

push    offset aX10D_0                  ; "x/-10 = %d \r\n"

call    sub_401570

分析36   4结果表达式: x(m-232)/232+2  =  =

向上面结果靠拢推: 如果有x/b 那么

:m = --->  m-= --->  b =  = -9.9999 x/-10; 符合颠倒规律 !

 

mov     eax, 0CCCCCCCDh //1. m = 0CCCCCCCDh = 3435973837

mul     [esp+44h+u] //2. um

shr     edx, 3 //3. 结果 um/232+3

push    edx

push    offset aU10D                    ; "u/10 = %d \r\n"

call    sub_401570

分析37: 3步结果um/232+3  =

向上面结果靠拢推: 如果有u/b 那么

:m = --> b =  = 9.9999 u/10. 也符合颠倒规律 !

 

mov     ecx, [esp+4Ch+u] //1. u

mov     eax, 0Bh //2. m = 11

mul     ecx //3. um

sub     ecx, edx //4. 232u-um

add     esp, 40h

shr     ecx, 1 //5. (232u-um)/232+1

add     ecx, edx //6. (232u-um)/232+1+um/232

shr     ecx, 1Fh //7. ((232u-um)/232+1+um/232)/231

push    ecx

push    offset aU10D_0                  ; "u/-10 = %d \r\n"

call    sub_401570

分析38:   结果 ( ( 232u-um)/ 233 + um/232 ) / 231=

 

向上面结果靠拢推: 如果有u/b 那么

:m = --->  m+= --->  b =  = FFFFFFF5 = -11

u/ FFFFFFF5

源码中是 u/-10 原因详见分析11 .符合颠倒规律 !

 

mov     ecx, [esp+14h+x] //1. x

mov     eax, 78787879h //2. m = 78787879h = 2021161081

imul    ecx //3. xm

sar     edx, 3 //4. xm/232+3

mov     eax, edx //5. 开始调整

shr     eax, 1Fh

add     edx, eax

push    edx

push    offset aX17D                    ; "x/17 = %d \r\n"

call    sub_401570

分析39:  最终结果xm/232+3  =    如果有x/b : =   

m =  -->  b =  = 16.999999998603 x/17 .符合颠倒规律 !

 

mov     ecx, [esp+1Ch+x] //1. x

mov     eax, 87878787h //2. m =  87878787h = 2273806215

imul    ecx //3. x(m-232)

sar     edx, 3 //4. x(m-232)/232+3

mov     ecx, edx //5. 开始调整

shr     ecx, 1Fh

add     edx, ecx

push    edx

push    offset aX17D_0                  ; "x/-17 = %d \r\n"

call    sub_401570

分析40:   结果: x(m – 232)/232+3 =  =

向上面结果靠拢推: 如果有x/b 那么

:m = --->  m-= --->  b =  = -16.999 x/-17; 符合颠倒规律 !

34359738368/(2273806215-4294967296)

 

mov     eax, 0F0F0F0F1h //1. m = F0F0F0F1h = 4042322161

mul     [esp+24h+u] //2. um

shr     edx, 4 //3. um/232+4

push    edx

push    offset aU17D                    ; "u/17 = %d \r\n"

call    sub_401570

分析41: 3步结果um/232+4  =

向上面结果靠拢推: 如果有u/b 那么

:m = --> b =  = 16.9999 u/17. 也符合颠倒规律 !

 

mov     eax, 80000009h //1. m = 80000009h = 2147483657

mul     [esp+2Ch+u] //2. um

shr     edx, 1Fh //3. um/232+31

push    edx

push    offset aU17D_0                  ; "u/-17 = %d \r\n"

call    sub_401570

分析42: 3步结果 (um)/232+31 =   若有u/b:    m =  -->

 b =  = FFFFFFEE = -18 u/ FFFFFFEE

源码中是 u/-17 原因详见分析11 .符合颠倒规律 !

 

mov     eax, [esp+34h+x] //1. x

cdq

and     edx, 7Fh //2.开始调整

add     eax, edx

sar     eax, 7 //3.x/27

push    eax

push    offset aX128D                   ; "x/128 = %d \r\n"

call    sub_401570

分析43:  .x/27  

x>0 = x >> 7  ;  x<0时   = (x+7) >> 7

2处巧妙的运用了x符号作了调整,避免分支了!

 

mov     eax, [esp+3Ch+x]

cdq

and     edx, 7Fh

add     eax, edx

sar     eax, 7

neg     eax

push    eax

push    offset aX128D_0                 ; "x/-128 = %d \r\n"

call    sub_401570

分析44:  x/-27 

译器这样处理了  先求括号里的值,分析过程同 分析43. 然后对结果求补.

 

mov     edx, [esp+44h+u]

shr     edx, 7

push    edx

push    offset aU128D                   ; "u/128 = %d \r\n"

call    sub_401570

分析45:  u/128 太直观

 

mov     eax, [esp+4Ch+u] //1. u

xor     edx, edx

mov     ecx, 0FFFFFF80h //2. m = 0FFFFFF80h

add     esp, 40h

div     ecx u/m

push    eax

push    offset aU128D_0                 ; "u/-128 = %d \r\n"

call    sub_401570

分析45:  u/0FFFFFF80h太直观 源码中是 u/-128

 

mov     ecx, [esp+14h+x] //1. x

mov     eax, 2572FB07h //2. m = 2572FB07h = 628292359

imul    ecx //3. xm

sar     edx, 0Ah //4. xm/232+10

mov     eax, edx //5.开始调整

shr     eax, 1Fh

add     edx, eax

push    edx

push    offset aX7000D                  ; "x/7000 = %d \r\n"

call    sub_401570

分析46:  结果xm/232+10  =    如果有x/b : =   

m =  -->  b =  = 6999.9999982x/7000 .符合颠倒规律 !

mov     ecx, [esp+1Ch+x] //1. x

mov     eax, 0DA8D04F9h //2. m = 0DA8D04F9h = 3666674937

imul    ecx //3. x(m-232)

sar     edx, 0Ah //4. x(m-232)/232+10

mov     ecx, edx //5. 开始调整

shr     ecx, 1Fh

add     edx, ecx

push    edx

push    offset aX7000D_0                ; "x/-7000 = %d \r\n"

call    sub_401570

分析47   4结果表达式: x(m-232)/232+10  =  =

向上面结果靠拢推: 如果有x/b 那么

:m = --->  m-= --->  b =  = -6999.9999 x/-7000; 符合颠倒规律 !

 

4398046511104/(3666674937-4294967296)

xor     eax, eax

add     esp, 34h

retn

main endp

posted @ 2019-07-08 19:06  CharyGao  阅读(881)  评论(0编辑  收藏  举报