你的位置:首页 > ASP.net教程

[ASP.net教程]C++反汇编学习笔记(六)各种算术运算的工作形式(1)


1、  加法

  加法的几种情况:

    ①    常量+常量

    ②    变量+常量

    ③    变量+变量

Debug

Release

#include <iostream>

using namespace std;

int main()

{

...........//保存现场和初始化略

         int a=0, b=0;

008544FE  mov         dword ptr [a],0 

00854505  mov         dword ptr [b],0 

//常量+常量

         a = 1 + 1;

//在保持与源码对应的情况下,也进行了常量折叠的优化

0085450C  mov         dword ptr [a],2 

//变量+常量

         a = a + 1;

00854513  mov         eax,dword ptr [a] 

00854516  add         eax,1 

00854519  mov         dword ptr [a],eax 

//变量+变量

         a = a + b;

0085451C  mov         eax,dword ptr [a] 

0085451F  add         eax,dword ptr [b] 

00854522  mov         dword ptr [a],eax 

         cout << a << b << endl;

......//输出略

         system("pause");

......//略

         return 0;

00854580  xor         eax,eax 

}

.......//堆栈平衡略

00854595  ret 

 

int a=0, b=0;

         a = 1 + 1;

         a = a + 1;

         a = a + b;

//编译阶段进行了常量折叠,常量传播,复写传播的优化,变量a和b都没有存在的必要,最后只生成了输出3和0指令

         cout << a << b << endl;

012112A0  mov         ecx,dword ptr ds:[1213040h] 

012112A6  push        1211720h 

012112AB  push        0 

012112AD  push        3 

012112AF  call        dword ptr ds:[1213024h] 

012112B5  mov         ecx,eax 

012112B7  call        dword ptr ds:[1213024h] 

012112BD  mov         ecx,eax 

012112BF  call        dword ptr ds:[1213048h] 

 

         system("pause");

012112C5  push        12131ACh 

012112CA  call        dword ptr ds:[12130CCh] 

012112D0  add         esp,4 

         return 0;

012112D3  xor         eax,eax 

}

012112D5  ret 

 

2、  减法

  计算机只会做加法。减法操作,都是通过补码转换将减法转变为加法。Debug为了调试方便和源码的对应,并不进行转换。Release下就会进行减法到加法的转变,然后其优化策略与加法一致。

3、  乘法

  由于乘法指令的周期较长,在编译过程中,编译器会先尝试将乘法转换称加法,或使用移位等周期较短的指令。当他们都不可转换时,才使用乘法指令。

  乘法的几种情况:

    ①    变量*常量(常量值为非2的幂)

    ②    变量*常量(常量值为2的幂)

    ③    常量*常量

    ④    变量*常量(2、4、8)+常量(组合运算)

    ⑤    变量*常量(非2、4、8,但是2的幂)+常量(组合运算)

    ⑥    变量*常量(非2的幂)+常量(组合运算)

    ⑦    变量*变量

C++原码

Debug

Release

#include <iostream>

using namespace std;

int main()

{

         int a, b;

         cin >> a >> b;

         //变量*常量(常量值为非2的幂)

         cout << a * 15;

         //变量*常量(常量值为2的幂)

         cout << a * 16;

         //常量*常量

         cout << 2 * 2;

         //变量*常量(2、4、8)+常量(组合运算)

         cout << a *4 + 5;

         //变量*常量(非2、4、8,但是2的幂)+常量(组合运算)

         cout << a * 16 + 5;

         //变量*常量(非2的幂)+常量(组合运算)

         cout << a * 12 + 5;

         //变量*变量

         cout << a*b;

 

         system("pause");

         return 0;

}

int main()

