c++ 反汇编 除法优化

接上篇:《C++反汇编与逆向分析技术揭秘》--算术运算和赋值

printf("argc / 4 = %d\n", argc / 4);
printf("argc / 5 = %d\n", argc / 5);
printf("argc / 7 = %d\n", argc / 7);
printf("argc / -4 = %d\n", argc / -4);
printf("argc / -5 = %d\n", argc / -5);
printf("argc / -7 = %d\n", argc / -7);
printf("argc % 3 = %d\n", argc % 3);
printf("argc % 4 = %d\n", argc % 4);
printf("argc % -7 = %d\n", argc % -7);
printf("argc % -8 = %d\n", argc % -8);

01334B50 <ope | 55                 | push ebp                         | operation.cpp:156
01334B51      | 8BEC               | mov ebp,esp                      |
01334B53      | 56                 | push esi                         | esi:__argc
01334B54      | 57                 | push edi                         |
01334B55      | 8B7D 08            | mov edi,dword ptr ss:[ebp+0x8]   | operation.cpp:162
01334B58      | 8BC7               | mov eax,edi                      |除数为2的幂时采用sar,算术右移,相当于向下取整,负数情况下需要调整
01334B5A      | 99                 | cdq                              |
01334B5B      | 83E2 03            | and edx,0x3                      |考虑被除数为负数时,要加上(2^n)-1,
01334B5E      | 03C2               | add eax,edx                      |
01334B60      | C1F8 02            | sar eax,0x2                      |
01334B63      | 50                 | push eax                         |
01334B64      | 68 FC933A01        | push operation.13A93FC           | 13A93FC:"argc / 4 = %d\n"
01334B69      | E8 02010000        | call <operation.printf>          |
01334B6E      | B8 67666666        | mov eax,0x66666667               |
01334B73      | F7EF               | imul edi                         |
01334B75      | D1FA               | sar edx,0x1                      |
01334B77      | 8BC2               | mov eax,edx                      |>>>2**33/0x66666667 =4.99999999825377
01334B79      | C1E8 1F            | shr eax,0x1F                     |
01334B7C      | 03C2               | add eax,edx                      |
01334B7E      | 50                 | push eax                         |
01334B7F      | 68 0C943A01        | push operation.13A940C           | 13A940C:"argc / 5 = %d\n"
01334B84      | E8 E7000000        | call <operation.printf>          |
01334B89      | B8 93244992        | mov eax,0x92492493               |
01334B8E      | F7EF               | imul edi                         |
01334B90      | 03D7               | add edx,edi                      |
01334B92      | C1FA 02            | sar edx,0x2                      |
01334B95      | 8BF2               | mov esi,edx                      | >>> 2**34/0x92492493=6.999999997962732
01334B97      | C1EE 1F            | shr esi,0x1F                     | esi:__argc
01334B9A      | 03F2               | add esi,edx                      | esi:__argc
01334B9C      | 56                 | push esi                         | esi:__argc
01334B9D      | 68 1C943A01        | push operation.13A941C           | 13A941C:"argc / 7 = %d\n"
01334BA2      | E8 C9000000        | call <operation.printf>          |
01334BA7      | 8BC7               | mov eax,edi                      |
01334BA9      | 99                 | cdq                              |
01334BAA      | 83E2 03            | and edx,0x3                      |
01334BAD      | 03C2               | add eax,edx                      |
01334BAF      | C1F8 02            | sar eax,0x2                      |
01334BB2      | F7D8               | neg eax                          |//多一步取反
01334BB4      | 50                 | push eax                         |
01334BB5      | 68 2C943A01        | push operation.13A942C           | 13A942C:"argc / -4 = %d\n"
01334BBA      | E8 B1000000        | call <operation.printf>          |
01334BBF      | B8 99999999        | mov eax,0x99999999               |
01334BC4      | F7EF               | imul edi                         |
01334BC6      | D1FA               | sar edx,0x1                      |
01334BC8      | 8BC2               | mov eax,edx                      |>>> 2**33/(2**32-0x99999999)=4.99999999825377
01334BCA      | C1E8 1F            | shr eax,0x1F                     |
01334BCD      | 03C2               | add eax,edx                      |
01334BCF      | 50                 | push eax                         |
01334BD0      | 68 3C943A01        | push operation.13A943C           | 13A943C:"argc / -5 = %d\n"
01334BD5      | E8 96000000        | call <operation.printf>          |
01334BDA      | B8 6DDBB66D        | mov eax,0x6DB6DB6D               |
01334BDF      | F7EF               | imul edi                         |
01334BE1      | 2BD7               | sub edx,edi                      |
01334BE3      | C1FA 02            | sar edx,0x2                      |
01334BE6      | 8BC2               | mov eax,edx                      |>>> 2**34/(2**32-0x6db6db6d)=6.999999997962732
01334BE8      | C1E8 1F            | shr eax,0x1F                     |
01334BEB      | 03C2               | add eax,edx                      |
01334BED      | 50                 | push eax                         |
01334BEE      | 68 4C943A01        | push operation.13A944C           | 13A944C:"argc / -7 = %d\n"
01334BF3      | E8 78000000        | call <operation.printf>          |
01334BF8      | B8 56555555        | mov eax,0x55555556               |
01334BFD      | 8BCF               | mov ecx,edi                      |
01334BFF      | F7EF               | imul edi                         |
01334C01      | 8BC2               | mov eax,edx                      |>>> 2**32/0x55555556=2.999999998603016
01334C03      | C1E8 1F            | shr eax,0x1F                     |
01334C06      | 03C2               | add eax,edx                      |
01334C08      | 8D0440             | lea eax,dword ptr ds:[eax+eax*2] |
01334C0B      | 2BC8               | sub ecx,eax                      |
01334C0D      | 51                 | push ecx                         |
01334C0E      | 68 5C943A01        | push operation.13A945C           | 13A945C:"argc % 3 = %d\n"
01334C13      | E8 58000000        | call <operation.printf>          |
01334C18      | 8BC7               | mov eax,edi                      |
01334C1A      | 25 03000080        | and eax,0x80000003               |对2的N次方数取余使用and操作,x%2^N 使用位运算x & (2^N - 1)代替
01334C1F      | 79 05              | jns operation.1334C26            |
01334C21      | 48                 | dec eax                          |减一
01334C22      | 83C8 FC            | or eax,0xFFFFFFFC                |相当于取反
01334C25      | 40                 | inc eax                          |加一
01334C26      | 50                 | push eax                         |
01334C27      | 68 6C943A01        | push operation.13A946C           | 13A946C:"argc % 4 = %d\n"
01334C2C      | E8 3F000000        | call <operation.printf>          |
01334C31      | 83C4 40            | add esp,0x40                     |
01334C34      | 8D0CF5 00000000    | lea ecx,dword ptr ds:[esi*8]     |
01334C3B      | 2BCE               | sub ecx,esi                      | esi:__argc
01334C3D      | 8BC7               | mov eax,edi                      |
01334C3F      | 2BC1               | sub eax,ecx                      |
01334C41      | 50                 | push eax                         |
01334C42      | 68 7C943A01        | push operation.13A947C           | 13A947C:"argc % -7 = %d\n"
01334C47      | E8 24000000        | call <operation.printf>          |
01334C4C      | 81E7 07000080      | and edi,0x80000007               |
01334C52      | 79 05              | jns operation.1334C59            |
01334C54      | 4F                 | dec edi                          |减一
01334C55      | 83CF F8            | or edi,0xFFFFFFF8                |
01334C58      | 47                 | inc edi                          |
01334C59      | 57                 | push edi                         |
01334C5A      | 68 8C943A01        | push operation.13A948C           | 13A948C:"argc % -8 = %d\n"
01334C5F      | E8 0C000000        | call <operation.printf>          |
01334C64      | 83C4 10            | add esp,0x10                     |
01334C67      | 33C0               | xor eax,eax                      | operation.cpp:167
01334C69      | 5F                 | pop edi                          |
01334C6A      | 5E                 | pop esi                          | esi:__argc
01334C6B      | 5D                 | pop ebp                          | operation.cpp:168
01334C6C      | C3                 | ret                              |
 除数为正数时:
     除数为2的幂时
         mov eax,edi                      
         cdq                              
         and edx,0x3                     
         add eax,edx                     
         sar eax,0x2                     /4
     
     除数不为2的幂时:
         magicnumber<=0x7fffffff时:
         mov eax,0x66666667               |
         imul edi                         |
         sar edx,0x1                      |
         mov eax,edx                      |>>>2**33/0x66666667 =4.99999999825377
         shr eax,0x1F                     |
         add eax,edx
     
         magicnumber>0x7fffffff时:
         mov eax,0x92492493               |
         imul edi                         |
         add edx,edi                      |
         sar edx,0x2                      |
         mov esi,edx                      | >>> 2**34/0x92492493=6.999999997962732
         shr esi,0x1F                
         add esi,edx
 
 
 除数为负数时:
     除数为2的幂时
         mov eax,edi                      
         cdq                              
         and edx,0x3                      
         add eax,edx                      
         sar eax,0x2                      
         neg eax                           /-4
     
     除数不为2的幂时
         magicnumber<=0x7fffffff时:
         mov eax,0x6DB6DB6D               |
         imul edi                         |
         sub edx,edi                      |
         sar edx,0x2                      |
         mov eax,edx                      |>>> 2**34/(2**32-0x6db6db6d)=6.999999997962732     -7
         shr eax,0x1F                     |
         add eax,edx
     
         magicnumber>0x7fffffff时:
         mov eax,0x99999999               |
         imul edi                         |
         sar edx,0x1                      |
         mov eax,edx                      |>>> 2**33/(2**32-0x99999999)=4.99999999825377      -5
         shr eax,0x1F                     |
         add eax,edx 
 
 
 模运算
     模数为2的幂时                      
         mov eax,edi                      |%4
         and eax,0x80000003               |对2的N次方数取余使用and操作,x%2^N 使用位运算x & (2^N - 1)代替
         jns operation.1334C26            |
         dec eax                          |减一
         or eax,0xFFFFFFFC                |相当于取反
         inc eax                          |加一           
     
     模数不为2的幂时
         mov eax,0x55555556               |%3
         mov ecx,edi                      |
         imul edi                         |
         mov eax,edx                      |>>> 2**32/0x55555556=2.999999998603016
         shr eax,0x1F                     |
         add eax,edx                      |
         lea eax,dword ptr ds:[eax+eax*2] |
         sub ecx,eax                      |
         push ecx    
    模数为负时实现相同

除数为正数时,使用公式o=2^n/c,将MagicNumber作为c值代入公式求解常量除数o,即可恢复除法原型

特殊情况:

 

 除数为负数时:统计右移的总次数以确定公式中的n值,然后使用公式|o|=(2^n) / (2^32 -c)。,将MagicNumber作为c值代入公式求解常量除数lol,即可恢复除法原型。

模运算:对两个变量取模或者对非2的幂取模,可直接使用div或idiv指令完成,余数在dx或者是edx中。

对2的k次方取余,余数的值只需取得被除数二进制数值中的最后k位的值即可,负数则还需在k位之前补1,

x % 2^N  使用 x & (2^N - 1)代替

 对于为什么要这样优化呢?这其中涉及到一些数学知识,有兴趣的可以继续深入研究下去。

其实能够总结出各种优化的特征,遇到时可以还原操作便达到了我们逆向分析的目的。

猜你喜欢

转载自www.cnblogs.com/DirWang/p/12150117.html