do..while、while、for循环反汇编剖析

1、循环语句重要特征提取

循环语句最重要的特点就是执行的过程中会往上跳!!!

箭头往上跳的一般都是循环语句,比如下面的for循环: 

do..while、while、for循环反汇编剖析_第1张图片

2、do..while语句反汇编

#include
using namespace std;
#pragma warning (disable:4996)

//1、do..while
void Fun(int x, int y) {

	do {
		printf("%d\n", x);
		x++;
	} while (x < y);

}

int main() {

	Fun(0, 10);
	system("pause");
	return 0;
}
00C51790  push        ebp  
00C51791  mov         ebp,esp  
00C51793  sub         esp,0C0h  
00C51799  push        ebx  
00C5179A  push        esi  
00C5179B  push        edi  
00C5179C  mov         edi,ebp  
00C5179E  xor         ecx,ecx  
00C517A0  mov         eax,0CCCCCCCCh  
00C517A5  rep stos    dword ptr es:[edi]  
00C517A7  mov         ecx,offset _A8394B5C_循环语句测试@cpp (0C5C029h)  
00C517AC  call        @__CheckForDebuggerJustMyCode@4 (0C51325h)  
00C517B1  mov         eax,dword ptr [x]  
00C517B4  push        eax  
00C517B5  push        offset string "%d\n" (0C57B30h)  
00C517BA  call        _printf (0C510CDh)  
00C517BF  add         esp,8  
00C517C2  mov         eax,dword ptr [x]  
00C517C5  add         eax,1  
00C517C8  mov         dword ptr [x],eax  
00C517CB  mov         eax,dword ptr [x]  
00C517CE  cmp         eax,dword ptr [y]  
00C517D1  jl          __$EncStackInitStart+15h (0C517B1h)  
00C517D3  pop         edi  
00C517D4  pop         esi  
00C517D5  pop         ebx  
00C517D6  add         esp,0C0h  
00C517DC  cmp         ebp,esp  
00C517DE  call        __RTC_CheckEsp (0C51249h)  
00C517E3  mov         esp,ebp  
00C517E5  pop         ebp  
00C517E6  ret  

由此可以分析:do..while是先执行{}里的内容,然后再判断是不是需要跳出循环,如果不跳出就跳到do..while开始的地方继续执行。

3、while语句分析

#include
using namespace std;
#pragma warning (disable:4996)

//2、while

void Fun(int x, int y) {

	while (x < y) {
		printf("%d\n", x);
		++x;
	}

}

int main() {

	Fun(0, 10);
	system("pause");
	return 0;

}
009D1790  push        ebp  
009D1791  mov         ebp,esp  
009D1793  sub         esp,0C0h  
009D1799  push        ebx  
009D179A  push        esi  
009D179B  push        edi  
009D179C  mov         edi,ebp  
009D179E  xor         ecx,ecx  
009D17A0  mov         eax,0CCCCCCCCh  
009D17A5  rep stos    dword ptr es:[edi]  
009D17A7  mov         ecx,offset _A8394B5C_循环语句测试@cpp (09DC029h)  
009D17AC  call        @__CheckForDebuggerJustMyCode@4 (09D1325h)
009D17B1  mov         eax,dword ptr [x]  
009D17B4  cmp         eax,dword ptr [y]  
009D17B7  jge         __$EncStackInitStart+39h (09D17D5h)  
009D17B9  mov         eax,dword ptr [x]  
009D17BC  push        eax  
009D17BD  push        offset string "%d\n" (09D7B30h)  
009D17C2  call        _printf (09D10CDh)  
009D17C7  add         esp,8  
009D17CA  mov         eax,dword ptr [x]  
009D17CD  add         eax,1  
009D17D0  mov         dword ptr [x],eax  
009D17D3  jmp         __$EncStackInitStart+15h (09D17B1h)  
009D17D5  pop         edi  
009D17D6  pop         esi  
009D17D7  pop         ebx  
009D17D8  add         esp,0C0h  
009D17DE  cmp         ebp,esp  
009D17E0  call        __RTC_CheckEsp (09D1249h)  
009D17E5  mov         esp,ebp  
009D17E7  pop         ebp  
009D17E8  ret  

while语句是先判断,不符合就跳出循环,符合就执行循环体里的内容,最后再跳到开始进行判断

4、while(y--)语句分析

#include
using namespace std;
#pragma warning (disable:4996)

