switch反汇编(C语言)
在分支较多的时候,switch的效率比if高,在反汇编中我们即可看到效率高的原因
0x01分支结构不超过3个
#include <stdio.h>
void main()
{
int x = 5;
switch(x)
{
case 5:
printf("%d\n",x);
break;
case 6:
printf("%d\n",x);
break;
case 7:
printf("%d\n",x);
break;
default:
break;
}
return;
}
5: int x = 5;
00401028 mov dword ptr [ebp-4],5
6: switch(x)
7: {
0040102F mov eax,dword ptr [ebp-4]
00401032 mov dword ptr [ebp-8],eax //x的值放入[ebp-8]
00401035 cmp dword ptr [ebp-8],5
00401039 je main+39h (00401049) //x与5相等就跳转,下面6和7相同
0040103B cmp dword ptr [ebp-8],6
0040103F je main+4Ch (0040105c)
00401041 cmp dword ptr [ebp-8],7
00401045 je main+5Fh (0040106f)
00401047 jmp main+72h (00401082)
8: case 5:
9: printf("%d\n",x);
00401049 mov ecx,dword ptr [ebp-4]
0040104C push ecx
0040104D push offset string "%d\n" (0042201c)
00401052 call printf (004010d0)
00401057 add esp,8
10: break;
0040105A jmp main+83h (00401093)
11: case 6:
12: printf("%d\n",x);
0040105C mov edx,dword ptr [ebp-4]
0040105F push edx
00401060 push offset string "%d\n" (0042201c)
00401065 call printf (004010d0)
0040106A add esp,8
13: break;
0040106D jmp main+83h (00401093)
14: case 7:
15: printf("%d\n",x);
0040106F mov eax,dword ptr [ebp-4]
00401072 push eax
00401073 push offset string "%d\n" (0042201c)
00401078 call printf (004010d0)
0040107D add esp,8
16: break;
00401080 jmp main+83h (00401093)
17: default:
18: printf("%d\n",x);
00401082 mov ecx,dword ptr [ebp-4]
00401085 push ecx
00401086 push offset string "%d\n" (0042201c)
0040108B call printf (004010d0)
00401090 add esp,8
19: break;
20: }
0x02分支数超过3且分支存在线性关系
#include <stdio.h>
void main()
{
int x = 5;
switch(x)
{
case 5:
printf("%d\n",x);
break;
case 6:
printf("%d\n",x);
break;
case 7:
printf("%d\n",x);
break;
case 8:
printf("%d\n",x);
break;
case 9:
printf("%d\n",x);
break;
default:
printf("%d\n",x);
break;
}
return;
}
5: int x = 5;
0040D778 mov dword ptr [ebp-4],5
6: switch(x)
7: {
0040D77F mov eax,dword ptr [ebp-4]
0040D782 mov dword ptr [ebp-8],eax
0040D785 mov ecx,dword ptr [ebp-8]
0040D788 sub ecx,5 //x减去分支中的最小值5,方便构建跳转表
0040D78B mov dword ptr [ebp-8],ecx
0040D78E cmp dword ptr [ebp-8],4
0040D792 ja $L537+13h (0040d7fd) //x-5>4跳转到default,即x>9跳转
0040D794 mov edx,dword ptr [ebp-8] //edx=x-5
0040D797 jmp dword ptr [edx*4+40D81Fh] //构建跳转表,根据edx的值从对应地址取出值(各个分支的地址),40D81F为跳转表起始地址
8: case 5:
9: printf("%d\n",x);
0040D79E mov eax,dword ptr [ebp-4]
0040D7A1 push eax
0040D7A2 push offset string "%d\n" (0042201c)
0040D7A7 call printf (004010d0)
0040D7AC add esp,8
10: break;
0040D7AF jmp $L537+24h (0040d80e)
11: case 6:
12: printf("%d\n",x);
0040D7B1 mov ecx,dword ptr [ebp-4]
0040D7B4 push ecx
0040D7B5 push offset string "%d\n" (0042201c)
0040D7BA call printf (004010d0)
0040D7BF add esp,8
13: break;
0040D7C2 jmp $L537+24h (0040d80e)
14: case 7:
15: printf("%d\n",x);
0040D7C4 mov edx,dword ptr [ebp-4]
0040D7C7 push edx
0040D7C8 push offset string "%d\n" (0042201c)
0040D7CD call printf (004010d0)
0040D7D2 add esp,8
16: break;
0040D7D5 jmp $L537+24h (0040d80e)
17: case 8:
18: printf("%d\n",x);
0040D7D7 mov eax,dword ptr [ebp-4]
0040D7DA push eax
0040D7DB push offset string "%d\n" (0042201c)
0040D7E0 call printf (004010d0)
0040D7E5 add esp,8
19: break;
0040D7E8 jmp $L537+24h (0040d80e)
20: case 9:
21: printf("%d\n",x);
0040D7EA mov ecx,dword ptr [ebp-4]
0040D7ED push ecx
0040D7EE push offset string "%d\n" (0042201c)
0040D7F3 call printf (004010d0)
0040D7F8 add esp,8
22: break;
0040D7FB jmp $L537+24h (0040d80e)
23: default:
24: printf("%d\n",x);
0040D7FD mov edx,dword ptr [ebp-4]
0040D800 push edx
0040D801 push offset string "%d\n" (0042201c)
0040D806 call printf (004010d0)
0040D80B add esp,8
25: break;
26: }
跳转表从[edx*4+40D81Fh]取出分支的地址值然后进行jmp,下表是跳转表部分
0040D81F 9E D7 40 00 ..@.
0040D823 B1 D7 40 00 ..@.
0040D827 C4 D7 40 00 ..@.
0040D82B D7 D7 40 00 ..@.
0040D82F EA D7 40 00 ..@.
0x03分支跃度大难以构成跳转表的分支结构
#include <stdio.h>
void main()
{
int x = 5;
switch(x)
{
case 5:
printf("%d\n",x);
break;
case 6:
printf("%d\n",x);
break;
case 7:
printf("%d\n",x);
break;
case 8:
printf("%d\n",x);
break;
case 100:
printf("%d\n",x);
break;
default:
printf("%d\n",x);
break;
}
return;
}
5: int x = 5;
00401028 mov dword ptr [ebp-4],5
6: switch(x)
7: {
0040102F mov eax,dword ptr [ebp-4]
00401032 mov dword ptr [ebp-8],eax
00401035 mov ecx,dword ptr [ebp-8]
00401038 sub ecx,5
0040103B mov dword ptr [ebp-8],ecx
0040103E cmp dword ptr [ebp-8],5Fh
00401042 ja $L536+13h (004010b5) //具体参见上一种,x大于100跳转到default
00401044 mov eax,dword ptr [ebp-8] //edx=x-5
00401047 xor edx,edx //edx置零
00401049 mov dl,byte ptr (004010ef)[eax] //查询索引表并将取出来的值放入DL(在od里面的这条反汇编更清楚)
0040104F jmp dword ptr [edx*4+4010D7h] //根据DL(EDX)的值查跳转表
8: case 5:
9: printf("%d\n",x);
00401056 mov ecx,dword ptr [ebp-4]
00401059 push ecx
0040105A push offset string "%d\n" (0042201c)
0040105F call printf (004011a0)
00401064 add esp,8
10: break;
00401067 jmp $L536+24h (004010c6)
11: case 6:
12: printf("%d\n",x);
00401069 mov edx,dword ptr [ebp-4]
0040106C push edx
0040106D push offset string "%d\n" (0042201c)
00401072 call printf (004011a0)
00401077 add esp,8
13: break;
0040107A jmp $L536+24h (004010c6)
14: case 7:
15: printf("%d\n",x);
0040107C mov eax,dword ptr [ebp-4]
0040107F push eax
00401080 push offset string "%d\n" (0042201c)
00401085 call printf (004011a0)
0040108A add esp,8
16: break;
0040108D jmp $L536+24h (004010c6)
17: case 8:
18: printf("%d\n",x);
0040108F mov ecx,dword ptr [ebp-4]
00401092 push ecx
00401093 push offset string "%d\n" (0042201c)
00401098 call printf (004011a0)
0040109D add esp,8
19: break;
004010A0 jmp $L536+24h (004010c6)
20: case 100:
21: printf("%d\n",x);
004010A2 mov edx,dword ptr [ebp-4]
004010A5 push edx
004010A6 push offset string "%d\n" (0042201c)
004010AB call printf (004011a0)
004010B0 add esp,8
22: break;
004010B3 jmp $L536+24h (004010c6)
23: default:
24: printf("%d\n",x);
004010B5 mov eax,dword ptr [ebp-4]
004010B8 push eax
004010B9 push offset string "%d\n" (0042201c)
004010BE call printf (004011a0)
004010C3 add esp,8
25: break;
26: }
索引表
004010F1 00 01 02 03 05 05 05 05 ........
004010F9 05 05 05 05 05 05 05 05 ........
00401101 05 05 05 05 05 05 05 05 ........
00401109 05 05 05 05 05 05 05 05 ........
00401111 05 05 05 05 05 05 05 05 ........
00401119 05 05 05 05 05 05 05 05 ........
00401121 05 05 05 05 05 05 05 05 ........
00401129 05 05 05 05 05 05 05 05 ........
00401131 05 05 05 05 05 05 05 05 ........
00401139 05 05 05 05 05 05 05 05 ........
00401141 05 05 05 05 05 05 05 05 ........
00401149 05 05 05 05 05 05 05 04 ........
跳转表
004010D9 58 10 40 00 X.@.
004010DD 6B 10 40 00 k.@.
004010E1 7E 10 40 00 ~.@.
004010E5 91 10 40 00 ..@.
004010E9 A4 10 40 00 ..@.
004010ED B7 10 40 00 ..@.
switch反汇编(C语言)的更多相关文章
- Linux环境下使用gcc编译,gdb反汇编C语言程序
使用虚拟机 VMware Workstation 10 Linux环境:Ubuntu 14.04 LTS Server amd64 我把过程截图如下. 首先是hello world程序: 备注: ...
- 通过反汇编C语言小程序学习Liunx汇编语言
大家好! 我是来自山东师范大学的吴乐. 今天在<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ...
- 《天书夜读:从汇编语言到windows内核编程》三 练习反汇编C语言程序
1) Debug版本算法反汇编,现有如下3×3矩阵相乘的程序: #define SIZE 3 int MyFunction(int a[SIZE][SIZE],int b[SIZE][SIZE],in ...
- switch反汇编
以下总结为debug模式
- Go丨语言学习笔记--switch
Java语言与Go语言的switch对比 Go语言 switch str { case "yes" : do something ... case "no" d ...
- 利用反汇编手段解析C语言函数
1.问题的提出函数是 C语言中的重要概念.利用好函数能够充分利用系统库的功能写出模块独立.易于维护和修改的程序.函数并不是 C 语言独有的概念,其他语言中的方法.过程等本质上都是函数.可见函数在教学中 ...
- go语言之if语句和switch语句和循环语句
1.if语句 package main import ( "fmt" "io/ioutil" ) func main() { //流程控制 //使用常量定义一个 ...
- (八)羽夏看C语言——C番外篇
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...
- Go语言程序设计(1)--基本语法
第一个程序 package main import "fmt" func main() { fmt.Printf("Hello world") } 通过阅读这个 ...
随机推荐
- linux常见运维题
linux运维题 一.填空题 1. 在Linux 系统 中,以文件方式访问设备 . (linux下一切都是文件) 2. Linux 内核引导时,从文件/etc/fstab中读取要加载的文件系统 . ( ...
- smtp常见问题
http://blog.csdn.net/chenfei_5201213/article/details/10138969
- vs远程调试 转http://www.cnblogs.com/magicchaiy/archive/2013/05/28/3088274.html
远程调试应用场景 部署环境:ASP.NET(C#)+IIS+Win7 64 bit 很多公司的开发模式都是将开发机器和服务器分开,也就是开发一台机,服务器一台机.而测试人员会在服务器上录入测试数据,此 ...
- html5随机背景颜色
<script>var colors=['red','blue','green','orange','yellow']; function bcolor(){ var ...
- 排序(I)
NSSortDescriptor 排序 Person类 #import <Foundation/Foundation.h> @interface Person : NSObject @pr ...
- kali 创建快捷方式的方法
Kali应用程序快捷方式分析 kali默认使用Gnome桌面环境,所以给kali添加应用程序快捷方式就是给Gnome添加应用快捷方式. 在/usr/share/applications目录下有很多的. ...
- ATM-JAVA程序 //程序有5处相同错误,找不出原因 转账功能没有实现,修改密码来不及实现了
package JCC;//信1705-3 20173681 靳晨晨import java.io.BufferedReader;import java.io.File;import java.io.F ...
- Chrome表单自动填充如何取消(暂时可行的解决办法)
做项目时一直遇到一个问题,那就是用chrome测试的时候页面上的表单一直会自动填充,并且伴有黄色的背景颜色,有时候感觉很方便,有时候又很想去掉. 之前也多次寻找过方法,但是网上的方法都差不多,很多都是 ...
- AtCoder Beginner Contest 086 (ABCD)
A - Product 题目链接:https://abc086.contest.atcoder.jp/tasks/abc086_a Time limit : 2sec / Memory limit : ...
- Lonsdor K518ISE free update news on what makes and year can work
Lonsdor K518ISE engineers recently tested a number of cars and verified working great, below are tes ...