------------恢复内容开始------------

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反汇编(四种)的更多相关文章

  1. C++中四种类型转换以及const_cast是否能改变常量的问题

    we have four specific casting operators:dynamic_cast, reinterpret_cast, static_cast and const_cast. ...

  2. 两个变量交换的四种方法(Java)

    对于两种变量的交换,我发现四种方法,下面我用Java来演示一下. 1.利用第三个变量交换数值,简单的方法. (代码演示一下) class TestEV //创建一个类 { public static ...

  3. Android开发之基本控件和详解四种布局方式

    Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方 ...

  4. TCP四种计时器

    TCP共使用以下四种计时器,即重传计时器.坚持计时器.保活计时器和时间等待计时器 .这几个计时器的主要特点如下:      1.重传计时器      当TCP发送报文段时,就创建该特定报文段的重传计时 ...

  5. C++四种类型转换方式。

    类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,比 ...

  6. C#批量插入数据到Sqlserver中的四种方式

    我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...

  7. 织梦DedeCMS模板防盗的四种方法

    织梦(DedeCMS)模板也是一种财富,不想自己辛辛苦苦做的模板被盗用,在互联网上出现一些和自己一模一样的网站,就需要做好模板防盗.本文是No牛收集整理自网络,不过网上的版本都没有提供 Nginx 3 ...

  8. 四种比较简单的图像显著性区域特征提取方法原理及实现-----> AC/HC/LC/FT。

    laviewpbt  2014.8.4 编辑 Email:laviewpbt@sina.com   QQ:33184777 最近闲来蛋痛,看了一些显著性检测的文章,只是简单的看看,并没有深入的研究,以 ...

  9. 像画笔一样慢慢画出Path的三种方法(补充第四种)

    今天大家在群里大家非常热闹的讨论像画笔一样慢慢画出Path的这种效果该如何实现. 北京-LGL 博客号@ligl007发起了这个话题.然后各路高手踊跃发表意见.最后雷叔 上海-雷蒙 博客号@雷蒙之星 ...

  10. 让一个图片在div中居中(四种方法)

    第一种方法: <div class="title"> <div class="flag"></div> <div cl ...

随机推荐

  1. js-函数记忆

    函数记忆: 指将上次的(计算结果)缓存起来,当下次调用时,如果遇到相同的(参数),就直接返回(缓存中的数据). 实现原理:将参数和对应的结果保存在对象中,再次调用时,判断对象 key 是否存在,存在返 ...

  2. 执行sql报lock wait timeout exceeded; try restarting transaction

    mysql查询时候报错: Lock wait timeout exceeded; try restarting transaction 译文:锁等待超时;试着重新启动事务 被锁了,需要解锁. 1.in ...

  3. gRPC 应用指引

    一.核心概念.架构及生命周期 1.服务定义 gRPC 默认使用 protocol buffers. service HelloService { rpc SayHello (HelloRequest) ...

  4. xcode历史版本下载

    一.背景 较早之前做过一个项目,当时使用swift 3.x开发. 项目结束后就没再有新需求与更新. 但最近呢需要对项目的某些功能进行调整,项目又重新被拾了起来. 我们知道现在的swift 版本已经到了 ...

  5. VS 查看引用的DLL/Nuget包源码时,无法看到注释

    一.问题描述 在下面的截图中,我们发现,源码有添加一段注释. 然后通过Nuget包引用,在VS中用Reshaper反编译时,发现没有注释: 原来,DLL是默认不带注释的.即你生成一个DLL,给另一个项 ...

  6. c语言中的链接属性和存储类型

    链接属性 external属性: 不在代码块中的函数和变量在缺省情况下都属于external链接属性. 具有external属性的变量或者函数在其他源文件中无论被包含多少次,都指向同一个实体. #a. ...

  7. [UR #14]人类补完计划

    计数好题. 题意:给定简单无向图 \(G=(V,E),|V|=n,|E|=m\),有 \(n\leq 16,m\leq {n\choose 2}\),求所有为基环树的子图的权值之和.一个基环树的权值定 ...

  8. map和multimap

    map相对于set区别,map具有键值和实值,所有元素根据键值自动排序,pair的第一个值被称为键值key,pair的第二个值被称为实值value.map也是以红黑树为底层实现机制,根据key进行排序 ...

  9. 在vue标签代码块中定义变量

    方式一: 在标签上使用:set关键字,不管什么标签都可以 <template> <h1>test</h1> <template :set="firs ...

  10. ClickHouse笔记: Ubuntu/Centos下的安装, 配置和用户管理

    ClickHouse ClickHouse 属于 OLAP 数据库 OLTP 与 OLAP OLTP (On-Line Transaction Processing 联机事务处理), 注重事务处理, ...