老码识途 switch机制

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了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值