标签:
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 |
标签:
原文地址:http://www.cnblogs.com/nitianbenbendan/p/4409610.html