《C++反汇编与逆向分析技术揭秘》–算术运算和赋值

一、加法

1.Debug下:

14:     int nVarOne0 = 1 + 5 - 3 * 6;//编译时计算得到结果
00C0550E C7 45 F8 F4 FF FF FF mov         dword ptr [nVarOne0],0FFFFFFF4h  
    15:     cout << nVarOne0 << endl;
00C05515 68 9D 4A BF 00       push        offset std::endl<char,std::char_traits<char> > (0BF4A9Dh)  
00C0551A 8B 45 F8             mov         eax,dword ptr [nVarOne0]  
00C0551D 50                   push        eax  
00C0551E B9 F8 B1 D5 00       mov         ecx,offset std::cout (0D5B1F8h)  
00C05523 E8 9A C1 FE FF       call        std::basic_ostream<char,std::char_traits<char> >::operator<< (0BF16C2h)  
    15:     cout << nVarOne0 << endl;
00C05528 8B C8                mov         ecx,eax  
00C0552A E8 7C E7 FE FF       call        std::basic_ostream<char,std::char_traits<char> >::operator<< (0BF3CABh)  
    16:     int nVarTwo = 0;//变量赋值,立即数
00C0552F C7 45 EC 00 00 00 00 mov         dword ptr [nVarTwo],0  
    17:     int nVarOne = argc;//赋值 变量
00C05536 8B 45 08             mov         eax,dword ptr [argc]  
00C05539 89 45 E0             mov         dword ptr [nVarOne],eax  
    18:      //int nVarTwo = argc;
    19:  
    20:      nVarOne = nVarOne + 1;//变量+常数
00C0553C 8B 45 E0             mov         eax,dword ptr [nVarOne]  //取变量
00C0553F 83 C0 01             add         eax,1  //加 立即数
00C05542 89 45 E0             mov         dword ptr [nVarOne],eax  
    21:      nVarOne = 1 + 2;//编译时得到结果,立即数
00C05545 C7 45 E0 03 00 00 00 mov         dword ptr [nVarOne],3  
    22:      nVarOne = nVarOne + nVarTwo;//变量+变量
00C0554C 8B 45 E0             mov         eax,dword ptr [nVarOne]  
00C0554F 03 45 EC             add         eax,dword ptr [nVarTwo]  
00C05552 89 45 E0             mov         dword ptr [nVarOne],eax  
    23:  
    24:     printf("nVarOne = %d rn", nVarOne);
00C05555 8B 45 E0             mov         eax,dword ptr [nVarOne]  
00C05558 50                   push        eax  
00C05559 68 14 A3 D1 00       push        offset string "nVarOne = %d rn" (0D1A314h)  
00C0555E E8 55 C1 FE FF       call        _printf (0BF16B8h)  
00C05563 83 C4 08             add         esp,8

2.release

00854B07      | 6A F4          | push 0xFFFFFFF4                                                                | //直接计算出结果
00854B09      | B9 501A8E00    | mov ecx,<operation.std::cout>                                                  |
00854B0E      | E8 2DD4FFFF    | call <operation.std::basic_ostream<char,std::char_traits<char> >::operator<<>  |
00854B13      | 8BF8           | mov edi,eax                                                                    | edi:&"E:\Des\C++反汇编与逆向分析技术揭秘与随书源码\随书相关代码\第四章\Operation\Release\Operation.exe"
00854B15      | 8B0F           | mov ecx,dword ptr ds:[edi]                                                     | [edi]:"E:\Des\C++反汇编与逆向分析技术揭秘与随书源码\随书相关代码\第四章\Operation\Release\Operation.exe"
00854B17      | 8B49 04        | mov ecx,dword ptr ds:[ecx+0x4]                                                 |
00854B1A      | 8B4C39 30      | mov ecx,dword ptr ds:[ecx+edi+0x30]                                            | ecx+edi*1+30:"源码\随书相关代码\第四章\Operation\Release\Operation.exe"
00854B1E      | 8B71 04        | mov esi,dword ptr ds:[ecx+0x4]                                                 | esi:__argc
00854B21      | 8BCE           | mov ecx,esi                                                                    | esi:__argc
00854B23      | C745 FC 000000 | mov dword ptr ss:[ebp-0x4],0x0                                                 |//变量nVarTwo 赋值0
00854B2A      | 8975 F0        | mov dword ptr ss:[ebp-0x10],esi                                                | 
····················优化的内嵌函数····················00854B89      | 6A 03          | push 0x3                                                                       |//编译时进行了优化,直接得到变量nVarOne值为3
00854B8B      | 68 6C938C00    | push operation.8C936C                                                          | 8C936C:"nVarOne = %d rn"
00854B90      | E8 1B000000    | call <operation.printf>                                                        |