{

..........//略

         int a, b;

         cin >> a >> b;

001F5E88  mov         esi,esp 

001F5E8A  lea         eax,[b] 

001F5E8D  push        eax 

001F5E8E  mov         edi,esp 

001F5E90  lea         ecx,[a] 

001F5E93  push        ecx 

001F5E94  mov         ecx,dword ptr ds:[2010A4h] 

001F5E9A  call        dword ptr ds:[201100h] 

001F5EA0  cmp         edi,esp 

001F5EA2  call        __RTC_CheckEsp (01F1339h) 

001F5EA7  mov         ecx,eax 

001F5EA9  call        dword ptr ds:[201100h] 

001F5EAF  cmp         esi,esp 

001F5EB1  call        __RTC_CheckEsp (01F1339h) 

         //变量*常量(常量值为非2的幂)

         cout << a * 15;

001F5EB6  imul        eax,dword ptr [a],0Fh 

001F5EBA  mov         esi,esp 

001F5EBC  push        eax 

001F5EBD  mov         ecx,dword ptr ds:[2010A8h] 

001F5EC3  call        dword ptr ds:[201094h] 

001F5EC9  cmp         esi,esp 

001F5ECB  call        __RTC_CheckEsp (01F1339h) 

         //变量*常量(常量值为2的幂)

         cout << a * 16;

001F5ED0  mov         eax,dword ptr [a] 

001F5ED3  shl         eax,4 

001F5ED6  mov         esi,esp 

001F5ED8  push        eax 

001F5ED9  mov         ecx,dword ptr ds:[2010A8h] 

001F5EDF  call        dword ptr ds:[201094h] 

001F5EE5  cmp         esi,esp 

001F5EE7  call        __RTC_CheckEsp (01F1339h) 

         //常量*常量

         cout << 2 * 2;

001F5EEC  mov         esi,esp 

001F5EEE  push        4 

001F5EF0  mov         ecx,dword ptr ds:[2010A8h] 

001F5EF6  call        dword ptr ds:[201094h] 

001F5EFC  cmp         esi,esp 

001F5EFE  call        __RTC_CheckEsp (01F1339h) 

         //变量*常量(2、4、8)+常量(组合运算)

         cout << a *4 + 5;

001F5F03  mov         eax,dword ptr [a] 

001F5F06  lea         ecx,[eax*4+5] 

001F5F0D  mov         esi,esp 

001F5F0F  push        ecx 

001F5F10  mov         ecx,dword ptr ds:[2010A8h] 

001F5F16  call        dword ptr ds:[201094h] 

001F5F1C  cmp         esi,esp 

001F5F1E  call        __RTC_CheckEsp (01F1339h) 

         //变量*常量(非2、4、8,但是2的幂)+常量(组合运算)

         cout << a * 16 + 5;

001F5F23  mov         eax,dword ptr [a] 

001F5F26  shl         eax,4 

001F5F29  add         eax,5 

001F5F2C  mov         esi,esp 

001F5F2E  push        eax 

001F5F2F  mov         ecx,dword ptr ds:[2010A8h] 

001F5F35  call        dword ptr ds:[201094h] 

001F5F3B  cmp         esi,esp 

001F5F3D  call        __RTC_CheckEsp (01F1339h) 

         //变量*常量(非2的幂)+常量(组合运算)

         cout << a * 12 + 5;

001F5F42  imul        eax,dword ptr [a],0Ch 

         //变量*常量(非2的幂)+常量(组合运算)

         cout << a * 12 + 5;

001F5F46  add         eax,5 

001F5F49  mov         esi,esp 

001F5F4B  push        eax 

001F5F4C  mov         ecx,dword ptr ds:[2010A8h] 

001F5F52  call        dword ptr ds:[201094h] 

001F5F58  cmp         esi,esp 

001F5F5A  call        __RTC_CheckEsp (01F1339h) 

         //变量*变量

         cout << a*b;

001F5F5F  mov         eax,dword ptr [a] 

001F5F62  imul        eax,dword ptr [b] 

001F5F66  mov         esi,esp 

001F5F68  push        eax 

001F5F69  mov         ecx,dword ptr ds:[2010A8h] 

001F5F6F  call        dword ptr ds:[201094h] 

001F5F75  cmp         esi,esp 

001F5F77  call        __RTC_CheckEsp (01F1339h) 

 

         system("pause");

...............//略

         return 0;

001F5F93  xor         eax,eax 

}

#include <iostream>

using namespace std;

int main()

