一、加法
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 ", 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 " (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 " 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 ", nVarOne); 00046AA0 8B 45 F8 mov eax,dword ptr [nVarOne] 37: printf("nVarOne = %d ", nVarOne); 00046AA3 50 push eax 00046AA4 68 14 A3 15 00 push offset string "nVarOne = %d " (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 " 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 = %d ", 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 = %d " (0B9A7C0h) 00A86994 E8 1F AD FE FF call _printf (0A716B8h) 00A86999 83 C4 08 add esp,8 47: printf("nVarOne * 16 = %d ", 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 = %d " (0B9A7D8h) 00A869A8 E8 0B AD FE FF call _printf (0A716B8h) 00A869AD 83 C4 08 add esp,8 48: printf("2 * 2 = %d ", 2 * 2); 00A869B0 6A 04 push 4 //编译时直接得到结果 00A869B2 68 F0 A7 B9 00 push offset string "2 * 2 = %d " (0B9A7F0h) 00A869B7 E8 FC AC FE FF call _printf (0A716B8h) 00A869BC 83 C4 08 add esp,8 49: printf("nVarTwo * 4 + 5 = %d ", 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 = %d " (0B9A800h) 00A869CF E8 E4 AC FE FF call _printf (0A716B8h) 00A869D4 83 C4 08 add esp,8 50: printf("nVarTwo * 9 + 5 = %d ", 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 = %d " (0B9A81Ch) 00A869E4 E8 CF AC FE FF call _printf (0A716B8h) 00A869E9 83 C4 08 add esp,8 51: printf("nVarOne * nVarTwo = %d ", 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 = %d " (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 = %d " 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 = %d " 00AF4B04 | E8 57000000 | call <operation.printf> | 00AF4B09 | 6A 04 | push 0x4 | 00AF4B0B | 68 A893B600 | push operation.B693A8 | B693A8:"2 * 2 = %d " 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 = %d " 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 = %d " 00AF4B36 | E8 25000000 | call <operation.printf> | 00AF4B3B | 0FAFF6 | imul esi,esi |//变量之间乘法无优化 00AF4B3E | 56 | push esi | 00AF4B3F | 68 E493B600 | push operation.B693E4 | B693E4:"nVarOne * nVarTwo = %d " 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 = %d ", 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 = %d " (043A854h) 00326827 E8 8C AE FE FF call _printf (03116B8h) 0032682C 83 C4 08 add esp,8 60: printf("nVarOne / 2 = %d ", 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 = %d " (043A870h) 0032683D E8 76 AE FE FF call _printf (03116B8h) 00326842 83 C4 08 add esp,8 61: printf("nVarTwo / 7 = %d ", 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 = %d " (043A884h) 00326856 E8 5D AE FE FF call _printf (03116B8h) 0032685B 83 C4 08 add esp,8 62: printf("nVarTwo % 7 = %d ", 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 = %d " (043A898h) 0032686F E8 44 AE FE FF call _printf (03116B8h) 00326874 83 C4 08 add esp,8 63: printf("nVarOne / 8 = %d ", 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 = %d ", 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 = %d " (043A8ACh) 00326889 E8 2A AE FE FF call _printf (03116B8h) 0032688E 83 C4 08 add esp,8 64: printf("nVarOne / 14 = %d ", 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 = %d " (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
2.release
00224AE5 | 6A 01 | push 0x1 | //赋值相同的变量,编译时得到结果 00224AE7 | 68 FC932900 | push operation.2993FC | 2993FC:"nVarOne / nVarTwo = %d " 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 = %d " 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 = %d " 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 = %d " 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 = %d " 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 = %d " 00224B6B | E8 10000000 | call <operation.printf> | 00224B70 | 83C4 30 | add esp,0x30 |
除法优化中,改除为乘的细节较多,日后再写,Orz,,