二、减法:

1.Debug

29:     // 变量定义
    30:     int nVarOne = argc;
00046A6E 8B 45 08             mov         eax,dword ptr [argc]  
00046A71 89 45 F8             mov         dword ptr [nVarOne],eax  
    31:     int nVarTwo = argc;
00046A74 8B 45 08             mov         eax,dword ptr [argc]  
00046A77 89 45 EC             mov         dword ptr [nVarTwo],eax  
    32:     scanf("%d", &nVarTwo);
00046A7A 8D 45 EC             lea         eax,[nVarTwo]  
00046A7D 50                   push        eax  
00046A7E 68 AC A7 15 00       push        offset string "%d" (015A7ACh)  
00046A83 E8 38 B3 FE FF       call        _scanf (031DC0h)  
00046A88 83 C4 08             add         esp,8  
    33:     // 变量减常量的减法运算
    34:     nVarOne = nVarOne - 100;
00046A8B 8B 45 F8             mov         eax,dword ptr [nVarOne]  
00046A8E 83 E8 64             sub         eax,64h  
00046A91 89 45 F8             mov         dword ptr [nVarOne],eax  
    35:     // 减法与加法混合运算
    36:     nVarOne = nVarOne + 5 - nVarTwo ;
00046A94 8B 45 F8             mov         eax,dword ptr [nVarOne]  
00046A97 83 C0 05             add         eax,5  
00046A9A 2B 45 EC             sub         eax,dword ptr [nVarTwo]  
00046A9D 89 45 F8             mov         dword ptr [nVarOne],eax  
    37:     printf("nVarOne = %d rn", nVarOne);
00046AA0 8B 45 F8             mov         eax,dword ptr [nVarOne]  
    37:     printf("nVarOne = %d rn", nVarOne);
00046AA3 50                   push        eax  
00046AA4 68 14 A3 15 00       push        offset string "nVarOne = %d rn" (015A314h)  
00046AA9 E8 0A AC FE FF       call        _printf (0316B8h)  
00046AAE 83 C4 08             add         esp,8  
    38:     
    39: }

2.release

00C94AE0 <operati | 55                    | push ebp                         | operation.cpp:137
00C94AE1          | 8BEC                  | mov ebp,esp                      |
00C94AE3          | 56                    | push esi                         | esi:__argc
00C94AE4          | 8B75 08               | mov esi,dword ptr ss:[ebp+0x8]   | //变量nVarOne, esi:__argc
00C94AE7          | 8D45 08               | lea eax,dword ptr ss:[ebp+0x8]   |
00C94AEA          | 50                    | push eax                         | eax:&"#envTSLOGSHELLEXT8692=95686944"
00C94AEB          | 68 7C93D000           | push operation.D0937C            | D0937C:"%d"
00C94AF0          | 8975 08               | mov dword ptr ss:[ebp+0x8],esi   | //ebp+8看作nVarTwo esi:__argc
00C94AF3          | E8 58000000           | call <operation.scanf>           | //输入将修改ebp+8,即nVarTwo
00C94AF8          | 2B75 08               | sub esi,dword ptr ss:[ebp+0x8]   | //nVarOne-nVarTwo esi:__argc
00C94AFB          | 83EE 5F               | sub esi,0x5F                     | //nVarOne-95 esi:__argc
00C94AFE          | 56                    | push esi                         | esi:__argc
00C94AFF          | 68 6C93D000           | push operation.D0936C            | D0936C:"nVarOne = %d rn"
00C94B04          | E8 17000000           | call <operation.printf>          |
00C94B09          | 83C4 10               | add esp,0x10                     |
00C94B0C          | 33C0                  | xor eax,eax                      | operation.cpp:148, eax:&"#envTSLOGSHELLEXT8692=95686944"
00C94B0E          | 5E                    | pop esi                          | esi:__argc
00C94B0F          | 5D                    | pop ebp                          | operation.cpp:149

