Switch的識別

1.if else模式:case語句塊不超過3條
通過O2優化後的代碼來看, if else if 結構會在條件跳轉後緊跟語句塊,而switch結構則將所有的條件跳轉都放在一起。
特徵1:

sub eax,case1
je  add1
sub eax,case2
je  add2
sub eax,case3
jne addend

特徵2:

語句
mov esp,ebp
pop ebp
ret
語句
mov esp,ebp
pop ebp
ret
語句
mov esp,ebp
pop ebp
ret

2.線性結構模式:每兩個case間的差值小於7
特徵1:LastBreakAdd和TableAdd捱得較近 且 特徵2的地址中會包括LastBreakAdd

dec eax
cmp eax,CaseMax-1
ja  LastBreakAdd
jmp [eax*4+TableAdd]

特徵2:代碼段中出現,連續增大,偶有出現LastBreakAdd

地址
地址
地址
地址 
……

3.地址表模式:兩個相鄰case間的差值大於6,CaseMax<256
特徵1:

dec eax
cmp eax,CaseMax-1
ja  LastBreakAdd
movzx   eax, byte[eax+IndexTableAdd]
jmp [eax*4+TableAdd]

特徵2:連續增大的地址塊無逆序,索引塊以IndexMax爲主導,間有從0到IndexMax-1的依次增大的自然數

地址塊 
索引塊

4.判定樹模式:CaseMax>255 又稱混合模式 子樹優化優先
特徵1:

cmp     eax,Middle
jg      RightTreeAdd
je      MiddleAdd
add     eax, balance
cmp     eax,LeftMax-blance
jg      LastBreakAdd
jmp     AddTable

特徵2:

