flag稠密时的switch算法:
1:i=flag-n;n=case分支中最小的整数;
2: if i>num jmp default;num=case 分支max-min;即中间数个数-1(无须比较小于是因为当小于是,i<0;存在计算机中为负数,无符号比较会大于num);
3:跳转到address[i]中存储的地址。address是预先准备好的数组,其中存储了对应case分支的起始地址
flag稀疏时的switch算法:增加了地址索引表
1:i=flag-min;min=case分支中最小的整数;
2:if(i>max-min)则跳到default(用ja无符号比较);
3:否则addIndex=Index[i];
4:jmp address[addIndex];
再稀疏的话则相当于if else

#include <iostream>
using namespace std;
int main(int n,char **s)
{int flag=20;switch(flag){case 2:printf("%d",&flag);break;case 4:printf("%d",flag);break;case 5:cout<<flag;break;case 6:cout<<&flag<<endl;break;default:cout<<6<<endl;break;}
}
汇编代码:
int flag=20;
00401588 C7 45 FC 14 00 00 00 mov dword ptr [ebp-4],14h
6: switch(flag)
7: {
0040158F 8B 45 FC mov eax,dword ptr [ebp-4]
00401592 89 45 F8 mov dword ptr [ebp-8],eax
00401595 8B 4D F8 mov ecx,dword ptr [ebp-8]
00401598 83 E9 03 sub ecx,2//减去第一个的大小,
0040159B 89 4D F8 mov dword ptr [ebp-8],ecx
0040159E 83 7D F8 03 cmp dword ptr [ebp-8],4//大于最后一个则跳到default
004015A2 77 5C ja $L7390+1Ch (00401600) //ja=大于就跳
004015A4 8B 55 F8 mov edx,dword ptr [ebp-8]
004015A7 FF 24 95 29 16 40 00 jmp dword ptr [edx*4+401629h] //跳到case处,edx*4是偏移地址
8: case 2:
9: printf("%d",&flag);
004015AE 8D 45 FC lea eax,[ebp-4]
004015B1 50 push eax
004015B2 68 1C C0 46 00 push offset string "%d" (0046c01c)
004015B7 E8 C4 F2 01 00 call printf (00420880)
004015BC 83 C4 08 add esp,8
10: break;
004015BF EB 57 jmp $L7390+34h (00401618)
11: case 4:
12: printf("%d",flag);break;
004015C1 8B 4D FC mov ecx,dword ptr [ebp-4]
004015C4 51 push ecx
004015C5 68 1C C0 46 00 push offset string "%d" (0046c01c)
004015CA E8 B1 F2 01 00 call printf (00420880)
004015CF 83 C4 08 add esp,8
004015D2 EB 44 jmp $L7390+34h (00401618)
13: case 5:
14: cout<<flag;break;
004015D4 8B 55 FC mov edx,dword ptr [ebp-4]
004015D7 52 push edx
004015D8 B9 F0 77 47 00 mov ecx,offset std::cout (004777f0)
004015DD E8 22 FB FF FF call @ILT+255(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401104)
004015E2 EB 34 jmp $L7390+34h (00401618)
15: case 6:
16: cout<<&flag<<endl;break;
004015E4 68 CD 10 40 00 push offset @ILT+200(std::endl) (004010cd)
004015E9 8D 45 FC lea eax,[ebp-4]
004015EC 50 push eax
004015ED B9 F0 77 47 00 mov ecx,offset std::cout (004777f0)
004015F2 E8 4A FA FF FF call @ILT+60(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401041)
004015F7 8B C8 mov ecx,eax
004015F9 E8 E7 FB FF FF call @ILT+480(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e5)
004015FE EB 18 jmp $L7390+34h (00401618)
17: default:
18: cout<<6<<endl;
00401600 68 CD 10 40 00 push offset @ILT+200(std::endl) (004010cd)
00401605 6A 06 push 6
00401607 B9 F0 77 47 00 mov ecx,offset std::cout (004777f0)
0040160C E8 F3 FA FF FF call @ILT+255(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401104)
00401611 8B C8 mov ecx,eax
00401613 E8 CD FB FF FF call @ILT+480(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e5)
19: break;
20: }
21: }
00401618 5F pop edi
00401619 5E pop esi
0040161A 5B pop ebx