三、乘法:

1.debug

43:     int nVarOne = argc;
00A8697E 8B 45 08             mov         eax,dword ptr [argc]  
00A86981 89 45 F8             mov         dword ptr [nVarOne],eax  
    44:     int nVarTwo = argc;
00A86984 8B 45 08             mov         eax,dword ptr [argc]  
00A86987 89 45 EC             mov         dword ptr [nVarTwo],eax  
    45:     // 乘法运算
    46:     printf("nVarOne * 15 = %dn", nVarOne * 15);//15 非2的倍数,debug下无优化
00A8698A 6B 45 F8 0F          imul        eax,dword ptr [nVarOne],0Fh  
00A8698E 50                   push        eax  
00A8698F 68 C0 A7 B9 00       push        offset string "nVarOne * 15 = %dn" (0B9A7C0h)  
00A86994 E8 1F AD FE FF       call        _printf (0A716B8h)  
00A86999 83 C4 08             add         esp,8  
    47:     printf("nVarOne * 16 = %dn", nVarOne * 16);//16=2**4
00A8699C 8B 45 F8             mov         eax,dword ptr [nVarOne]  
00A8699F C1 E0 04             shl         eax,4  //左移4位,相当于乘16
00A869A2 50                   push        eax  
00A869A3 68 D8 A7 B9 00       push        offset string "nVarOne * 16 = %dn" (0B9A7D8h)  
00A869A8 E8 0B AD FE FF       call        _printf (0A716B8h)  
00A869AD 83 C4 08             add         esp,8  
    48:     printf("2 * 2 = %dn", 2 * 2);
00A869B0 6A 04                push        4  //编译时直接得到结果
00A869B2 68 F0 A7 B9 00       push        offset string "2 * 2 = %dn" (0B9A7F0h)  
00A869B7 E8 FC AC FE FF       call        _printf (0A716B8h)  
00A869BC 83 C4 08             add         esp,8  
    49:     printf("nVarTwo * 4 + 5 = %dn", nVarTwo * 4 + 5);//乘数变量为2的倍数,利用lea指令进行 乘法和加法的混合运算
00A869BF 8B 45 EC             mov         eax,dword ptr [nVarTwo]  
00A869C2 8D 0C 85 05 00 00 00 lea         ecx,[eax*4+5]  
00A869C9 51                   push        ecx  
00A869CA 68 00 A8 B9 00       push        offset string "nVarTwo * 4 + 5 = %dn" (0B9A800h)  
00A869CF E8 E4 AC FE FF       call        _printf (0A716B8h)  
00A869D4 83 C4 08             add         esp,8  
    50:     printf("nVarTwo * 9 + 5 = %dn", nVarTwo * 9 + 5);//乘数变量不为2的倍数,debug下无优化
00A869D7 6B 45 EC 09          imul        eax,dword ptr [nVarTwo],9  
00A869DB 83 C0 05             add         eax,5  
00A869DE 50                   push        eax  
00A869DF 68 1C A8 B9 00       push        offset string "nVarTwo * 9 + 5 = %dn" (0B9A81Ch)  
00A869E4 E8 CF AC FE FF       call        _printf (0A716B8h)  
00A869E9 83 C4 08             add         esp,8  
    51:     printf("nVarOne * nVarTwo = %dn", nVarOne * nVarTwo);//变量之间相乘,无优化
00A869EC 8B 45 F8             mov         eax,dword ptr [nVarOne]  
00A869EF 0F AF 45 EC          imul        eax,dword ptr [nVarTwo]  
00A869F3 50                   push        eax  
00A869F4 68 38 A8 B9 00       push        offset string "nVarOne * nVarTwo = %dn" (0B9A838h)  
00A869F9 E8 BA AC FE FF       call        _printf (0A716B8h)  
00A869FE 83 C4 08             add         esp,8  
    52: }

