这篇文章用汇编查看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 }