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") } 通过阅读这个 ...
随机推荐
- Python并发编程之线程池/进程池--concurrent.futures模块
一.关于concurrent.futures模块 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/ ...
- SourceTree 使用
删除分支 新建一个分支 A 后,要想把 A 分支删除掉,只需跳到另一个分支上去,选中 A 分支然后右击,在弹出的菜单栏中选中 [删除 A 分支]即可: 在分支下建一个文件夹 左上的然后弹出选框,在[新 ...
- django中orm的批量操作
ORM批量操作 数据模型定义 from django.db import models class Product(models.Model): name = models.CharField(max ...
- 对SQLite 数据库的一点点了解
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中.它的设计目标是嵌入式的,它占用资源非常低,在嵌入式设备中,可能只需要几百k的内存就够了. SQLit ...
- C++中set用法详解
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
- Different between MB SD Connect Compact 5 and MB SD C4 Star Diagnostic Tool
MB SD C4 Star Diagnostic Tool is the professional MB Star Diagnostic Tools for benz cars and trucks. ...
- hive 用户行为分析(活跃。启动,留存,回访,新增)的一些经典sql
很简单的sql 用户分析语句 :只要自定义简单的udf函数 获取统计时间createdatms字段的使用的日历类 add方法 和simpledateformat 将long类型的 定义多个重载方法 获 ...
- selenium自动化之鼠标操作
在做自动化测试的时候,经常会遇到这种情况,某个页面元素,你必须要把鼠标移动到上面才能显示出元素.那么这种情况,我们怎么处理呢?,selenium给我们提供了一个类来处理这类事件——ActionChai ...
- NGINX转发代理情况下,获取客户单真实IP
编译时加上http_realip_module 模块 realip模块生效的前提是:直接连接nginx的ip是在set_real_ip_from中指定的. 原机配置: set_real_ip_from ...
- Prometheus监控学习笔记之在 HTTP API 中使用 PromQL
0x00 概述 Prometheus 当前稳定的 HTTP API 可以通过 /api/v1 访问. 0x01 API 响应格式 Prometheus API 使用了 JSON 格式的响应内容. 当 ...