2.release

00AF4AE4          | 8B75 08            | mov esi,dword ptr ss:[ebp+0x8]       | operation.cpp:142
00AF4AE7          | 8BC6               | mov eax,esi                          |
00AF4AE9          | C1E0 04            | shl eax,0x4                          |//nVarOne*15  分解为  nVarOne*16-nVarOne
00AF4AEC          | 2BC6               | sub eax,esi                          |
00AF4AEE          | 50                 | push eax                             |
00AF4AEF          | 68 8093B600        | push operation.B69380                | B69380:"nVarOne * 15 = %dn"
00AF4AF4          | E8 67000000        | call <operation.printf>              |
00AF4AF9          | 8BC6               | mov eax,esi                          |
00AF4AFB          | C1E0 04            | shl eax,0x4                          |//左移4位,即*16
00AF4AFE          | 50                 | push eax                             |
00AF4AFF          | 68 9493B600        | push operation.B69394                | B69394:"nVarOne * 16 = %dn"
00AF4B04          | E8 57000000        | call <operation.printf>              |
00AF4B09          | 6A 04              | push 0x4                             |
00AF4B0B          | 68 A893B600        | push operation.B693A8                | B693A8:"2 * 2 = %dn"
00AF4B10          | E8 4B000000        | call <operation.printf>              |
00AF4B15          | 8D04B5 05000000    | lea eax,dword ptr ds:[esi*4+0x5]     |与debug模式下处理相同
00AF4B1C          | 50                 | push eax                             |
00AF4B1D          | 68 B493B600        | push operation.B693B4                | B693B4:"nVarTwo * 4 + 5 = %dn"
00AF4B22          | E8 39000000        | call <operation.printf>              |
00AF4B27          | 8D04F5 05000000    | lea eax,dword ptr ds:[esi*8+0x5]     |//nVarTwo*9+5 分解为 nVarTwo*8+5+nVarTwo
00AF4B2E          | 03C6               | add eax,esi                          |//
00AF4B30          | 50                 | push eax                             |
00AF4B31          | 68 CC93B600        | push operation.B693CC                | B693CC:"nVarTwo * 9 + 5 = %dn"
00AF4B36          | E8 25000000        | call <operation.printf>              |
00AF4B3B          | 0FAFF6             | imul esi,esi                         |//变量之间乘法无优化
00AF4B3E          | 56                 | push esi                             |
00AF4B3F          | 68 E493B600        | push operation.B693E4                | B693E4:"nVarOne * nVarTwo = %dn"
00AF4B44          | E8 17000000        | call <operation.printf>              |
00AF4B49          | 83C4 30            | add esp,0x30                         |

四、除法

1.debug

56:     int nVarOne = argc;
0032680E 8B 45 08             mov         eax,dword ptr [argc]  
00326811 89 45 F8             mov         dword ptr [nVarOne],eax  
    57:     int nVarTwo = argc;
00326814 8B 45 08             mov         eax,dword ptr [argc]  
00326817 89 45 EC             mov         dword ptr [nVarTwo],eax  
    58:     // 除法运算
    59:     printf("nVarOne / nVarTwo = %dn", nVarOne / nVarTwo);//两个变量之间除法,无优化
0032681A 8B 45 F8             mov         eax,dword ptr [nVarOne]  
0032681D 99                   cdq  
0032681E F7 7D EC             idiv        eax,dword ptr [nVarTwo]  //直接使用 idiv 有符号数除法指令,商保存到eax,余数保存到edx
00326821 50                   push        eax  
00326822 68 54 A8 43 00       push        offset string "nVarOne / nVarTwo = %dn" (043A854h)  
00326827 E8 8C AE FE FF       call        _printf (03116B8h)  
0032682C 83 C4 08             add         esp,8  
    60:     printf("nVarOne / 2 = %dn", nVarOne / 2);//被除数为2的倍数时,使用算术移位来优化
