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") } 通过阅读这个 ...
随机推荐
- HDU1007.Quoit Design
-- 点我 -- 题目大意 :给你一堆点,求一个最小圆能够覆盖两个点的半径(最近两点距离的一半): 最多100000个点,暴力即O(n^2)会超时,考虑二分,先求左边最短距离dl,右边dr, 和一个点 ...
- sitecore系统教程之架构概述
Sitecore体验数据库(xDB)从实时大数据存储库中的所有通道源收集所有客户交互.它连接交互数据,为每个客户创建全面,统一的视图,并使营销人员可以使用数据来管理客户的实时体验. xDB架构非常灵活 ...
- flask 自定义验证器(行内验证器、全局验证器)
自定义验证器 在WTForms中,验证器是指在定义字段时传入validators参数列表的可调用对象,下面来看下编写自定义验证器. 行内验证器 除了使用WTForms提供的验证器来验证表单字段,我们还 ...
- 【Alpha版本】冲刺阶段——Day7
[Alpha版本]冲刺阶段--Day7 阅读目录 今日进展 今日贡献量 贡献量汇总 TODOList 及项目燃尽图 [今日进展] 将项目源文件打成jar包,并运行测试 完成答辩ppt 项目运行情况 主 ...
- DB2的空间数据库管理复杂配置
计算机条件: a机器:linux系统 安装arcgis server b机器:windows系统 安装catalog c机器:linux系统 安装DB2 ...
- Flask-----轻量级的框架,快速的搭建程序
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...
- 课堂测试代码(未完全实现,部分代码有bug,仅供参考)
//信1705-3 20173507 周龙海package account; public class account { private String accountID; private Stri ...
- Spring Boot 实现RESTful webservice服务端实例
1.Spring Boot configurations application.yml spring: profiles: active: dev mvc: favicon: enabled: fa ...
- 安装启动kafka
vim kafka/config/server.properties #确保唯一 broker.id=0 #允许删除主题 delete.topic.enable=true # 指定数据文件所在目录 l ...
- bzoj 3083
bzoj 3083 树链剖分,换根 对于一颗树有以下操作 1.确定x为根,2.将u到v的简单路径上的数全改成c,3.询问当前以x为根的子树中的节点最小权值. 如果没有操作1:树链剖分很明显. 于是考虑 ...