switch反汇编自学过程中的总结:
例子: 随便写一个3个case的switch,查看汇编。
void function()
{
int i = 0;
switch (i)
{
case 1:
printf("1");
break;
case 2:
printf("2");
break;
case 3:
printf("3");
break;
default:
printf("error");
break;
}
}
看得出与if的反汇编并无差别,并且挨个判断。所以如果没有3个以上的case条件可不必要使用switch。
修改一下例子:
void function()
{
int i = 0;
switch (i)
{
case 1:
printf("1");
break;
case 2:
printf("2");
break;
case 3:
printf("3");
break;
case 4:
printf("4");
break;
case 5:
printf("5");
break;
default:
printf("error");
break;
}
}
反汇编代码:
其中0x6A1918 是编译器为switch生成的表的第一个地址。
这就是生成的大表。
ecx为判断的变量的值。
sub ecx,1
减1中的‘1’是和
cmp dword ptr [ebp-0D0h],4
中的‘4’加起来为case中最大的判断值。
jmp dword ptr [edx*4+6D1918h]
为跳转地址计算公式,dex*4中dex可以理解为偏移量(switch表)。即可直接跳转到目的地址(下一条指令)。
以上为一般(规范)switch。
!!!!!以下是不连续,乱序,差量过大的情况:
void function()
{
int i = 102;
switch (i)
{
case 102:
printf("102");
break;
case 1:
printf("1");
break;
case 2:
printf("2");
break;
case 3:
printf("3");
break;
case 4:
printf("4");
break;
case 101:
printf("101");
break;
case 104:
printf("104");
break;
default:
printf("error");
break;
}
}
当差距过大此编译器为再生成一个表上右图来计算(
movzx eax,byte ptr [edx+68195Ch]
)eax的值
生成了104字节的表。再通过eax的值得到偏移后的跳转地址。
总结:
switch适合于小量连续的判断条件。(生成的表不会浪费空间)