稀疏:

#include <iostream>
using namespace std;
int main(int n,char **s)
{int flag=20;switch(flag){case 2:printf("%d",&flag);break;case 40:printf("%d",flag);break;case 50:cout<<flag;break;case 60:cout<<&flag<<endl;break;default:cout<<6<<endl;break;}
}
5: int flag=20;
00401588 C7 45 FC 14 00 00 00 mov dword ptr [ebp-4],14h
6: switch(flag)
7: {
0040158F 8B 45 FC mov eax,dword ptr [ebp-4]
00401592 89 45 F8 mov dword ptr [ebp-8],eax
00401595 8B 4D F8 mov ecx,dword ptr [ebp-8]
00401598 83 E9 02 sub ecx,2
0040159B 89 4D F8 mov dword ptr [ebp-8],ecx
0040159E 83 7D F8 3A cmp dword ptr [ebp-8],3Ah
004015A2 77 64 ja $L7390+1Ch (00401608)
004015A4 8B 45 F8 mov eax,dword ptr [ebp-8]
004015A7 33 D2 xor edx,edx
004015A9 8A 90 45 16 40 00 mov dl,byte ptr (00401645)[eax]
004015AF FF 24 95 31 16 40 00 jmp dword ptr [edx*4+401631h]//跳转到跳转表,每个地址1个字节,59*1+(4+1)*4=79B ;
否则(59+1)*4=240B

再稀疏:

#include <iostream>
using namespace std;
int main(int n,char **s)
{int flag=20;switch(flag){case 2:printf("%d",&flag);break;case 40:printf("%d",flag);break;case 50:cout<<flag;break;case 600:cout<<&flag<<endl;break;default:cout<<6<<endl;break;}
}

则:

       int flag=20;
00401588 C7 45 FC 14 00 00 00 mov dword ptr [ebp-4],14h
6: switch(flag)
7: {
0040158F 8B 45 FC mov eax,dword ptr [ebp-4]
00401592 89 45 F8 mov dword ptr [ebp-8],eax
00401595 83 7D F8 32 cmp dword ptr [ebp-8],32h
00401599 7F 14 jg main+3Fh (004015af)
0040159B 83 7D F8 32 cmp dword ptr [ebp-8],32h
0040159F 74 3F je main+70h (004015e0)
004015A1 83 7D F8 02 cmp dword ptr [ebp-8],2
004015A5 74 13 je main+4Ah (004015ba)
004015A7 83 7D F8 28 cmp dword ptr [ebp-8],28h
004015AB 74 20 je main+5Dh (004015cd)
004015AD EB 5D jmp main+9Ch (0040160c)
004015AF 81 7D F8 58 02 00 00 cmp dword ptr [ebp-8],258h
004015B6 74 38 je main+80h (004015f0)
004015B8 EB 52 jmp main+9Ch (0040160c)

相当于if else了

老码识途 switch机制相关推荐

  1. 老码识途:从机器码到框架的系统观逆向修炼之路 pdf电子书

    重要提示尊敬的用户您好,由于老码识途:从机器码到框架的系统观逆向修炼之路pdf书受百度网盘影响无法做公共分享,只能私密分享,有不到之处请多多谅解! 百度网盘链接: http://pan.baidu.c ...

  2. 《老码识途》读书笔记:第一章(上)

    <老码识途>读书笔记:第一章--欲向码途问大道,锵锵bit是吾刀(上)   1.赋值语句 对于全局变量赋值语句,例如下面这句: 1 int gi; 2 void main(int argc ...

  3. 老码识途学习笔记(一)

    第一章 全局变量引发的故事 1 程序存储区 程序存储区一般有下列几段: 程序代码区(SECTION.txt ): 用来存放可执行文件的操作指令(二进制),也就是说是它是可执行程序在内存中的镜像.代码段 ...

  4. 《老码识途:从机器码到框架的系统观逆向修炼之路》- 第1章 - 总结

    本章学到了什么 调试技巧:在VS中断点调试,查看反汇编代码,step into进行步进调试,运行过程中查看寄存器.内存地址.变量值变化等. 机器码构造能力:使用C/C++中的直接在C代码里写汇编语言的 ...

  5. 老码识途——在堆中构建mov和jmp指令

    // asmjmp.cpp : 定义控制台应用程序的入口点. // #include <stdio.h> #include <malloc.h>int gi; void * a ...

  6. 老码识途读书笔记 1

    知识点记录: 1.int 或指针类型的全局变量默认初始化为0,局部变量则为0xcccccccc.(win7 + vs2008 ) 2.内存溢出攻击即使用6个字节空间改变程序执行流程达到某种目的.话说当 ...

  7. 老码识途之对象函数调用

    上一期,我们讨论了普通函数的调用过程,如果没弄明白,看这里 今天所要讲的将是对象调用函数. class C{public:int a;int b;int c;void f(int t){a = t;} ...

  8. 老码识途之构造函数和析构函数

    对象初始化过程就是先父类构造函数,再子类构造函数.,那么我们从汇编角度去探索这个过程是怎么样的 class P{public:int a ;P(){a = 1;}~P(){a = 4;} };clas ...

  9. 读书 --- 老码识途

    上周在图书馆借了这本书,这个周末细看了下,是本好书.作者应该是个大学教授叫韩宏.书中讲的很底层,一开始就告诉大家如何debug一段程序,在VS2008里面查看内存.寄存器.反汇编.通过这些来认识汇编. ...

最新文章

  1. 使用结构体输出员工工资表
  2. Apache+php+tomcat+mysql整合手册
  3. Android开发之dp转像素,像素转换为dp工具类,详细代码,带有源文件下载地址。...
  4. 基于redis的cas集群配置(转)
  5. 软件工程师的职业生涯
  6. python学习之老男孩python全栈第九期_day004知识点总结
  7. leetcode 413. Arithmetic Slices | 413. 等差数列划分(Java)
  8. 使用此首选项可加快Eclipse m2e配置
  9. Frida Android hook
  10. 矩阵分析理论在实际工程中的应用_【顶管技术在市政给排水工程中的应用分析】...
  11. lg手机历史机型_LG手机业务亏损增加70% 宣称主因是国产品牌卖的太便宜
  12. http 二进制_图解 HTTP 的前世今生!
  13. 10蓝牙_小米10手机专用?小米“真无线蓝牙耳机Air 2s”评测
  14. dubbo学习(八)dubbo项目搭建--消费者(服务消费者)
  15. javascript 编程指南
  16. Fis3的前端工程化之路[三大特性篇之内容嵌入]
  17. 故障转移群集 SQLSERVER解决方案
  18. C语言·数组·密码编译(阿斯克码法)
  19. 【C语言】 C语言图形编程 俄罗斯方块 课程设计
  20. python如何设计系统界面教程_python图形化界面设计tkinter!python用户界面设计教程...

热门文章

  1. splice和slice的使用
  2. 态℃|非洲之王传音回国上市 加固护城河
  3. URP自定义屏幕后处理
  4. WPS应用之下拉列表 和 多级下拉列表联动
  5. Instruments的一点使用心得
  6. tsm linux 错误日志,TSM linux oracle安装
  7. smart原则_如何建立学习目标:这个SMART原则,你要了解,家长看懂教给孩子
  8. Linux内核TC工具链路带宽设计--HTB队列规定及简单的过滤器介绍
  9. 梦幻优化服务器,云风的 BLOG
  10. 腾讯CDC团队:前端异常监控解决方案