同時見前三種模式特徵中的兩到三種。
if模式
void test_switch_if()
{
00408320 55                   push        ebp  
00408321 8B EC                mov         ebp,esp  
00408323 51                   push        ecx  
    int i = 1;
    scanf("%d", &i);
00408324 8D 45 FC             lea         eax,[i]  
00408327 C7 45 FC 01 00 00 00 mov         dword ptr [i],1  
0040832E 50                   push        eax  
0040832F 68 50 CE 4A 00       push        offset string "%d" (04ACE50h)  
00408334 E8 67 B0 FF FF       call        _scanf (04033A0h)  
    switch(i){
00408339 8B 45 FC             mov         eax,dword ptr [i]  
0040833C 83 C4 08             add         esp,8  
0040833F 83 E8 01             sub         eax,1  
00408342 74 2C                je          test_switch_if+50h (0408370h)  
00408344 83 E8 02             sub         eax,2  
00408347 74 16                je          test_switch_if+3Fh (040835Fh)  
00408349 83 E8 61             sub         eax,61h  
0040834C 75 2F                jne         test_switch_if+5Dh (040837Dh)  
    case 100:
        printf("i == 100");
0040834E 68 64 CE 4A 00       push        offset string "i == 100" (04ACE64h)  
00408353 E8 B6 BF FF FF       call        _printf (040430Eh)  
00408358 83 C4 04             add         esp,4  
        break;
0040835B 8B E5                mov         esp,ebp  
0040835D 5D                   pop         ebp  
0040835E C3                   ret   
    case 3:
        printf("i == 3");
0040835F 68 5C CE 4A 00       push        offset string "i == 3" (04ACE5Ch)  
00408364 E8 A5 BF FF FF       call        _printf (040430Eh)  
00408369 83 C4 04             add         esp,4  
        break;
0040836C 8B E5                mov         esp,ebp  
0040836E 5D                   pop         ebp  
0040836F C3                   ret  
    case 1:
        printf("i == 1");
00408370 68 54 CE 4A 00       push        offset string "i == 1" (04ACE54h)  
00408375 E8 94 BF FF FF       call        _printf (040430Eh)  
0040837A 83 C4 04             add         esp,4  
        break;
0040837D 8B E5                mov         esp,ebp  
0040837F 5D                   pop         ebp  
00408380 C3                   ret  
地址表模式 
void SwitchLine()
{
00408240 55                   push        ebp  
00408241 8B EC                mov         ebp,esp  
00408243 51                   push        ecx  
    int nIndex = 0;
    scanf("%d", &nIndex);
00408244 8D 45 FC             lea         eax,[nIndex]  
00408247 C7 45 FC 00 00 00 00 mov         dword ptr [nIndex],0  
0040824E 50                   push        eax  
0040824F 68 50 CE 4A 00       push        offset string "%d" (04ACE50h)  
00408254 E8 47 B1 FF FF       call        _scanf (04033A0h)  
    switch(nIndex)
00408259 8B 45 FC             mov         eax,dword ptr [nIndex]  
0040825C 83 C4 08             add         esp,8  
0040825F 48                   dec         eax  
00408260 83 F8 06             cmp         eax,6  
00408263 77 69                ja          $LN9+0Dh (04082CEh)  
00408265 FF 24 85 D4 82 40 00 jmp         dword ptr [eax*4+4082D4h]  
    case 1:
        printf("nIndex == 1");
0040826C 68 70 CE 4A 00       push        offset string "nIndex == 1" (04ACE70h)  
00408271 E8 98 C0 FF FF       call        _printf (040430Eh)  
00408276 83 C4 04             add         esp,4  
        break;
00408279 8B E5                mov         esp,ebp  
0040827B 5D                   pop         ebp  
0040827C C3                   ret  
        break;
    case 2:
        printf("nIndex == 2");
0040827D 68 80 CE 4A 00       push        offset string "nIndex == 2" (04ACE80h)  
00408282 E8 87 C0 FF FF       call        _printf (040430Eh)  
00408287 83 C4 04             add         esp,4  
        break;
0040828A 8B E5                mov         esp,ebp  
0040828C 5D                   pop         ebp  
0040828D C3                   ret  
    case 3:
        printf("nIndex == 3");
0040828E 68 90 CE 4A 00       push        offset string "nIndex == 3" (04ACE90h)  
00408293 E8 76 C0 FF FF       call        _printf (040430Eh)  
00408298 83 C4 04             add         esp,4  
        break;
0040829B 8B E5                mov         esp,ebp  
0040829D 5D                   pop         ebp  
0040829E C3                   ret  
    case 5:
        printf("nIndex == 5");
0040829F 68 A0 CE 4A 00       push        offset string "nIndex == 5" (04ACEA0h)  
004082A4 E8 65 C0 FF FF       call        _printf (040430Eh)  
004082A9 83 C4 04             add         esp,4  
        break;
004082AC 8B E5                mov         esp,ebp  
004082AE 5D                   pop         ebp  
004082AF C3                   ret  
    case 6:
        printf("nIndex == 6");
004082B0 68 B0 CE 4A 00       push        offset string "nIndex == 6" (04ACEB0h)  
004082B5 E8 54 C0 FF FF       call        _printf (040430Eh)  
004082BA 83 C4 04             add         esp,4  
        break;
004082BD 8B E5                mov         esp,ebp  
004082BF 5D                   pop         ebp  
004082C0 C3                   ret  
    case 7:
        printf("nIndex == 7");
004082C1 68 C0 CE 4A 00       push        offset string "nIndex == 7" (04ACEC0h)  
004082C6 E8 43 C0 FF FF       call        _printf (040430Eh)  
004082CB 83 C4 04             add         esp,4  
        break;
004082CE 8B E5                mov         esp,ebp  
004082D0 5D                   pop         ebp  
004082D1 C3                   ret  
;nop
004082D2 66 90                xchg        ax,ax  
;下面是case地址塊 不是代碼  VS2015的反彙編搞差了 第一個是 6C 82 40 00 後面跟了另外6個地址
004082D4 6C                   ins         byte ptr es:[edi],dx  
004082D5 82 40 00 7D          add         byte ptr [eax],7Dh  
004082D9 82 40 00 8E          add         byte ptr [eax],8Eh  
004082DD 82 40 00 CE          add         byte ptr [eax],0CEh  
004082E1 82 40 00 9F          add         byte ptr [eax],9Fh  
004082E5 82 40 00 B0          add         byte ptr [eax],0B0h  
004082E9 82 40 00 C1          add         byte ptr [eax],0C1h  
004082ED 82 40 00 CC          add         byte ptr [eax],0CCh 
索引表模式 
void test_switch_nonline()
{
004083A0 55                   push        ebp  
004083A1 8B EC                mov         ebp,esp  
004083A3 51                   push        ecx  
    int i = 0;
    scanf("%d", &i);
004083A4 8D 45 FC             lea         eax,[i]  
004083A7 C7 45 FC 00 00 00 00 mov         dword ptr [i],0  
004083AE 50                   push        eax  
004083AF 68 50 CE 4A 00       push        offset string "%d" (04ACE50h)  
004083B4 E8 E7 AF FF FF       call        _scanf (04033A0h)  
    switch(i){
004083B9 8B 45 FC             mov         eax,dword ptr [i]  
004083BC 83 C4 08             add         esp,8  
004083BF 48                   dec         eax  
004083C0 83 F8 0E             cmp         eax,0Eh  
004083C3 77 70                ja          $LN9+0Dh (0408435h)  
004083C5 0F B6 80 58 84 40 00 movzx       eax,byte ptr [eax+408458h]
;movzx無符號擴展並傳送,用於將字節型索引轉換爲32位   
004083CC FF 24 85 3C 84 40 00 jmp         dword ptr [eax*4+40843Ch]  
    case 1:
        printf("i == 1");
004083D3 68 54 CE 4A 00       push        offset string "i == 1" (04ACE54h)  
004083D8 E8 31 BF FF FF       call        _printf (040430Eh)  
004083DD 83 C4 04             add         esp,4  
        break;
004083E0 8B E5                mov         esp,ebp  
004083E2 5D                   pop         ebp  
004083E3 C3                   ret  
    case 2:
        printf("i == 2");
004083E4 68 D0 CE 4A 00       push        offset string "i == 2" (04ACED0h)  
004083E9 E8 20 BF FF FF       call        _printf (040430Eh)  
004083EE 83 C4 04             add         esp,4  
        break;
004083F1 8B E5                mov         esp,ebp  
004083F3 5D                   pop         ebp  
004083F4 C3                   ret  
    case 3:
        printf("i == 3");
004083F5 68 5C CE 4A 00       push        offset string "i == 3" (04ACE5Ch)  
004083FA E8 0F BF FF FF       call        _printf (040430Eh)  
004083FF 83 C4 04             add         esp,4  
        break;
00408402 8B E5                mov         esp,ebp  
00408404 5D                   pop         ebp  
00408405 C3                   ret  
    case 5:
        printf("i == 5");
00408406 68 D8 CE 4A 00       push        offset string "i == 5" (04ACED8h)  
0040840B E8 FE BE FF FF       call        _printf (040430Eh)  
00408410 83 C4 04             add         esp,4  
        break;
00408413 8B E5                mov         esp,ebp  
00408415 5D                   pop         ebp  
00408416 C3                   ret  
    case 6:
        printf("i == 6");
00408417 68 E0 CE 4A 00       push        offset string "i == 6" (04ACEE0h)  
0040841C E8 ED BE FF FF       call        _printf (040430Eh)  
00408421 83 C4 04             add         esp,4  
        break;
00408424 8B E5                mov         esp,ebp  
00408426 5D                   pop         ebp  
00408427 C3                   ret  
    case 15:
        printf("i == 15");
00408428 68 E8 CE 4A 00       push        offset string "i == 15" (04ACEE8h)  
0040842D E8 DC BE FF FF       call        _printf (040430Eh)  
00408432 83 C4 04             add         esp,4  
        break;
00408435 8B E5                mov         esp,ebp  
00408437 5D                   pop         ebp  
00408438 C3                   ret  
;nop
00408439 0F 1F 00             nop         dword ptr [eax]  
;下面是case地址塊 第一個是00 40 83 D3 
0040843C D3 83 40 00 E4 83    rol         dword ptr [ebx-7C1BFFC0h],cl  
00408442 40                   inc         eax  
00408443 00 F5                add         ch,dh  
00408445 83 40 00 06          add         dword ptr [eax],6  
00408449 84 40 00             test        byte ptr [eax],al  
0040844C 17                   pop         ss  
0040844D 84 40 00             test        byte ptr [eax],al  
00408450 28 84 40 00 35 84 40 sub         byte ptr [eax+eax*2+40843500h],al 
; 00408458開始爲case語句塊索引表
00408457 00 00                add         byte ptr [eax],al  
00408459 01 02                add         dword ptr [edx],eax  
0040845B 06                   push        es  
0040845C 03 04 06             add         eax,dword ptr [esi+eax]  
0040845F 06                   push        es  
00408460 06                   push        es  
00408461 06                   push        es  
00408462 06                   push        es  
00408463 06                   push        es  
00408464 06                   push        es  
00408465 06                   push        es  
00408466 05 CC CC CC CC       add         eax,0CCCCCCCCh  
混合模式:本例  左子樹優化爲地址表模式,右子樹優化爲if模式
void test_switch_tree()
{
004084A0 55                   push        ebp  
004084A1 8B EC                mov         ebp,esp  
004084A3 51                   push        ecx  
    int i = 8;
    scanf("%d", &i);
004084A4 8D 45 FC             lea         eax,[i]  
004084A7 C7 45 FC 08 00 00 00 mov         dword ptr [i],8  
004084AE 50                   push        eax  
004084AF 68 50 CE 4A 00       push        offset string "%d" (04ACE50h)  
004084B4 E8 E7 AE FF FF       call        _scanf (04033A0h)  
    switch(i){
004084B9 8B 45 FC             mov         eax,dword ptr [i]  
004084BC 83 C4 08             add         esp,8  
004084BF 83 F8 23             cmp         eax,23h  
004084C2 7F 66                jg          $LN7+22h (040852Ah)  
004084C4 74 53                je          $LN7+11h (0408519h)  
004084C6 83 C0 FE             add         eax,0FFFFFFFEh  
;這裏是下標平衡值 0FFFFFFFEh表示-2 
004084C9 83 F8 08             cmp         eax,8  
004084CC 77 6F                ja          $LN7+35h (040853Dh)  
004084CE FF 24 85 84 85 40 00 jmp         dword ptr [eax*4+408584h]  
    case 2:
        printf("i == 2\n");
004084D5 68 F4 CE 4A 00       push        offset string "i == 2\n" (04ACEF4h)  
004084DA E8 2F BE FF FF       call        _printf (040430Eh)  
004084DF 83 C4 04             add         esp,4  
        break;
004084E2 8B E5                mov         esp,ebp  
004084E4 5D                   pop         ebp  
004084E5 C3                   ret  
    case 3:
        printf("i == 3\n");
004084E6 68 00 CF 4A 00       push        offset string "i == 3\n" (04ACF00h)  
004084EB E8 1E BE FF FF       call        _printf (040430Eh)  
004084F0 83 C4 04             add         esp,4  
        break;
004084F3 8B E5                mov         esp,ebp  
004084F5 5D                   pop         ebp  
004084F6 C3                   ret  
    case 8:
        printf("i == 8\n");
004084F7 68 0C CF 4A 00       push        offset string "i == 8\n" (04ACF0Ch)  
004084FC E8 0D BE FF FF       call        _printf (040430Eh)  
00408501 83 C4 04             add         esp,4  
        break;
00408504 8B E5                mov         esp,ebp  
00408506 5D                   pop         ebp  
00408507 C3                   ret  
    case 10:
        printf("i == 10\n");
00408508 68 18 CF 4A 00       push        offset string "i == 10\n" (04ACF18h)  
0040850D E8 FC BD FF FF       call        _printf (040430Eh)  
00408512 83 C4 04             add         esp,4  
        break;
00408515 8B E5                mov         esp,ebp  
00408517 5D                   pop         ebp  
00408518 C3                   ret  
    case 35:
        printf("i == 35\n");
00408519 68 24 CF 4A 00       push        offset string "i == 35\n" (04ACF24h)  
0040851E E8 EB BD FF FF       call        _printf (040430Eh)  
00408523 83 C4 04             add         esp,4  
        break;
00408526 8B E5                mov         esp,ebp  
00408528 5D                   pop         ebp  
00408529 C3                   ret  
;右子樹被優化爲if else模式
0040852A 83 F8 25             cmp         eax,25h  
0040852D 74 41                je          $LN7+68h (0408570h)  
0040852F 3D 9A 02 00 00       cmp         eax,29Ah  
00408534 74 29                je          $LN7+57h (040855Fh)  
00408536 3D 10 27 00 00       cmp         eax,2710h  
0040853B 74 11                je          $LN7+46h (040854Eh)  
    default:
        printf("default\n");
0040853D 68 58 CF 4A 00       push        offset string "default\n" (04ACF58h)  
00408542 E8 C7 BD FF FF       call        _printf (040430Eh)  
00408547 83 C4 04             add         esp,4  
        break;
0040854A 8B E5                mov         esp,ebp  
0040854C 5D                   pop         ebp  
0040854D C3                   ret  
    case 10000:
        printf("i == 10000\n");
0040854E 68 48 CF 4A 00       push        offset string "i == 10000\n" (04ACF48h)  
00408553 E8 B6 BD FF FF       call        _printf (040430Eh)  
00408558 83 C4 04             add         esp,4  
        break;
0040855B 8B E5                mov         esp,ebp  
0040855D 5D                   pop         ebp  
0040855E C3                   ret  
    case 666:
        printf("i == 666\n");
0040855F 68 3C CF 4A 00       push        offset string "i == 666\n" (04ACF3Ch)  
00408564 E8 A5 BD FF FF       call        _printf (040430Eh)  
00408569 83 C4 04             add         esp,4  
        break;
0040856C 8B E5                mov         esp,ebp  
0040856E 5D                   pop         ebp  
0040856F C3                   ret  
    case 37:
        printf("i == 37\n");
00408570 68 30 CF 4A 00       push        offset string "i == 37\n" (04ACF30h)  
00408575 E8 94 BD FF FF       call        _printf (040430Eh)  
0040857A 83 C4 04             add         esp,4  
        break;
0040857D 8B E5                mov         esp,ebp  
0040857F 5D                   pop         ebp  
00408580 C3                   ret  
;nop
00408581 0F 1F 00             nop         dword ptr [eax]  
;AddTable First:D5 84 40 00 
00408584 D5 84                aadb        84h  
00408586 40                   inc         eax  
00408587 00 E6                add         dh,ah  
00408589 84 40 00             test        byte ptr [eax],al  
0040858C 3D 85 40 00 3D       cmp         eax,3D004085h  
00408591 85 40 00             test        dword ptr [eax],eax  
00408594 3D 85 40 00 3D       cmp         eax,3D004085h  
00408599 85 40 00             test        dword ptr [eax],eax  
0040859C F7 84 40 00 3D 85 40 00 08 85 40 test        dword ptr [eax+eax*2+40853D00h],40850800h  
004085A7 00 CC                add         ah,cl  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章