在分支较多的时候,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语言)的更多相关文章

  1. Linux环境下使用gcc编译,gdb反汇编C语言程序

    使用虚拟机 VMware Workstation 10 Linux环境:Ubuntu 14.04 LTS Server amd64   我把过程截图如下. 首先是hello world程序: 备注: ...

  2. 通过反汇编C语言小程序学习Liunx汇编语言

    大家好!    我是来自山东师范大学的吴乐.    今天在<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ...

  3. 《天书夜读:从汇编语言到windows内核编程》三 练习反汇编C语言程序

    1) Debug版本算法反汇编,现有如下3×3矩阵相乘的程序: #define SIZE 3 int MyFunction(int a[SIZE][SIZE],int b[SIZE][SIZE],in ...

  4. switch反汇编

    以下总结为debug模式

  5. Go丨语言学习笔记--switch

    Java语言与Go语言的switch对比 Go语言 switch str { case "yes" : do something ... case "no" d ...

  6. 利用反汇编手段解析C语言函数

    1.问题的提出函数是 C语言中的重要概念.利用好函数能够充分利用系统库的功能写出模块独立.易于维护和修改的程序.函数并不是 C 语言独有的概念,其他语言中的方法.过程等本质上都是函数.可见函数在教学中 ...

  7. go语言之if语句和switch语句和循环语句

    1.if语句 package main import ( "fmt" "io/ioutil" ) func main() { //流程控制 //使用常量定义一个 ...

  8. (八)羽夏看C语言——C番外篇

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  9. Go语言程序设计(1)--基本语法

    第一个程序 package main import "fmt" func main() { fmt.Printf("Hello world") } 通过阅读这个 ...

随机推荐

  1. Beta冲刺阶段3.0

    1. 提供当天站立式会议照片一张 2. 每个人的工作 (有work item 的ID) 成员 昨天已完成的工作 今天计划完成的工作 工作中遇到的困难 具体贡献 郑晓丽 完成"我的活动&quo ...

  2. 03-树2 List Leaves(25)

    题目 分析 输入先给出结点的数量,把结点从0开始标号,每一行给出结点的左右两个子节点,-表示子节点不存在. 很容易分析出在子节点中没有出现的就是根节点,两个子节点都为空的是叶子节点 先建树,然后从ro ...

  3. mysql 知识

    1.  数据库事务的四个特性及含义 数据库事务transanction正确执行的四个基本要素.ACID,原子性(Atomicity).一致性(Correspondence).隔离性(Isolation ...

  4. 2.sklearn库中的标准数据集与基本功能

    sklearn库中的标准数据集与基本功能 下面我们详细介绍几个有代表性的数据集: 当然同学们也可以用sklearn机器学习函数来挖掘这些数据,看看可不可以捕捉到一些有趣的想象或者是发现: 波士顿房价数 ...

  5. RobotFrameWork(一)robotfamework(python版)及Ride在windows安装

    1.windows下的安装 (1)准备条件: python-2.7.3.msi robotframework-2.7.5.win32.exe wxPython2.8-win32-unicode-2.8 ...

  6. codeforces 984B Minesweeper

    题意: 给出一个矩阵,如果一个格子是数字,那么与这个格子相邻的格子中有炸弹的数量必须等于这个格子中的数字: 如果一个格子是空地,那么这个格子的所有相邻的格子中就不能有炸弹. 判断这个矩阵是否合法. 思 ...

  7. XML文件怎么添加注释

    注释以 <!-- 开始并以 --> 结束,例如 <!--注释内容-->.   注释可以出现在文档序言中,包括文档类型定义 (DTD):文档之后:或文本内容中. 注释不能出现在属 ...

  8. CRM 权限设置

    表结构的设计 权限表 url -url地址的正则表达式 ^$ title - 标题 角色表 name - 角色名称 permissions 多对多关联权限表 (权限和角色的关系表) 用户表 name ...

  9. python-数据分析与展示(Numpy、matplotlib、pandas)---3

    笔记内容整理自mooc上北京理工大学嵩天老师python系列课程数据分析与展示,本人小白一枚,如有不对,多加指正 0.pandas基于Numpy实现的,前者注重应用,后者注重结构 1.Series类型 ...

  10. python的一些遗漏用法

    一. 补充基础数据类型的相关知识点 1. str. join() 把列表变成字符串 li = ["李嘉诚", "麻花藤", "⻩海峰", & ...