Switch

来源:互联网 发布:js设置fps 编辑:程序博客网 时间:2024/06/08 01:23

在 switch 的反汇编中,最典型的是,在跳转之间并无实质性功能的代码

Switch 情况一

case 的数量小于等于 3
int main(int argc, char* argv[]){    switch (argc)    {    case 1:        printf("1\r\n");        break;    case 2:        printf("1\r\n");        break;    case 3:        printf("1\r\n");        break;    }    return 0;}

会产生一张引导性的跳转表,引导到正确的代码块中。 如果在 switch 中有 default ,那么最后一条指令 jmp 跳转到 default 块中;如果没有 default,则跳出 switch 块中。

这里写图片描述

Switch 情况二

case 的数量大于 3,间隔值不大
int main(int argc, char* argv[]){    switch (argc)    {    case -2:        printf("1\r\n");        break;    case -1:        printf("2\r\n");        break;    case 2:        printf("3\r\n");        break;    case 3:        printf("5\r\n");        break;    case 5:        printf("6\r\n");        break;    default:        printf("Default\r\n");    }    return 0;}

编译器会做一张表,然后调整传入值,再根据调整后的值寻址。调整的值,是加上,将 case 中的最小值调整为 0 的值。如上面的代码中,case 的最小值为 -2,那么调整值就是 2。

假设 case 的最小值为 2,那么调整值为 -2

编译器形成表时,如果 case标号case标号 之间不连续,中间会填充跳转到 default 的地址(如果 switch 中没有 default,那么会填充跳出 switch 块的地址)。生成的汇编代码如下:

这里写图片描述

这里写图片描述

Switch 情况三

 
case 的最大值 - case 的最小值 <= 255,没有明显的顺序

int main(int argc, char* argv[]){    switch (argc)    {    case 8:        printf("1\r\n");        break;    case 3:        printf("2\r\n");        break;    case 34:        printf("3\r\n");        break;    case -54:        printf("5\r\n");        break;    case 100:        printf("6\r\n");        break;    default:        printf("Default\r\n");    }    return 0;}

编译器会建立 2 张表,一张表的作用类似于 调色板 ,第二张表存放跳转的地址。根据第一张表,可以定位到第二张表的位置。比如,在第一张表定位到的位置是数组的第一项,这项中的值为 0,那么就根据 0,再定位到第二张表中的数组中的第一项(数组下标从 0 开始)。

调色板的概念,是为了解决位图文件存储空间过大的问题。在 “真彩色”图片中,一个像素中的颜色需要 4 个字节来存储。但实际上,一张图片往往不需要用到所有颜色,造成了空间上的浪费。如果做一张表,表中存放一张图片中需要用到的颜色的索引,那么,要表示一个像素中的颜色,只要指向这张表的的索引即可。这张表,即是所谓的 调色板

这里写图片描述

这里写图片描述

Switch 情况四

case 的最大值 - case 的最小值 > 255,没有明显的顺序
int main(int argc, char* argv[]){    switch (argc)    {    case 1:        printf("1\r\n");        break;    case 555:        printf("2\r\n");        break;    case -33:        printf("3\r\n");        break;    case 444:        printf("5\r\n");        break;    case 333:        printf("6\r\n");        break;    default:        printf("Default\r\n");    }    return 0;}

使用类似二分法的查找方法,从 case 的中间值开始查找。

这里写图片描述

此时 switch 假设各个情况的命中率是相同的。如果某种情况的命中率特别高,推荐使用 if…else…