0032682F 8B 45 F8             mov         eax,dword ptr [nVarOne]  
00326832 99                   cdq  //eax高位拓展到edx,即用变量eax的符号位来占满edx每一位
00326833 2B C2                sub         eax,edx  //正数无变化,负数则加1(c中有符号数除法为向零取正,正数相当于向下取整,负数相当于向上取整)
00326835 D1 F8                sar         eax,1  //算术右移1位,相当于除2,(sar,高位用符号位补充)
00326837 50                   push        eax  
00326838 68 70 A8 43 00       push        offset string "nVarOne / 2 = %dn" (043A870h)  
0032683D E8 76 AE FE FF       call        _printf (03116B8h)  
00326842 83 C4 08             add         esp,8  
    61:     printf("nVarTwo / 7 = %dn", nVarTwo / 7);//被除数不为2的倍数时,无优化
00326845 8B 45 EC             mov         eax,dword ptr [nVarTwo]  
00326848 99                   cdq  
00326849 B9 07 00 00 00       mov         ecx,7  
0032684E F7 F9                idiv        eax,ecx  
00326850 50                   push        eax  
00326851 68 84 A8 43 00       push        offset string "nVarTwo / 7 = %dn" (043A884h)  
00326856 E8 5D AE FE FF       call        _printf (03116B8h)  
0032685B 83 C4 08             add         esp,8  
    62:     printf("nVarTwo % 7 = %dn", nVarTwo % 7);//模运算,模数不为2的倍数时无优化
0032685E 8B 45 EC             mov         eax,dword ptr [nVarTwo]  
00326861 99                   cdq  
00326862 B9 07 00 00 00       mov         ecx,7  
00326867 F7 F9                idiv        eax,ecx  
00326869 52                   push        edx  
0032686A 68 98 A8 43 00       push        offset string "nVarTwo % 7 = %dn" (043A898h)  
0032686F E8 44 AE FE FF       call        _printf (03116B8h)  
00326874 83 C4 08             add         esp,8  
    63:     printf("nVarOne / 8 = %dn", nVarOne / 8);
00326877 8B 45 F8             mov         eax,dword ptr [nVarOne]  
0032687A 99                   cdq  
0032687B 83 E2 07             and         edx,7  //nVarOne为正数则dex为0,负数则edx为7
    63:     printf("nVarOne / 8 = %dn", nVarOne / 8);
0032687E 03 C2                add         eax,edx  //负数除法时,相当于计算ceil(nVarOne/8)=》floor( (nVarOne+8-1)/8 )=》floor((nVarOne+7)/8);正数时,nVarOne/8
00326880 C1 F8 03             sar         eax,3  
00326883 50                   push        eax  
00326884 68 AC A8 43 00       push        offset string "nVarOne / 8 = %dn" (043A8ACh)  
00326889 E8 2A AE FE FF       call        _printf (03116B8h)  
0032688E 83 C4 08             add         esp,8  
    64:     printf("nVarOne / 14 = %dn", argc / 14);
00326891 8B 45 08             mov         eax,dword ptr [argc]  
00326894 99                   cdq  
00326895 B9 0E 00 00 00       mov         ecx,0Eh  
0032689A F7 F9                idiv        eax,ecx  
0032689C 50                   push        eax  
0032689D 68 C0 A8 43 00       push        offset string "nVarOne / 14 = %dn" (043A8C0h)  
003268A2 E8 11 AE FE FF       call        _printf (03116B8h)  
003268A7 83 C4 08             add         esp,8

计算nVarOne/2时:

0032682F 8B 45 F8             mov         eax,dword ptr [nVarOne]  
00326832 99                   cdq  //eax高位拓展到edx,即用变量eax的符号位来占满edx每一位
00326833 2B C2                sub         eax,edx  //正数无变化,负数则加1(c中有符号数除法为向零取正,正数相当于向下取整,负数相当于向上取整)
00326835 D1 F8                sar         eax,1

计算nVarOne/8时:

00326877 8B 45 F8             mov         eax,dword ptr [nVarOne]  
0032687A 99                   cdq  
0032687B 83 E2 07             and         edx,7  //nVarOne为正数则dex为0,负数则edx为7
0032687E 03 C2                add         eax,edx  //负数除法时,相当于计算ceil(nVarOne/8)=》floor( (nVarOne+8-1)/8 )=》floor((nVarOne+7)/8);正数时,nVarOne/8
00326880 C1 F8 03             sar         eax,3

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

