Author: Wilson
10多年的C/C++工作经历,常常设计ARM下编程,粗懂ARM汇编, 经常穷尽所能提高运行效率,减小代码尺寸。而在WIN32下,除了关注算法优化、数据结构设计等优化外,而是假定了ARM下的优化技术,而并没有认真去核实,现先小探for loop.
VS2005 sp1
从简单入手,看看
int g_a = 0;
for( int i=0; i<100; i++)
{
g_a++;
}
release 下,Maximize Speed (/O2)
汇编展开:
for( int i=0; i<100; i++)
004012A1 mov eax,dword ptr [g_a (40512Ch)]
004012A6 add eax,64h
{
g_a++;
}
哈哈,编译器也太聪明了,知道我是循环100此,直接加100(64h)了,for 被优化掉了。
改复杂一点,再看:
for(int i=0; i<100; i++)
{
g_b += Funct3();
004012B0 call edi
004012B2 and eax,400h
004012B7 add dword ptr [g_b (405130h)],eax
004012BD sub esi,1
004012C0 mov dword ptr [g_k (4054ACh)],eax
004012C5 jne CTestSomeCCPP_AboutDlg::OnInitDialog+0D0h (4012B0h)
}
发现sub esi 1, 第一次运行 esi=100,以后递减,哦,你也想到了,没错,就是ARM常用的i-- loop:
for(int i=100; i--; )
{....
}
看来这种写法性能上高,编译器就直接这样优化了。
但是这种写法有个问题,i不能小于等于1,否,等死吧,你明白的,不过for的常量初始值,编译器肯定会检查这个条件,我们看看是否如此:
fror(iint i=0; i--;)//直接被优化掉了,
{...}
改
for(int i=-10; i--; )//i=-10, 编译器当然不知道你要做什么了,
004012A1 mov edi,dword ptr [__imp__GetTickCount@0 (403038h)]
004012A7 mov esi,0FFFFFFF6h
004012AC lea esp,[esp]
004012B0 sub esi,1
{
g_b += Funct3();
004012B3 call edi
004012B5 and eax,400h
004012BA add dword ptr [g_b (405130h)],eax
004012C0 test esi,esi
004012C2 mov dword ptr [g_k (4054ACh)],eax
004012C7 jne CTestSomeCCPP_AboutDlg::OnInitDialog+0D0h (4012B0h)
}
然后,无限循环,等死了。
既然常变量for都被优化成i--了,我们看看变量作为循环条件的
for(int i=0; i<g_a; i++)
004012A1 xor esi,esi
004012A3 cmp dword ptr [g_a (40512Ch)],esi
004012A9 jle CTestSomeCCPP_AboutDlg::OnInitDialog+0EEh (4012CEh)
004012AB mov edi,dword ptr [__imp__GetTickCount@0 (403038h)]
{
g_b += Funct3();
004012B1 call edi
004012B3 and eax,400h
004012B8 add dword ptr [g_b (405130h)],eax
004012BE add esi,1
004012C1 cmp esi,dword ptr [g_a (40512Ch)]
004012C7 mov dword ptr [g_k (4054ACh)],eax
004012CC jl CTestSomeCCPP_AboutDlg::OnInitDialog+0D1h (4012B1h)
}
第一行 xor esi,esi, 查一下,有人说清零的话,xor 比mov效率高,
用i=10测试一下,就变成mov 了,我只能说编译器实在是太强了。
这会是默认的i++循环了
其中Funct3{
g_k = GetTickCount()&1024;
return g_k;
}
看看i--怎么样
for(int i=g_a; i--; )
004012A1 mov esi,dword ptr [g_a (40512Ch)]
004012A7 test esi,esi
004012A9 je CTestSomeCCPP_AboutDlg::OnInitDialog+0EAh (4012CAh)
004012AB mov edi,dword ptr [__imp__GetTickCount@0 (403038h)]
004012B1 sub esi,1
{
g_b += Funct3();
004012B4 call edi
004012B6 and eax,400h
004012BB add dword ptr [g_b (405130h)],eax
004012C1 test esi,esi
004012C3 mov dword ptr [g_k (4054ACh)],eax
004012C8 jne CTestSomeCCPP_AboutDlg::OnInitDialog+0D1h (4012B1h)
}
发现汇编代码差不太多,但是i--循环下,循环体少一行汇编语句,这个很重要,减少时间哦
因为不是很了解各汇编的执行效率,不能相对准确地估算运行时间,
但是,我们基本可以得出结论,能用i--方式的循环,还是用i--方式,但是,
不要写成假死状态的循环哦!