1、选择语句
(1)、if语句
示例代码:
#include "stdafx.h"
int main(int argc, char* argv[])
{
printf("Hello World!\n");
int a,b,temp;
a = 4;
b = 3;
if( a < b )
{
//将a和b的值互换
temp = a;
a = b;
b = temp;
}
printf("%d=%d",a,b);
printf("end\n");
return 0;
}
总体反汇编代码:
10: int a,b,temp;
11: a = 4;
0040F9C5 C7 45 FC 04 00 00 00 mov dword ptr [ebp-4],4
12: b = 3;
0040F9CC C7 45 F8 03 00 00 00 mov dword ptr [ebp-8],3
13: if( a > b )
0040F9D3 8B 45 FC mov eax,dword ptr [ebp-4]
0040F9D6 3B 45 F8 cmp eax,dword ptr [ebp-8]
0040F9D9 7E 12 jle main+4Dh (0040f9ed)
14: {
15: //将a和b的值互换
16: temp = a;
0040F9DB 8B 4D FC mov ecx,dword ptr [ebp-4]
0040F9DE 89 4D F4 mov dword ptr [ebp-0Ch],ecx
17: a = b;
0040F9E1 8B 55 F8 mov edx,dword ptr [ebp-8]
0040F9E4 89 55 FC mov dword ptr [ebp-4],edx
18: b = temp;
0040F9E7 8B 45 F4 mov eax,dword ptr [ebp-0Ch]
0040F9EA 89 45 F8 mov dword ptr [ebp-8],eax
19: }
20:
21: printf("%d=%d",a,b);
0040F9ED 8B 4D F8 mov ecx,dword ptr [ebp-8]
0040F9F0 51 push ecx
0040F9F1 8B 55 FC mov edx,dword ptr [ebp-4]
0040F9F4 52 push edx
0040F9F5 68 18 60 42 00 push offset string "%d<%d" (00426018)
0040F9FA E8 11 17 FF FF call printf (00401110)
0040F9FF 83 C4 0C add esp,0Ch
分步解析:
10: int a,b,temp;
11: a = 4;
0040F9C5 C7 45 FC 04 00 00 00 mov dword ptr [ebp-4],4
12: b = 3;
0040F9CC C7 45 F8 03 00 00 00 mov dword ptr [ebp-8],3
如上代码可见,在定义变量时并没有为变量分配空间,而是赋值的时候分配。例如
11: a = 4;
0040F9C5 C7 45 FC 04 00 00 00 mov dword ptr [ebp-4],4
将a的值mov如一个内存单元中。
13: if( a > b )
0040F9D3 8B 45 FC mov eax,dword ptr [ebp-4]
0040F9D6 3B 45 F8 cmp eax,dword ptr [ebp-8]
0040F9D9 7E 12 jle main+4Dh (0040f9ed)
首先是将存储a值的内存单元赋值给寄存器eax,然后将eax与存储b值的内存单元进行cmp比较。(为什么不直接cmp 两个内存单元呢?因为cmp指令不同同时比较两个内存单元)
当jle(小于或等于)时(即a<=b),跳转到 “main+4Dh”内存单元,从main开始向后偏移4Dh个地址(即内存单元(0040f9ed) ),刚好是 if {} 代码块的下一条指令。
因此,当 a<=b 时,程序跳过 if代码块执行下一条语句。
15: //将a和b的值互换
16: temp = a;
0040F9DB 8B 4D FC mov ecx,dword ptr [ebp-4]
0040F9DE 89 4D F4 mov dword ptr [ebp-0Ch],ecx
17: a = b;
0040F9E1 8B 55 F8 mov edx,dword ptr [ebp-8]
0040F9E4 89 55 FC mov dword ptr [ebp-4],edx
18: b = temp;
0040F9E7 8B 45 F4 mov eax,dword ptr [ebp-0Ch]
0040F9EA 89 45 F8 mov dword ptr [ebp-8],eax
上面为交换两个数的代码,可知,之前没有被赋值即没有分配内存空间的temp顺位分配到【ebp-0Ch】的内存单元中了。并且每次变量赋值时,都是先将一个变量赋值给寄存器,然后再将寄存器的值赋给另外一个变量。
if综述:
例如:if(a>b)语句,先将a赋值给寄存器,然后将寄存器与存储b相关的值进行cmp比较,jle(小于等于)的的话,就直接跳到 if代码块的下一个执行语句。(如果为if( a<b ),那么跳转语句为 jge(大于等于) ,如果是if(a=b),那么跳转语句为je(等于))
跳转指令机器码:
直接跳 JMP EB 八位
直接跳 JMP E9 十六位
直接标志转移(8位寻址)
指令格式 机器码 测试条件 如…则转移
指令格式 机器码 测试条件 如…则转移
JC 72 C=1 有进位 JNS 79 S=0 正号
JNC 73 C=0 无进位 JO 70 O=1 有溢出
JZ/JE 74 Z=1 零/等于 JNO 71 O=0 无溢出
JNZ/JNE 75 Z=0 不为零/不等于 JP/JPE 7A P=1 奇偶位为偶
汇编代码实现:
#include "stdafx.h"
int main(int argc, char* argv[])
{
printf("Hello World!\n");
char* str = "a=%d,b=%d\n";
_asm{
push 4
push 3
mov eax, [esp+4]
mov ebx, [esp+0]
cmp eax, ebx
jge swap
xchg eax, ebx
swap: push ebx
push eax
push str
call printf
add esp, 12
jmp end
end: nop
}
/*
int a,b,temp;
a = 4;
b = 3;
if( a < b )
{
//将a和b的值互换
temp = a;
a = b;
b = temp;
}
*/
// printf("%d=%d",a,b);
printf("end\n");
return 0;
}
(2)、if–else语句
示例代码:
```cpp
int main(int argc, char* argv[])
{
printf("Hello World!\n");
int a;
a = 4;
if( a < 5 )
{
a = 5;
}
else
a = 10;
printf("%d\n",a);
printf("end\n");
return 0;
}
总体反汇编:
10: int a;
11: a = 4;
0040F9C5 C7 45 FC 04 00 00 00 mov dword ptr [ebp-4],4
12: if( a < 5 )
0040F9CC 83 7D FC 05 cmp dword ptr [ebp-4],5
0040F9D0 7D 09 jge main+3Bh (0040f9db)
13: {
14: a = 5;
0040F9D2 C7 45 FC 05 00 00 00 mov dword ptr [ebp-4],5
15: }
16: else
0040F9D9 EB 07 jmp main+42h (0040f9e2)
17: a = 10;
0040F9DB C7 45 FC 0A 00 00 00 mov dword ptr [ebp-4],0Ah
18:
19: printf("%d\n",a);
0040F9E2 8B 45 FC mov eax,dword ptr [ebp-4]
0040F9E5 50 push eax
0040F9E6 68 24 50 42 00 push offset string "a=%d,b=%d\n" (00425024)
0040F9EB E8 20 17 FF FF call printf (00401110)
0040F9F0 83 C4 08 add esp,8
20:
12: if( a < 5 )
0040F9CC 83 7D FC 05 cmp dword ptr [ebp-4],5
0040F9D0 7D 09 jge main+3Bh (0040f9db)
由上面汇编可知,在 if(a<5) 时,类似于一个单独的 if 语句,cmp进行条件比较,jge进行对应条件的转移地址。
16: else
0040F9D9 EB 07 jmp main+42h (0040f9e2)
如上为else反汇编语句,简答的一个jmp跳址,刚好 跳出else代码块。
综述:if - else语句其实就是先cmp条件比较,然后 jge决定是否符合条件(类似于 if条件语句);而else语句就是一个简单的 jmp 语句,用来跳出 else 代码块。
(3)、if-else if -else语句
示例代码:
int main(int argc, char* argv[])
{
printf("Hello World!\n");
int a;
a = 4;
if( a < 5 )
{
a = 5;
}
else if(a = 5)
a = 5;
else
a = 10;
printf("%d\n",a);
printf("end\n");
return 0;
}
总体反汇编:
由上可知:if - else if - else语句:
第一个 if(a<5) 语句:首先先cmp进行条件比较,然后 jge 判断是否符合条件。
而第二个else if( a=5 )语句:可以分解成else + if( a=5 ),所以反汇编代码第一句类似于else 为 jmp+地址,当满足if条件时,则执行if代码块,只有当执行完if代码块后,才会开始执行else语句,而else汇编代码为jmp+地址,所以便直接跳出了else if和后面的else代码块,然后执行最后的printf语句。