void Fun(int x, int y) {

	while (y--) {
		printf("%d\n", y);
	}

}
int main() {

	Fun(0, 10);
	system("pause");
	return 0;
}
00FA1790  push        ebp  
00FA1791  mov         ebp,esp  
00FA1793  sub         esp,0C4h  
00FA1799  push        ebx  
00FA179A  push        esi  
00FA179B  push        edi  
00FA179C  lea         edi,[ebp-4]  
00FA179F  mov         ecx,1  
00FA17A4  mov         eax,0CCCCCCCCh  
00FA17A9  rep stos    dword ptr es:[edi]  
00FA17AB  mov         ecx,offset _A8394B5C_循环语句测试@cpp (0FAC029h)  
00FA17B0  call        @__CheckForDebuggerJustMyCode@4 (0FA1325h)  
00FA17B5  mov         eax,dword ptr [y]  
00FA17B8  mov         dword ptr [ebp-0C4h],eax  
00FA17BE  mov         ecx,dword ptr [y]  
00FA17C1  sub         ecx,1  
00FA17C4  mov         dword ptr [y],ecx  
00FA17C7  cmp         dword ptr [ebp-0C4h],0  
00FA17CE  je          __$EncStackInitStart+47h (0FA17E3h)  
00FA17D0  mov         eax,dword ptr [y]  
00FA17D3  push        eax  
00FA17D4  push        offset string "%d\n" (0FA7B30h)  
00FA17D9  call        _printf (0FA10CDh)  
00FA17DE  add         esp,8  
00FA17E1  jmp         __$EncStackInitStart+19h (0FA17B5h)  
00FA17E3  pop         edi  
00FA17E4  pop         esi  
00FA17E5  pop         ebx  
00FA17E6  add         esp,0C4h  
00FA17EC  cmp         ebp,esp  
00FA17EE  call        __RTC_CheckEsp (0FA1249h)  
00FA17F3  mov         esp,ebp  
00FA17F5  pop         ebp  
00FA17F6  ret  

先执行while括号()里的内容,然后cmp判断是否需要跳出循环(当且仅当y==0的时候才会跳出循环!!!我竟然现在才发现),不需要就一路往后执行,然后再跳回到一开始的()的语句进行处理。

5、for循环分析

#include
using namespace std;
#pragma warning (disable:4996)

void Fun(int x, int y) {

	for (int i = x; i < y; i++) {
		printf("%d\n", i);
	}

}

int main() {

	Fun(0, 9);
	system("pause");
	return 0;
}
00E61790  push        ebp  
00E61791  mov         ebp,esp  
00E61793  sub         esp,0CCh  
00E61799  push        ebx  
00E6179A  push        esi  
00E6179B  push        edi  
00E6179C  lea         edi,[ebp-0Ch]  
00E6179F  mov         ecx,3  
00E617A4  mov         eax,0CCCCCCCCh  
00E617A9  rep stos    dword ptr es:[edi]  
00E617AB  mov         ecx,offset _A8394B5C_循环语句测试@cpp (0E6C029h)  
00E617B0  call        @__CheckForDebuggerJustMyCode@4 (0E61325h)  
00E617B5  mov         eax,dword ptr [x]  
00E617B8  mov         dword ptr [ebp-8],eax  
00E617BB  jmp         __$EncStackInitStart+2Ah (0E617C6h)  
00E617BD  mov         eax,dword ptr [ebp-8]  
00E617C0  add         eax,1  
00E617C3  mov         dword ptr [ebp-8],eax  
00E617C6  mov         eax,dword ptr [ebp-8]  
00E617C9  cmp         eax,dword ptr [y]  
00E617CC  jge         __$EncStackInitStart+45h (0E617E1h)  
00E617CE  mov         eax,dword ptr [ebp-8]  
00E617D1  push        eax  
00E617D2  push        offset string "%d\n" (0E67B30h)  
00E617D7  call        _printf (0E610CDh)  
00E617DC  add         esp,8  
00E617DF  jmp         __$EncStackInitStart+21h (0E617BDh)  
00E617E1  pop         edi  
00E617E2  pop         esi  
00E617E3  pop         ebx  
00E617E4  add         esp,0CCh  
00E617EA  cmp         ebp,esp  
00E617EC  call        __RTC_CheckEsp (0E61249h)  
00E617F1  mov         esp,ebp  
00E617F3  pop         ebp  
00E617F4  ret  

可以总结:for循环是先给i赋值,然后判断(i

6、i++和++i在for循环当中效率一样吗?

i++:

00E617BD  mov         eax,dword ptr [ebp-8]  
00E617C0  add         eax,1  
00E617C3  mov         dword ptr [ebp-8],eax 

++i:

008B17BE  mov         eax,dword ptr [ebp-8]  
008B17C1  add         eax,1  
008B17C4  mov         dword ptr [ebp-8],eax 

有区别吗?》没区别,所以不要被培训班的老师骗了,编译器才是真理!!!

那么,今天的逆向学习内容到这里就结束了,又是收获满满的一天呢!喜欢的话多多点赞收藏吧!!!

你可能感兴趣的:(逆向学习,c语言,windows,汇编,c++)