switch语句的反汇编
switch语句反汇编的几种形式
0x00
当case后面的常量较少时:
switch (x) { case 1: printf("1"); break; case 2: printf("2"); break; case 3: printf("3"); break; default: printf("error"); break; }
下面为它的汇编代码


可见,当常量减少时,switch的判断类似于if else语句,但不同的是,switch的判断都是集中在一起,而功能放在另一块地方,所以switch要与break一起使用
0x01
当case后面的常量较多且较连续时
switch (x) { 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; case 6: printf("6"); break; case 7: printf("7"); break; case 8: printf("8"); break; default: printf("error"); break; }
以下为它的汇编代码

这时候就有了switch的大表,编译器将整形变量x减去case后最小的常量1,并存储在edx中,通过一个确定的地址加上偏移确定应该转移的地址

如果去掉case 3和case 4,此时的大表发生了变化
3和4所对应的内存中存储了0x00401a70,这正是default所在的地址,也就是说当常量间隔的不多时,编译器仍然会使用大表。
0x11
当case后的常量连续但间隔过多的时候,此时出现了小表来配合大表使用,目的是为了节省空间
小表 大表

小表将出现的常量1~11对应的偏移都存储在内存中,每个占据一个字节,而大表中省去了因为间隔而浪费的多个双字的内存单元,因此实现了节省空间
例如,常量1在小表中对应的0x00,存储在eax中,因此在大表中对应的是0x008b1a1d;常量2在小表中对应的是0x05,存储在eax中,因此在大表中对应的是0x008b1a68,即default所在的地址。

浙公网安备 33010602011771号