2.release

00224AE5          | 6A 01              | push 0x1                             | //赋值相同的变量,编译时得到结果
00224AE7          | 68 FC932900        | push operation.2993FC                | 2993FC:"nVarOne / nVarTwo = %dn"
00224AEC          | E8 8F000000        | call <operation.printf>              |
00224AF1          | 8B7D 08            | mov edi,dword ptr ss:[ebp+0x8]       |
00224AF4          | 8BC7               | mov eax,edi                          |
00224AF6          | 99                 | cdq                                  |//将eax最高位拓展到edx每一位
00224AF7          | 2BC2               | sub eax,edx                          |正数eax不变,负数时eax+1
00224AF9          | D1F8               | sar eax,0x1                          |右移1位,即/2
00224AFB          | 50                 | push eax                             |
00224AFC          | 68 14942900        | push operation.299414                | 299414:"nVarOne / 2 = %dn"
00224B01          | E8 7A000000        | call <operation.printf>              |
00224B06          | B8 93244992        | mov eax,0x92492493                   |//除法优化,改除为乘
00224B0B          | F7EF               | imul edi                             |
00224B0D          | 03D7               | add edx,edi                          |
00224B0F          | C1FA 02            | sar edx,0x2                          |
00224B12          | 8BF2               | mov esi,edx                          | esi:__argc
00224B14          | C1EE 1F            | shr esi,0x1F                         | esi:__argc
00224B17          | 03F2               | add esi,edx                          | esi:__argc
00224B19          | 56                 | push esi                             | esi:__argc
00224B1A          | 68 28942900        | push operation.299428                | 299428:"nVarTwo / 7 = %dn"
00224B1F          | E8 5C000000        | call <operation.printf>              |
00224B24          | 8D0CF5 00000000    | lea ecx,dword ptr ds:[esi*8]         | //设被除数为a,除数为b,商为q,余数为r,则 r=a-b*q   ecx=(nVarTwo/7)*8
00224B2B          | 8BC7               | mov eax,edi                          |
00224B2D          | 2BCE               | sub ecx,esi                          | //结合lea ecx,dword ptr ds:[esi*8],相当于ecx=(nVarTwo/7)*7 00224B2F          | 2BC1               | sub eax,ecx                          | eax为被除数,减去ecx,得到余数
00224B31          | 50                 | push eax                             |
00224B32          | 68 3C942900        | push operation.29943C                | 29943C:"nVarTwo % 7 = %dn"
00224B37          | E8 44000000        | call <operation.printf>              |
00224B3C          | 8BC7               | mov eax,edi                          |
00224B3E          | 99                 | cdq                                  |
00224B3F          | 83E2 07            | and edx,0x7                          |负数情况下,下面要加2^n -1 =7
00224B42          | 03C2               | add eax,edx                          |
00224B44          | C1F8 03            | sar eax,0x3                          |
00224B47          | 50                 | push eax                             |
00224B48          | 68 50942900        | push operation.299450                | 299450:"nVarOne / 8 = %dn"
00224B4D          | E8 2E000000        | call <operation.printf>              |
00224B52          | B8 93244992        | mov eax,0x92492493                   |
00224B57          | F7EF               | imul edi                             |
00224B59          | 03D7               | add edx,edi                          |
00224B5B          | C1FA 03            | sar edx,0x3                          |
00224B5E          | 8BC2               | mov eax,edx                          |
00224B60          | C1E8 1F            | shr eax,0x1F                         |
00224B63          | 03C2               | add eax,edx                          |
00224B65          | 50                 | push eax                             |
00224B66          | 68 64942900        | push operation.299464                | 299464:"nVarOne / 14 = %dn"
00224B6B          | E8 10000000        | call <operation.printf>              |
00224B70          | 83C4 30            | add esp,0x30                         |

除法优化中,改除为乘的细节较多,日后再写,Orz,,

《C++反汇编与逆向分析技术揭秘》--算术运算和赋值
原文链接: https://www.cnblogs.com/DirWang/p/12133187.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/191304

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午5:41
下一篇 2023年2月12日 下午5:41

相关推荐