条件判断语句:
条件判断的汇编指令转换成C代码后,条件是相反的。
判断是单分支、多分支、循环:
先找到跳转地址,再看跳转地址的上一条指令是否为跳转,如果不是,则为单分支,如果是,则看跳转的指令是上跳还是下跳,如果是上跳,则是循环,如果是下跳,则是多分支。
If/else/if
1.1 单分支
1.2 多分支
更多的分支,与上面情况类似:
2.使用IDA(静态反汇编工具)打开该程序,从main函数开始:
DEBUG版下对应的for循环:
Switch多分支结构:
1、switch语句块不超过3条:
编译器不会建表查询,但是又和if...else多分支结构
有很大区别。
If...else..if结构会在条件跳转后紧跟语句块
而switch结构则将所有的条件跳转都放在一起
原因在于如果case语句块中没有break语句时,则是按顺序执行后续case语句块
2、switch语句块为一个有序序列:
编译器为case语句制作一份case地址数组
保存每个case语句块的首地址,数组下标以0开始
最小值以0对齐,如果最小值不为0则需要进行调整,再进行第一次比较时,判断输入数值是否大于case值最大值,如果是,则跳到switch末尾
3、索引优化:
对于非线性结构,会采用索引表来优化,需要建立两张表,1张为case语句块地址表,另一张为case语句块索引表。
索引表保存的地址编号,大小为最大case值和最小case值的差,当差值大于255时,也会浪费空间
4、树方式优化:
当差值大于255时,超出1字节表达范围时,会采用判定树优化。
将每个case值作为一个节点,从这些节点中找到一个中间值作为根节点,形成一棵平衡二叉树,以每个节点为判定值,大于和小于分别对应左子树和右子树。
3.1 case分支不大于三,仿照if/else
3.2 case分支大于3,且相邻case差值小于6,进行线性查表
首先调整最小case,对齐到0
根据最大case,设定边界
各case函数指针够成表,通过查表定位。
上面是case值连续的情况。
当相邻两case(指大小相邻)间差值小于6时,仍然采用同样的方法。
3.3 case分支数大于4,且相邻case差值大于6,采用双表查询
其中一个表用于存储函数指针(其数量较少)
另一表用于存储各case的函数指针在上表中的下标(单字节,为case_min ~ case_max)
3.4 case分支大于4,且相邻case差值大于6,且case处于稀疏状态,采用平衡树
整体上,取其中值,左右平衡比较,以此类推。
特殊的,各左右部分根据实际情况采用之前的if/else方法或者线性查表或者双表查询。