Swithch反汇编(四种)
------------恢复内容开始------------
Switch语法格式
Switch(表达式)
{
case 常量表达式1:
语句;
break;
case 常量表达式2:
语句;
break;
case 常量表达式3:
语句;
break;
default:
语句;
break;
}
Switch注意事项
- case后面必须是常量表达式
- case后常量表达式的值不一样
- switch后面表达式必须为整数类型其它类型诸如float double 等类型均不可以
- case如果没有添加break语句则会继续向下执行下面的case
- dafault语句可以没有,如果所有case都不匹配会默认执行default语句
分支语句的增加之反汇编
分支语句少于等于3条与if—else语句的反汇编相同(case 值连续)
0040103E cmp dword ptr [ebp-4],1
00401042 je tast+32h (00401052)
00401044 cmp dword ptr [ebp-4],2
00401048 je tast+41h (00401061)
0040104A cmp dword ptr [ebp-4],3
0040104E je tast+50h (00401070)
00401050 jmp tast+5Fh (0040107f)
00401052 push offset string "1" (00422028)
00401057 call printf (00401130)
0040105C add esp,4
0040105F jmp tast+6Ch (0040108c)
00401061 push offset string "2" (00422024)
00401066 call printf (00401130)
0040106B add esp,4
0040106E jmp tast+6Ch (0040108c)
00401070 push offset string "4" (00422020)
00401075 call printf (00401130)
0040107A add esp,4
0040107D jmp tast+6Ch (0040108c)
0040107F push offset string "5" (0042201c)
分支语句大于三条生成一张大表(但是不一定,假如差值大的话就会生成if—else)(case后面的常量可以时无序的,并不影响大表的生成)编译的时候就把地址排好了
#include "stdafx.h"
void test(int x)
{
switch(x)
{
case 2:
printf("2");
break;
case 3:
printf("3");
break;
case 4:
printf("4");
break;
case 5:
printf("5");
break;
case 6:
printf("6");
break;
default:
printf("5");
break;
}
}
int main(int argc, char* argv[])
{
test(5);
return 0;
}

case的值是从100-109汇编代码如下:
0040D7D8 mov eax,dword ptr [ebp+8]
0040D7DB mov dword ptr [ebp-4],eax
0040D7DE mov ecx,dword ptr [ebp-4]
0040D7E1 sub ecx,64h // 这个是第一个case
0040D7E4 mov dword ptr [ebp-4],ecx
0040D7E7 cmp dword ptr [ebp-4],9 //这是case的总个数 :9+1
0040D7EB ja $L550+0Fh (0040d897)
0040D7F1 mov edx,dword ptr [ebp-4]
0040D7F4 jmp dword ptr [edx*4+40D8B5h]//这就是生成的表
$L532:
0040D7FB push offset string "100" (00422fc0)
0040D800 call printf (00401130)
0040D805 add esp,4
0040D808 jmp $L550+1Ch (0040d8a4)
$L534:
0040D80D push offset string "101" (00422fbc)
0040D812 call printf (00401130)
0040D817 add esp,4
0040D81A jmp $L550+1Ch (0040d8a4)
$L536:
0040D81F push offset string "102" (00422fb8)
0040D824 call printf (00401130)
0040D829 add esp,4
0040D82C jmp $L550+1Ch (0040d8a4)
$L538:
0040D82E push offset string "103" (00422fb4)
0040D833 call printf (00401130)
0040D838 add esp,4
0040D83B jmp $L550+1Ch (0040d8a4)
$L540:
0040D83D push offset string "104" (00422fb0)
0040D842 call printf (00401130)
0040D847 add esp,4
0040D84A jmp $L550+1Ch (0040d8a4)
$L542:
0040D84C push offset string "105" (00422fac)
0040D851 call printf (00401130)
0040D856 add esp,4
0040D859 jmp $L550+1Ch (0040d8a4)
$L544:
0040D85B push offset string "106" (00422f5c)
0040D860 call printf (00401130)
0040D865 add esp,4
0040D868 jmp $L550+1Ch (0040d8a4)
$L546:
0040D86A push offset string "107" (00422028)
0040D86F call printf (00401130)
0040D874 add esp,4
0040D877 jmp $L550+1Ch (0040d8a4)
$L548:
0040D879 push offset string "108" (00422024)
0040D87E call printf (00401130)
0040D883 add esp,4
0040D886 jmp $L550+1Ch (0040d8a4)
$L550:
0040D888 push offset string "109" (00422020)
0040D88D call printf (00401130)
0040D892 add esp,4
0040D895 jmp $L550+1Ch (0040d8a4)
0040D897 push offset string "6" (0042201c)
0040D89C call printf (00401130)
说明ja 指令 jump above,大于时跳转(无符号),也就是比较参数x-1和3(case中的最大差值),最大差值就是最大值减最小值

得出的结论会给生成一个大表来直接查询
我们假如把case里面的值删除两个项会发生什么变化
#include<stdio.h>
#include "stdafx.h"
void test(int x)
{
switch(x)
{
case 100:
printf("100");
break;
case 103:
printf("103");
break;
case 104:
printf("104");
break;
case 105:
printf("105");
break;
case 106:
printf("106");
break;
case 107:
printf("107");
break;
case 108:
printf("108");
break;
case 109:
printf("109");
break;
default:
printf("5");
break;
}
}
int main(int argc, char* argv[])
{
test(106);
return 0;
}


