用汇编中查看常见的控制流

时间:2021-07-18 11:55:58

  这篇文章用汇编查看c/c++中常见的控制流。

1. if  else

    在汇编中主要用cmp指令比较两个数,然后利用jz/jnz实现逻辑的跳转。

    首先我们看下cmp指令的功能

CMP结果 ZF CF
目的<源 0 1
目的>源 0 0
目的=源 1 0

    对于有符号数,我们常用jnz表示不相等则跳,jle表示小于则跳,我们可以看下如下列子:

	int a = 4, b =5;

	if (a == 0)
		a = 8;
	else if (a > b)
		a = 9;
	else 
		a = 10;

	return 0;
 看看其对应的汇编源码:
	//int a = 4, b =5;
0119181E  mov         dword ptr [a],4  
01191825  mov         dword ptr [b],5  

	//if (a == 0)
0119182C  cmp         dword ptr [a],0  
01191830  jne         wmain+3Bh (119183Bh)  
	//	a = 8;
01191832  mov         dword ptr [a],8  
01191839  jmp         wmain+53h (1191853h)  
	//else if (a > b)
0119183B  mov         eax,dword ptr [a]  
0119183E  cmp         eax,dword ptr [b]  
01191841  jle         wmain+4Ch (119184Ch)  
	//	a = 9;
01191843  mov         dword ptr [a],9  
	//else 
0119184A  jmp         wmain+53h (1191853h)  
	//	a = 10;
0119184C  mov         dword ptr [a],0Ah  

 

  代码很简单, 看上去是不言而喻的, 就不过多解释了。

    有时我们会直接判断函数的返回值是不是为true.

bool fun1()
{
	return true;
}
int _tmain(int argc, _TCHAR* argv[])
{

	int a =0;
	if (fun1())
		a++;
	

	return 0;
}

 

下面来看下其汇编源码有什么不同:

int a =0;
0089184E  mov         dword ptr [a],0  
	if (fun1())
00891855  call        fun1 (8911C2h)  
0089185A  movzx       eax,al  //函数返回在al中,然后将高位扩展为0
0089185D  test        eax,eax  //判断eax 为0还是1
0089185F  je          wmain+3Ah (89186Ah)  
		a++;
00891861  mov         eax,dword ptr [a]  
00891864  add         eax,1  
00891867  mov         dword ptr [a],eax  
	

 

恩,还是很简单。这里在说下test的用法。

test 对每对数据执行隐含的与操作,并设置相应的标志位。但是不修改目的操作数。如:

00100101

00001001 --->test

00000001---->结果为1, ZF = 0;

2. switch case 语句

    switch case 语句实际上是多个if else 的应用。我们可以看下如下代码:

	int a = 4;
		
	switch(a)
	{
	case 0:
		a++;
		break;
	case 1:
		a--;
		break;
	case 3:
		break;
	default:
		a =10;
	}
	return 0;

 

    可以看下对应的汇编源码:

	//int a = 4;
0036181E  mov         dword ptr [a],4  
		
	//switch(a)
00361825  mov         eax,dword ptr [a]  
00361828  mov         dword ptr [ebp-0D0h],eax  
0036182E  cmp         dword ptr [ebp-0D0h],0  
00361835  je          wmain+4Bh (36184Bh)  //如a==0,则跳到36184B指令
00361837  cmp         dword ptr [ebp-0D0h],1  
0036183E  je          wmain+56h (361856h)  //如a==1,则跳到361856h指令
00361840  cmp         dword ptr [ebp-0D0h],3  
00361847  je          wmain+61h (361861h)  //如a==0,则跳到36186指令
00361849  jmp         wmain+63h (361863h)  //只要到我这里了,都跳到361863
	{
	//case 0:
	//	a++;
0036184B  mov         eax,dword ptr [a]  
0036184E  add         eax,1  
00361851  mov         dword ptr [a],eax  
	//	break;
00361854  jmp         wmain+6Ah (36186Ah)  
	//case 1:
	//	a--;
00361856  mov         eax,dword ptr [a]  
00361859  sub         eax,1  
0036185C  mov         dword ptr [a],eax  
	//	break;
0036185F  jmp         wmain+6Ah (36186Ah)  
	//case 3:
	//	break;
00361861  jmp         wmain+6Ah (36186Ah)  
	//default:
	//	a =10;
00361863  mov         dword ptr [a],0Ah  
	}