* 循环的效率分析, 用 goto + if 模拟 循环(for, do-while, while)如果模拟费劲(if + goto 的次数统计多),说明效率低.
备注: for循环的++或--是在循环体的上面, 是低地址. 不能在循环体内更改循环条件.
思路
先用C语言将循环写出来,将汇编代码复制出来备用,将CMP换成if, 将JMP换成goto, 将 JMP的地址换成标号.
这样就可以直接直接将汇编代码按照汇编代码的含义用C代码重写. 就完成了用if + goto 模拟循环的任务
源码
/// @file 2015_1026\exam_1_3\main.c
/// @brief
/**
* 循环的效率分析, 用 goto + if 模拟 循环(for, do-while, while)如果模拟费劲(if + goto 的次数统计多),说明效率低.
备注: for循环的++或--是在循环体的上面, 是低地址. 不能在循环体内更改循环条件.
*/
#include <stdlib.h>
#include <stdio.h>
void testLoop(); ///< test real loop(for, do-while, while)
void MyLoop_for(); ///< use gogo + if make our loop(for)
void MyLoop_do_while(); ///< use gogo + if make our loop(do-while)
void MyLoop_while(); ///< use gogo + if make our loop(while)
int main(int argc, char** argv)
{
// testLoop();
MyLoop_for();
MyLoop_do_while();
MyLoop_while();
getchar();
return 0;
}
void testLoop()
{
int iIndex = 0;
const int iCntMax = 3;
printf("===for===\n");
for (iIndex = 0; iIndex < iCntMax; iIndex++)
{
printf("iIndex = %d\n", iIndex);
}
printf("===do-while===\n");
iIndex = 0;
do
{
printf("iIndex = %d\n", iIndex);
} while (iIndex++ < iCntMax);
printf("===while===\n");
iIndex = 0;
while (iIndex++ < iCntMax)
{
printf("iIndex = %d\n", iIndex);
}
}
void MyLoop_for()
{
/**
29: for (iIndex = 0; iIndex < iCntMax; iIndex++)
00401103 mov dword ptr [ebp-4],0
0040110A jmp testLoop+45h (00401115)
0040110C mov eax,dword ptr [ebp-4]
0040110F add eax,1
00401112 mov dword ptr [ebp-4],eax
00401115 mov ecx,dword ptr [ebp-4]
00401118 cmp ecx,dword ptr [ebp-8]
0040111B jge testLoop+60h (00401130)
30: {
31: printf("iIndex = %d\n", iIndex);
0040111D mov edx,dword ptr [ebp-4]
00401120 push edx
00401121 push offset string "iIndex = %d\n" (00423040)
00401126 call printf (00401590)
0040112B add esp,8
32: }
0040112E jmp testLoop+3Ch (0040110c)
*/
/// 模拟 for 循环
/// 参考for循环的汇编代码
int iIndex = 0;
const int iCntMax = 3;
printf("===sim for===\n");
iIndex = 0;
goto label_for_compare;
label_for_next:
iIndex++;
label_for_compare:
if (iIndex > (iCntMax - 1))
goto label_for_end;
printf("iIndex = %d\n", iIndex);
goto label_for_next;
label_for_end:
;
}
void MyLoop_do_while()
{
/**
37: iIndex = 0;
00401103 mov dword ptr [ebp-4],0
38: do
39: {
40: printf("iIndex = %d\n", iIndex);
0040110A mov eax,dword ptr [ebp-4]
0040110D push eax
0040110E push offset string "iIndex = %d\n" (0042302c)
00401113 call printf (004015c0)
00401118 add esp,8
41: } while (iIndex++ < iCntMax);
0040111B mov ecx,dword ptr [ebp-4]
0040111E mov edx,dword ptr [ebp-8]
00401121 mov eax,dword ptr [ebp-4]
00401124 add eax,1
00401127 mov dword ptr [ebp-4],eax
0040112A cmp ecx,edx
0040112C jl testLoop+3Ah (0040110a)
*/
int iIndex = 0;
const int iCntMax = 3;
printf("===sim do-while===\n");
label_do_while:
printf("iIndex = %d\n", iIndex);
if (iIndex++ < iCntMax)
goto label_do_while;
}
void MyLoop_while()
{
/**
46: iIndex = 0;
00401113 mov dword ptr [ebp-4],0
47: while (iIndex++ < iCntMax)
0040111A mov eax,dword ptr [ebp-4]
0040111D mov ecx,dword ptr [ebp-8]
00401120 mov edx,dword ptr [ebp-4]
00401123 add edx,1
00401126 mov dword ptr [ebp-4],edx
00401129 cmp eax,ecx
0040112B jge testLoop+60h (00401140)
48: {
49: printf("iIndex = %d\n", iIndex);
0040112D mov eax,dword ptr [ebp-4]
00401130 push eax
00401131 push offset string "iIndex = %d\n" (0042301c)
00401136 call printf (00401630)
0040113B add esp,8
50: }
0040113E jmp testLoop+3Ah (0040111a)
51: }
*/
int iIndex = 0;
const int iCntMax = 3;
iIndex = 0;
printf("===sim while===\n");
label_while_begin:
if (iIndex++ > (iCntMax - 1))
goto label_while_end;
printf("iIndex = %d\n", iIndex);
goto label_while_begin;
label_while_end:
;
}
运行效果
分析
在vsIDE中,在运行到循环入口处,切换到反汇编窗口. 将循环的反汇编代码拷贝出来。将CMP改成if, 将JMP改成goto, 即可用goto + if 完全模拟3种循环(for, do-while, while)
在相同条件下(循环条件相同,循环体代码相同), 经过比较可知 : 效率最高 => do-while => while => for => 效率最低.
效率的定义: 汇编代码行数最少.