{

.................//略

         int a, b;

         cin >> a >> b;

009712B0  mov         ecx,dword ptr ds:[973038h] 

         int a, b;

         cin >> a >> b;

009712B6  lea         eax,[b] 

009712B9  push        eax 

009712BA  lea         eax,[a] 

009712BD  push        eax 

009712BE  call        dword ptr ds:[973028h] 

009712C4  mov         ecx,eax 

009712C6  call        dword ptr ds:[973028h] 

         //变量*常量(常量值为非2的幂)

         cout << a * 15;

//这里将a*15转变为a*16-a,因为16=2的4次方,可以进行移位操作

009712CC  mov         ecx,dword ptr [a] 

009712CF  shl         ecx,4  //a*16

009712D2  sub         ecx,dword ptr [a]  //a*16的值减去a

009712D5  push        ecx 

009712D6  mov         ecx,dword ptr ds:[97303Ch] 

009712DC  call        dword ptr ds:[973024h] 

         //变量*常量(常量值为2的幂)

         cout << a * 16;

//16=2的4次方,所以直接进行移位操作

009712E2  mov         eax,dword ptr [a] 

009712E5  mov         ecx,dword ptr ds:[97303Ch] 

009712EB  shl         eax,4 

009712EE  push        eax 

009712EF  call        dword ptr ds:[973024h] 

         //常量*常量

         cout << 2 * 2;

//编译期间计算出2*2的结果,将表达式转换为常量值

009712F5  mov         ecx,dword ptr ds:[97303Ch] 

009712FB  push        4  

009712FD  call        dword ptr ds:[973024h] 

         //变量*常量(2、4、8)+常量(组合运算)

         cout << a * 4 + 5;

//常量乘数为2、4或8时,会直接利用lea指令进行混合运算

00971303  mov         eax,dword ptr [a] 

00971306  mov         ecx,dword ptr ds:[97303Ch] 

0097130C  lea         eax,[eax*4+5] 

00971313  push        eax 

00971314  call        dword ptr ds:[973024h] 

         //变量*常量(非2、4、8,但是2的幂)+常量(组合运算)

         cout << a * 16 + 5;

//常量乘数非2、4、8,但是2的幂,则先进行移位完成乘法运算,//再进行加法运算

00F6131A  mov         eax,dword ptr [a] 

00F6131D  mov         ecx,dword ptr ds:[0F6303Ch] 

00F61323  shl         eax,4  //a*16

00F61326  add         eax,5  //a*16的值加5

00F61329  push        eax 

00F6132A  call        dword ptr ds:[0F63024h] 

         //变量*常量(非2的幂)+常量(组合运算)

         cout << a * 12 + 5;

//这种情况,编译器先对表达式进行分解,使其分解后的表达式能够使用以上的优化方案,然后再进行运算。

//这里将a*12转变为a+a*2,使用lea指令得到3a,再使用lea指令进//行3a*4+5的运算。就是将12分解成符合变量*常量(2、4、8)的//情况

//再例如:a*30+5,则分解成a*16-a,然后将得到的结果乘以2+5

//     mov ecx,dword ptr[a]

//     shl ecx,4     //ecx=a*16

//     sub ecx,dword ptr[a]  //ecx=ecx-a=15*a

//     lea eax,[ecx*2+5]    //eax=ecx*2+5(15a*2+5)

00F61330  mov         eax,dword ptr [a] 

00F61333  mov         ecx,dword ptr ds:[0F6303Ch] 

00F61339  lea         eax,[eax+eax*2] 

00F6133C  lea         eax,[eax*4+5] 

00F61343  push        eax                         

00F61344  call        dword ptr ds:[0F63024h]        

//变量*变量

         cout << a*b;

//变量a和b的值不确定,没法进行优化,所以只能使用imul乘法指令

0097131A  mov         eax,dword ptr [b] 

0097131D  imul        eax,dword ptr [a] 

00971321  mov         ecx,dword ptr ds:[97303Ch] 

         //变量*变量

         cout << a*b;

00971327  push        eax 

00971328  call        dword ptr ds:[973024h] 

 

         system("pause");

0097132E  push        97319Ch 

00971333  call        dword ptr ds:[9730C4h] 

         return 0;

}

................//堆栈平衡略

0097134B  ret