老码识途 switch机制

来源:互联网 发布:手机淘宝详情页尺寸 编辑:程序博客网 时间:2024/04/29 15:20

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],14h6: switch(flag)7: {0040158F 8B 45 FC mov eax,dword ptr [ebp-4]00401592 89 45 F8 mov dword ptr [ebp-8],eax00401595 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],ecx0040159E 83 7D F8 03 cmp dword ptr [ebp-8],4//大于最后一个则跳到default004015A2 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 eax004015B2 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,810: 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 ecx004015C5 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,8004015D2 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 edx004015D8 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 eax004015ED 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,eax004015F9 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 600401607 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,eax00401613 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 edi00401619 5E pop esi0040161A 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],14h6: switch(flag)7: {0040158F 8B 45 FC mov eax,dword ptr [ebp-4]00401592 89 45 F8 mov dword ptr [ebp-8],eax00401595 8B 4D F8 mov ecx,dword ptr [ebp-8]00401598 83 E9 02 sub ecx,20040159B 89 4D F8 mov dword ptr [ebp-8],ecx0040159E 83 7D F8 3A cmp dword ptr [ebp-8],3Ah004015A2 77 64 ja $L7390+1Ch (00401608)004015A4 8B 45 F8 mov eax,dword ptr [ebp-8]004015A7 33 D2 xor edx,edx004015A9 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],14h6: switch(flag)7: {0040158F 8B 45 FC mov eax,dword ptr [ebp-4]00401592 89 45 F8 mov dword ptr [ebp-8],eax00401595 83 7D F8 32 cmp dword ptr [ebp-8],32h00401599 7F 14 jg main+3Fh (004015af)0040159B 83 7D F8 32 cmp dword ptr [ebp-8],32h0040159F 74 3F je main+70h (004015e0)004015A1 83 7D F8 02 cmp dword ptr [ebp-8],2004015A5 74 13 je main+4Ah (004015ba)004015A7 83 7D F8 28 cmp dword ptr [ebp-8],28h004015AB 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],258h004015B6 74 38 je main+80h (004015f0)004015B8 EB 52 jmp main+9Ch (0040160c)

相当于if else了

0 0
原创粉丝点击