zoukankan      html  css  js  c++  java
  • 除法与模运算的识别-大量除法推导过程

    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 ", 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 " (00425354)

    00401063    call         printf (004016c0)

    00401068    add          esp,8

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

     

    16:       printf("x/u = %d ", 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 " (00425344)

    00401079   call         printf (004016c0)

    0040107E   add          esp,8

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

    17:       printf("u/x = %d ", 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 " (00425334)

    0040108F   call         printf (004016c0)

    00401094   add          esp,8

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

     

    19:       printf("x/2 = %d ", 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 " (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 ", 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 " (00425314)

    004010BD   call         printf (004016c0)

    004010C2   add          esp,8

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

    21:       printf("u/2 = %d ", 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 " (00425304)

    004010D0   call         printf (004016c0)

    004010D5   add          esp,8

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

    22:       printf("u/-2 = %d ", 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 " (004252f4)

    004010EA   call         printf (004016c0)

    004010EF   add          esp,8

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

     

    24:       printf("x/3 = %d ", 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 " (004252e4)

    00401103   call         printf (004016c0)

    00401108   add          esp,8

    分析8: 太直观

    25:       printf("x/-3 = %d ", 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 " (004252d4)

    0040111C   call         printf (004016c0)

    00401121   add          esp,8

    分析9: 太直观

    26:       printf("u/3 = %d ", 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 " (004252c4)

    00401136   call         printf (004016c0)

    0040113B   add          esp,8

    分析10: 太直观

    27:       printf("u/-3 = %d ", 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 " (004252b4)

    00401150   call         printf (004016c0)

    00401155   add          esp,8

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

     

    29:       printf("x/4 = %d ", 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 " (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 ", 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 " (00425294)

    00401186   call         printf (004016c0)

    0040118B   add          esp,8

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

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

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

    00401191   shr          eax,2

    00401194   push         eax

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

    0040119A   call         printf (004016c0)

    0040119F   add          esp,8

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

    32:       printf("u/-4 = %d ", 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 " (00425274)

    004011B4   call         printf (004016c0)

    004011B9   add          esp,8

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

     

    34:       printf("x/5 = %d ", 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 " (00425264)

    004011CD   call         printf (004016c0)

    004011D2   add          esp,8

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

    35:       printf("x/-5 = %d ", 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 " (00425254)

    004011E6   call         printf (004016c0)

    004011EB   add          esp,8

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

    36:       printf("u/5 = %d ", 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 " (00425244)

    00401200   call         printf (004016c0)

    00401205   add          esp,8

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

    37:       printf("u/-5 = %d ", 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 " (00425234)

    0040121A   call         printf (004016c0)

    0040121F   add          esp,8

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

     

    39:       printf("x/6 = %d ", 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 " (00425224)

    00401233   call         printf (004016c0)

    00401238   add          esp,8

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

    40:       printf("x/-6 = %d ", 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 " (00425214)

    0040124C   call         printf (004016c0)

    00401251   add          esp,8

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

    41:       printf("u/6 = %d ", 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 " (00425204)

    00401266   call        printf (004016c0)

    0040126B   add         esp,8

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

    42:       printf("u/-6 = %d ", 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 " (004251f4)

    00401280   call        printf (004016c0)

    00401285   add         esp,8

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

    44:       printf("x/7 = %d ", 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 " (004251e4)

    00401299   call        printf (004016c0)

    0040129E   add         esp,8

    分析24: 太直观

     

    45:       printf("x/-7 = %d ", 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 " (004251d4)

    004012B2   call        printf (004016c0)

    004012B7   add         esp,8

    分析25: 太直观

    46:       printf("u/7 = %d ", 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 " (004251c4)

    004012CC   call        printf (004016c0)

    004012D1   add         esp,8

    分析26: 太直观

    47:       printf("u/-7 = %d ", 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 " (004251b4)

    004012E6   call        printf (004016c0)

    004012EB   add         esp,8

    分析27: 太直观

     

    49:       printf("x/8 = %d ", 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 " (004251a4)

    00401300   call        printf (004016c0)

    分析28: 代码功能 x/8

    x > 0

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

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

    50:       printf("x/-8 = %d ", 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 " (00425194)

    0040131C   call        printf (004016c0)

    00401321   add         esp,8

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

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

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

    00401327   shr         eax,3

    0040132A   push        eax

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

    00401330   call        printf (004016c0)

    00401335   add         esp,8

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

    52:       printf("u/-8 = %d ", 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 " (00425174)

    0040134A   call        printf (004016c0)

    0040134F   add         esp,8

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

    54:       printf("x/9 = %d ", 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 " (00425164)

    00401363   call        printf (004016c0)

    00401368   add         esp,8

    分析32: 太直观

    55:       printf("x/-9 = %d ", 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 " (00425154)

    0040137C   call        printf (004016c0)

    00401381   add         esp,8

    分析33: 太直观

    56:       printf("u/9 = %d ", 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 " (00425144)

    00401396   call        printf (004016c0)

    0040139B   add         esp,8

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

    57:       printf("u/-9 = %d ", 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 " (00425134)

    004013B0   call        printf (004016c0)

    004013B5   add         esp,8

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

    54:       printf("x/9 = %d ", 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 " (00425164)

    00401363   call        printf (004016c0)

    00401368   add         esp,8

    分析36: 太直观

    55:       printf("x/-9 = %d ", 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 " (00425154)

    0040137C   call        printf (004016c0)

    00401381   add         esp,8

    分析37: 太直观

    56:       printf("u/9 = %d ", 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 " (00425144)

    00401396   call        printf (004016c0)

    0040139B   add         esp,8

    分析38: 太直观

    57:       printf("u/-9 = %d ", 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 " (00425134)

    004013B0   call        printf (004016c0)

    004013B5   add         esp,8

    分析39: 太直观

    59:       printf("x/10 = %d ", 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 " (00425124)

    004013C9   call        printf (004016c0)

    004013CE   add         esp,8

    分析40: 太直观

    60:       printf("x/-10 = %d ", 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 " (00425114)

    004013E2   call        printf (004016c0)

    004013E7   add         esp,8

    分析41: 太直观

    61:       printf("u/10 = %d ", 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 " (00425104)

    004013FC   call        printf (004016c0)

    00401401   add         esp,8

    分析42: 太直观

    62:       printf("u/-10 = %d ", 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 " (004250f4)

    00401416   call        printf (004016c0)

    0040141B   add         esp,8

    分析43: 太直观

     

    64:       printf("x/17 = %d ", 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 " (004250e4)

    0040142F   call        printf (004016c0)

    00401434   add         esp,8

    分析44: 太直观

    65:       printf("x/-17 = %d ", 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 " (004250d4)

    00401448   call        printf (004016c0)

    0040144D   add         esp,8

    分析45: 太直观

    66:       printf("u/17 = %d ", 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 " (004250c4)

    00401462   call        printf (004016c0)

    00401467   add         esp,8

    分析46: 太直观

     

    67:       printf("u/-17 = %d ", 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 " (004250b4)

    0040147C   call        printf (004016c0)

    00401481   add         esp,8

    分析46: 太直观

    69:       printf("x/128 = %d ", 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 " (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 ", 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 " (00425090)

    004014B2   call        printf (004016c0)

    004014B7   add         esp,8

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

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

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

    004014BD   shr         eax,7

    004014C0   push        eax

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

    004014C6   call        printf (004016c0)

    004014CB   add         esp,8

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

    72:       printf("u/-128 = %d ", 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 " (0042506c)

    004014E0   call        printf (004016c0)

    004014E5   add         esp,8

    分析50: 太直观

    74:       printf("x/7000 = %d ", 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 " (00425058)

    004014F9   call        printf (004016c0)

    004014FE   add         esp,8

    分析51: 太直观

    75:       printf("x/-7000 = %d ", 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 " (00425044)

    00401512   call        printf (004016c0)

    00401517   add         esp,8

    分析52: 太直观

    76:       printf("u/7000 = %d ", 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 " (00425030)

    0040152C   call        printf (004016c0)

    00401531   add         esp,8

    分析53: 太直观

    77:       printf("u/-7000 = %d ", 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 " (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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    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 "

    call    sub_401570

    分析44:  x/-27 

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

    mov     edx, [esp+44h+u]

    shr     edx, 7

    push    edx

    push    offset aU128D                   ; "u/128 = %d "

    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 "

    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 "

    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 "

    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

  • 相关阅读:
    阿里代码检查工具
    SpringCloud 服务通信方法
    Apache ab简单使用
    H5 webSocket使用
    Java list去重 取重
    解决 spring boot Failed to decode downloaded font
    Pycharm设置快捷方式
    环境变量与文件的查找
    Linux基础
    VIM中文乱码解决
  • 原文地址:https://www.cnblogs.com/Chary/p/11153128.html
Copyright © 2011-2022 走看看