总结删除两个时,编译器仍然生成大表来存储,没有case的值 会存储默认的地址
当删除到6个时编译器会帮我们创建小表
#include<stdio.h>
#include "stdafx.h"
void test(int x)
{
switch(x)
{
case 100:
printf("100");
break;
case 107:
printf("107");
break;
case 108:
printf("108");
break;
case 109:
printf("109");
break;
default:
printf("5");
break;
}
}
int main(int argc, char* argv[])
{
test(106);
return 0;
}






小表用来存放并不存在的case,然后通过大表来寻找到default
case后面常量表达式改成好不连续的值
#include<stdio.h>
#include "stdafx.h"
void test(int x)
{
switch(x)
{
case 1:
printf("100");
break;
case 5:
printf("107");
break;
case 200:
printf("108");
break;
case 9:
printf("109");
break;
case 300:
printf("109");
break;
default:
printf("5");
break;
}
}
int main(int argc, char* argv[])
{
test(103);
return 0;
}

------------恢复内容结束------------
Swithch反汇编(四种)的更多相关文章
- C++中四种类型转换以及const_cast是否能改变常量的问题
we have four specific casting operators:dynamic_cast, reinterpret_cast, static_cast and const_cast. ...
- 两个变量交换的四种方法(Java)
对于两种变量的交换,我发现四种方法,下面我用Java来演示一下. 1.利用第三个变量交换数值,简单的方法. (代码演示一下) class TestEV //创建一个类 { public static ...
- Android开发之基本控件和详解四种布局方式
Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方 ...
- TCP四种计时器
TCP共使用以下四种计时器,即重传计时器.坚持计时器.保活计时器和时间等待计时器 .这几个计时器的主要特点如下: 1.重传计时器 当TCP发送报文段时,就创建该特定报文段的重传计时 ...
- C++四种类型转换方式。
类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,比 ...
- C#批量插入数据到Sqlserver中的四种方式
我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...
- 织梦DedeCMS模板防盗的四种方法
织梦(DedeCMS)模板也是一种财富,不想自己辛辛苦苦做的模板被盗用,在互联网上出现一些和自己一模一样的网站,就需要做好模板防盗.本文是No牛收集整理自网络,不过网上的版本都没有提供 Nginx 3 ...
- 四种比较简单的图像显著性区域特征提取方法原理及实现-----> AC/HC/LC/FT。
laviewpbt 2014.8.4 编辑 Email:laviewpbt@sina.com QQ:33184777 最近闲来蛋痛,看了一些显著性检测的文章,只是简单的看看,并没有深入的研究,以 ...
- 像画笔一样慢慢画出Path的三种方法(补充第四种)
今天大家在群里大家非常热闹的讨论像画笔一样慢慢画出Path的这种效果该如何实现. 北京-LGL 博客号@ligl007发起了这个话题.然后各路高手踊跃发表意见.最后雷叔 上海-雷蒙 博客号@雷蒙之星 ...
- 让一个图片在div中居中(四种方法)
第一种方法: <div class="title"> <div class="flag"></div> <div cl ...
随机推荐
- Python变量的数据类型
主要内容 jupyter notebook的用法 变量 跟vi/vim的编辑模式很像 # 声明的三种格式 # 格式1 s1 = "我爱王晓静" # 格式2 s2 = s1 = &q ...
- Python 函数传递任意数量的实参
函数传递任意数量的实参 *形参名,形参名中的星号让python创建了一个空元组,并将收到的所有值都封装到这个元组中 # 案例 *toppings 形参名中的星号让python创建了一个空元组,并将收到 ...
- [Pytorch框架] 2.1.1 PyTorch 基础 : 张量
文章目录 PyTorch 基础 : 张量 张量(Tensor) 基本类型 Numpy转换 设备间转换 初始化 常用方法 PyTorch 基础 : 张量 在第一章中我们已经通过官方的入门教程对PyTor ...
- MySQL事务和锁实战篇
文章目录 MySQL事务和锁 事务 事务的控制语句 事务隔离级别设置 脏读 不可重复读 幻读 锁机制 InnoDB的行级锁 锁实战 死锁 总结 MySQL事务和锁 事务 说到关系型的数据库的事务,相信 ...
- SignalR服务端及客户端实现
服务器端: 引用nuget: 1.Microsoft.AspNet.SignalR.SelfHost 2.Microsoft.Owin.Cors internal class Program { st ...
- ESlint配置详解
开发中出现eslint提示代码格式错误,有时候不明白其配置规范,是件很头疼的事情到处找api又是半天:so记录一份配置详情便于开发中翻阅 { // 环境定义了预定义的全局变量. "env&q ...
- web自动化04-css定位
css元素定位 1. 是什么? 用来描述html元素的显示样式 选择器是一种模式,用于选择需要添加样式的元素 selenium中推荐使用css定位,比XPath定位要快 2.如何定位? ...
- react中useRef的应用
何为useRef useRef是随着react函数式组件发展而来的,是react众多官方hook中的一个,调用useRef可以返回一个伴随这组件整个声明周期不发生改变的对象,这个对象常见的用途有两个: ...
- javaer你还在手写分表分库?来看看这个框架怎么做的 干货满满
java orm框架easy-query分库分表之分表 高并发三驾马车:分库分表.MQ.缓存.今天给大家带来的就是分库分表的干货解决方案,哪怕你不用我的框架也可以从中听到不一样的结局方案和实现. 一款 ...
- logging 模块因权限问题写入日志失败
哈喽大家好,我是咸鱼 今天跟大家分享一个使用 Python 的 logging 模块写入日志文件时遇到的权限问题,不知道你们有没有遇到过 1.案例现象 今天上班的时候手机短信收到了 zabbix 告警 ...