滴水逆向-switch语句反汇编分析

 

 

 

 

 

 switch语句相关练习代码

switch语句反汇编

正常switch语句在VC6++的编译器环境下,3个或者3个一下的条件,反汇编语句跟if else if ......没啥区别,也是一个一个比较,看下面例子

源代码

#include "stdafx.h"    
#include <string.h>

void fun(int x)
{
    switch (x)
    {
    case 1:
        printf("1\n");
        break;
    case 2:
        printf("2\n");
        break;
    case 3:
        printf("3\n");
        break;
    default:
        printf("Error\n");
        break;
    }
}

int main(int argc, char* argv[])
{
    fun(2);
    return 0;
}            

反汇编代码

4:    #include "stdafx.h"
5:    #include <string.h>
6:
7:    void fun(int x)
8:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,44h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-44h]
0040102C   mov         ecx,11h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
9:        switch (x)
10:       {
00401038   mov         eax,dword ptr [ebp+8]
0040103B   mov         dword ptr [ebp-4],eax
0040103E   cmp         dword ptr [ebp-4],1
00401042   je          fun+32h (00401052)
00401044   cmp         dword ptr [ebp-4],2
00401048   je          fun+41h (00401061)
0040104A   cmp         dword ptr [ebp-4],3
0040104E   je          fun+50h (00401070)
00401050   jmp         fun+5Fh (0040107f)
11:       case 1:
12:           printf("1\n");
00401052   push        offset string "1\n" (0042002c)
00401057   call        printf (00401110)
0040105C   add         esp,4
13:           break;
0040105F   jmp         fun+6Ch (0040108c)
14:       case 2:
15:           printf("2\n");
00401061   push        offset string "2\n" (00420028)
00401066   call        printf (00401110)
0040106B   add         esp,4
16:           break;
0040106E   jmp         fun+6Ch (0040108c)
17:       case 3:
18:           printf("3\n");
00401070   push        offset string "3\n" (00420024)
00401075   call        printf (00401110)
0040107A   add         esp,4
19:           break;
0040107D   jmp         fun+6Ch (0040108c)
20:       //case 4:
21:       //  printf("4\n");
22:       //  break;
23:       default:
24:           printf("Error\n");
0040107F   push        offset string "Error\n" (0042001c)
00401084   call        printf (00401110)
00401089   add         esp,4
25:           break;
26:       }
27:   }
0040108C   pop         edi
0040108D   pop         esi
0040108E   pop         ebx
0040108F   add         esp,44h
00401092   cmp         ebp,esp
00401094   call        __chkesp (00401190)
00401099   mov         esp,ebp
0040109B   pop         ebp
0040109C   ret


1.添加case后面的值,一个一个增加,观察反汇编代码的变化(何时生成大表).    

通过测试,在switch语句添加到含有4个case语句的时候就开始生成大表,且case语句后面的常量是连续的;

源代码

#include "stdafx.h"    
#include <string.h>

void fun(int x)
{
    switch (x)
    {
    case 1:
        printf("1\n");
        break;
    case 2:
        printf("2\n");
        break;
    case 3:
        printf("3\n");
        break;
    case 4:
        printf("4\n");
        break;
    default:
        printf("Error\n");
        break;
    }
}

int main(int argc, char* argv[])
{
    fun(2);
    return 0;
}

反汇编代码

4:    #include "stdafx.h"
5:    #include <string.h>
6:
7:    void fun(int x)
8:    {
0040B800   push        ebp
0040B801   mov         ebp,esp
0040B803   sub         esp,44h
0040B806   push        ebx
0040B807   push        esi
0040B808   push        edi
0040B809   lea         edi,[ebp-44h]
0040B80C   mov         ecx,11h
0040B811   mov         eax,0CCCCCCCCh
0040B816   rep stos    dword ptr [edi]
9:        switch (x)
10:       {
0040B818   mov         eax,dword ptr [ebp+8]
0040B81B   mov         dword ptr [ebp-4],eax
0040B81E   mov         ecx,dword ptr [ebp-4]
0040B821   sub         ecx,1
0040B824   mov         dword ptr [ebp-4],ecx
0040B827   cmp         dword ptr [ebp-4],3
0040B82B   ja          $L803+0Fh (0040b873)
0040B82D   mov         edx,dword ptr [ebp-4]
0040B830   jmp         dword ptr [edx*4+40B891h]
11:       case 1:
12:           printf("1\n");
0040B837   push        offset string "1\n" (0042013c)
0040B83C   call        printf (00401110)
0040B841   add         esp,4
13:           break;
0040B844   jmp         $L803+1Ch (0040b880)
14:       case 2:
15:           printf("2\n");
0040B846   push        offset string "2\n" (0042002c)
0040B84B   call        printf (00401110)
0040B850   add         esp,4
16:           break;
0040B853   jmp         $L803+1Ch (0040b880)
17:       case 3:
18:           printf("3\n");
0040B855   push        offset string "3\n" (00420028)
0040B85A   call        printf (00401110)
0040B85F   add         esp,4
19:           break;
0040B862   jmp         $L803+1Ch (0040b880)
20:       case 4:
21:           printf("4\n");
0040B864   push        offset string "4\n" (00420024)
0040B869   call        printf (00401110)
0040B86E   add         esp,4
22:           break;
0040B871   jmp         $L803+1Ch (0040b880)
23:       default:
24:           printf("Error\n");
0040B873   push        offset string "Error\n" (0042001c)
0040B878   call        printf (00401110)
0040B87D   add         esp,4
25:           break;
26:       }
27:   }
0040B880   pop         edi
0040B881   pop         esi
0040B882   pop         ebx
0040B883   add         esp,44h
0040B886   cmp         ebp,esp
0040B888   call        __chkesp (00401190)
0040B88D   mov         esp,ebp
0040B88F   pop         ebp
0040B890   ret
0040B891   aaa
0040B892   mov         eax,0B8460040h
0040B897   inc         eax
0040B898   add         byte ptr [ebp-48h],dl
0040B89B   inc         eax
0040B89C   add         byte ptr [eax+edi*4+40h],ah
0040B8A0   add         ah,cl

对应生成的大表

0040B891  37 B8 40 00
0040B895  46 B8 40 00
0040B899  55 B8 40 00
0040B89D  64 B8 40 00                

上述的大表刚好是4个,这也对应了是4个case语句;
                
对应计算公式的反汇编代码

0040B818   mov         eax,dword ptr [ebp+8]
0040B81B   mov         dword ptr [ebp-4],eax
0040B81E   mov         ecx,dword ptr [ebp-4]
0040B821   sub         ecx,1
0040B824   mov         dword ptr [ebp-4],ecx
0040B827   cmp         dword ptr [ebp-4],3
0040B82B   ja          $L803+0Fh (0040b873)
0040B82D   mov         edx,dword ptr [ebp-4]
0040B830   jmp         dword ptr [edx*4+40B891h]

[edx*4+40B891h]  1x4=4 4+40B891 ----> 刚好就是上面大表对应的0040B895地址,里面的内容就是直达返回结果的内存地址编号0040B846
                                    
                                    
2.将1中的常量值的顺序打乱,观察反汇编代码(观察顺序是否会影响生成大表).        

打乱case语句顺序的情景

源代码
#include "stdafx.h"    
#include <string.h>

void fun(int x)
{
    switch (x)
    {
    case 3:
        printf("1\n");
        break;
    case 5:
        printf("2\n");
        break;
    case 7:
        printf("3\n");
        break;
    case 4:
        printf("4\n");
        break;
    case 2:
        printf("5\n");
        break;
    case 1:
        printf("6\n");
        break;
    case 6:
        printf("7\n");
        break;
    case 8:
        printf("8\n");
        break;
    default:
        printf("Error\n");
        break;
    }
}

int main(int argc, char* argv[])
{
    fun(2);
    return 0;
}            


反汇编代码

4:    #include "stdafx.h"
5:    #include <string.h>
6:
7:    void fun(int x)
8:    {
0040B800   push        ebp
0040B801   mov         ebp,esp
0040B803   sub         esp,44h
0040B806   push        ebx
0040B807   push        esi
0040B808   push        edi
0040B809   lea         edi,[ebp-44h]
0040B80C   mov         ecx,11h
0040B811   mov         eax,0CCCCCCCCh
0040B816   rep stos    dword ptr [edi]
9:        switch (x)
10:       {
0040B818   mov         eax,dword ptr [ebp+8]
0040B81B   mov         dword ptr [ebp-4],eax
0040B81E   mov         ecx,dword ptr [ebp-4]
0040B821   sub         ecx,1
0040B824   mov         dword ptr [ebp-4],ecx
0040B827   cmp         dword ptr [ebp-4],7
0040B82B   ja          $L811+0Fh (0040b8b3)
0040B831   mov         edx,dword ptr [ebp-4]
0040B834   jmp         dword ptr [edx*4+40B8D1h]
11:       case 3:
12:           printf("1\n");
0040B83B   push        offset string "1\n" (00420f8c)
0040B840   call        printf (00401110)
0040B845   add         esp,4
13:           break;
0040B848   jmp         $L811+1Ch (0040b8c0)
14:       case 5:
15:           printf("2\n");
0040B84A   push        offset string "2\n" (00420f88)
0040B84F   call        printf (00401110)
0040B854   add         esp,4
16:           break;
0040B857   jmp         $L811+1Ch (0040b8c0)
17:       case 7:
18:           printf("3\n");
0040B859   push        offset string "3\n" (00420f84)
0040B85E   call        printf (00401110)
0040B863   add         esp,4
19:           break;
0040B866   jmp         $L811+1Ch (0040b8c0)
20:       case 4:
21:           printf("4\n");
0040B868   push        offset string "4\n" (00420f34)
0040B86D   call        printf (00401110)
0040B872   add         esp,4
22:           break;
0040B875   jmp         $L811+1Ch (0040b8c0)
23:       case 2:
24:           printf("5\n");
0040B877   push        offset string "5\n" (0042013c)
0040B87C   call        printf (00401110)
0040B881   add         esp,4
25:           break;
0040B884   jmp         $L811+1Ch (0040b8c0)
26:       case 1:
27:           printf("6\n");
0040B886   push        offset string "6\n" (0042002c)
0040B88B   call        printf (00401110)
0040B890   add         esp,4
28:           break;
0040B893   jmp         $L811+1Ch (0040b8c0)
29:       case 6:
30:           printf("7\n");
0040B895   push        offset string "7\n" (00420028)
0040B89A   call        printf (00401110)
0040B89F   add         esp,4
31:           break;
0040B8A2   jmp         $L811+1Ch (0040b8c0)
32:       case 8:
33:           printf("8\n");
0040B8A4   push        offset string "8\n" (00420024)
0040B8A9   call        printf (00401110)
0040B8AE   add         esp,4
34:           break;
0040B8B1   jmp         $L811+1Ch (0040b8c0)
35:       default:
36:           printf("Error\n");
0040B8B3   push        offset string "Error\n" (0042001c)
0040B8B8   call        printf (00401110)
0040B8BD   add         esp,4
37:           break;
38:       }
39:   }
0040B8C0   pop         edi
0040B8C1   pop         esi
0040B8C2   pop         ebx
0040B8C3   add         esp,44h
0040B8C6   cmp         ebp,esp
0040B8C8   call        __chkesp (00401190)
0040B8CD   mov         esp,ebp
0040B8CF   pop         ebp
0040B8D0   ret
0040B8D1   xchg        bh,byte ptr [eax-4788FFC0h]
0040B8D7   inc         eax
0040B8D8   add         byte ptr [ebx],bh
0040B8DA   mov         eax,0B8680040h
0040B8DF   inc         eax
0040B8E0   add         byte ptr [edx-48h],cl
0040B8E3   inc         eax
0040B8E4   add         byte ptr [ebp+590040B8h],dl
0040B8EA   mov         eax,0B8A40040h
0040B8EF   inc         eax
0040B8F0   add         ah,cl


对应生成的大表

0040B8D1  86 B8 40 00  
0040B8D5  77 B8 40 00
0040B8D9  3B B8 40 00
0040B8DD  68 B8 40 00
0040B8E1  4A B8 40 00
0040B8E5  95 B8 40 00
0040B8E9  59 B8 40 00
0040B8ED  A4 B8 40 00                    
                                    
                                    
得出结论就是,即使case语句的常量打乱了顺序,仍然不影响大表的生成

                                    
3.将case后面的值改成从100开始到109,观察汇编变化(观察值较大时是否生成大表).                    

源代码

#include "stdafx.h"    
#include <string.h>

void fun(int x)
{
    switch (x)
    {
    case 100:
        printf("100\n");
        break;
    case 101:
        printf("101\n");
        break;
    case 102:
        printf("102\n");
        break;
    case 103:
        printf("103\n");
        break;
    case 104:
        printf("104\n");
        break;
    case 105:
        printf("105\n");
        break;
    case 106:
        printf("106\n");
        break;
    case 107:
        printf("107\n");
        break;
    case 108:
        printf("108\n");
        break;
    case 109:
        printf("109\n");
        break;
    default:
        printf("Error\n");
        break;
    }
}

int main(int argc, char* argv[])
{
    fun(106);
    return 0;
}


反汇编代码

4:    #include "stdafx.h"
5:    #include <string.h>
6:
7:    void fun(int x)
8:    {
0040B800   push        ebp
0040B801   mov         ebp,esp
0040B803   sub         esp,44h
0040B806   push        ebx
0040B807   push        esi
0040B808   push        edi
0040B809   lea         edi,[ebp-44h]
0040B80C   mov         ecx,11h
0040B811   mov         eax,0CCCCCCCCh
0040B816   rep stos    dword ptr [edi]
9:        switch (x)
10:       {
0040B818   mov         eax,dword ptr [ebp+8]
0040B81B   mov         dword ptr [ebp-4],eax
0040B81E   mov         ecx,dword ptr [ebp-4]
0040B821   sub         ecx,64h
0040B824   mov         dword ptr [ebp-4],ecx
0040B827   cmp         dword ptr [ebp-4],9
0040B82B   ja          $L815+0Fh (0040b8d7)
0040B831   mov         edx,dword ptr [ebp-4]
0040B834   jmp         dword ptr [edx*4+40B8F5h]
11:       case 100:
12:           printf("100\n");
0040B83B   push        offset string "100\n" (00420fc8)
0040B840   call        printf (00401110)
0040B845   add         esp,4
13:           break;
0040B848   jmp         $L815+1Ch (0040b8e4)
14:       case 101:
15:           printf("101\n");
0040B84D   push        offset string "101\n" (00420fc0)
0040B852   call        printf (00401110)
0040B857   add         esp,4
16:           break;
0040B85A   jmp         $L815+1Ch (0040b8e4)
17:       case 102:
18:           printf("102\n");
0040B85F   push        offset string "102\n" (00420fb8)
0040B864   call        printf (00401110)
0040B869   add         esp,4
19:           break;
0040B86C   jmp         $L815+1Ch (0040b8e4)
20:       case 103:
21:           printf("103\n");
0040B86E   push        offset string "103\n" (00420f84)
0040B873   call        printf (00401110)
0040B878   add         esp,4
22:           break;
0040B87B   jmp         $L815+1Ch (0040b8e4)
23:       case 104:
24:           printf("104\n");
0040B87D   push        offset string "104\n" (00420fb0)
0040B882   call        printf (00401110)
0040B887   add         esp,4
25:           break;
0040B88A   jmp         $L815+1Ch (0040b8e4)
26:       case 105:
27:           printf("105\n");
0040B88C   push        offset string "105\n" (00420fa8)
0040B891   call        printf (00401110)
0040B896   add         esp,4
28:           break;
0040B899   jmp         $L815+1Ch (0040b8e4)
29:       case 106:
30:           printf("106\n");
0040B89B   push        offset string "106\n" (00420fa0)
0040B8A0   call        printf (00401110)
0040B8A5   add         esp,4
31:           break;
0040B8A8   jmp         $L815+1Ch (0040b8e4)
32:       case 107:
33:           printf("107\n");
0040B8AA   push        offset string "107\n" (00420f98)
0040B8AF   call        printf (00401110)
0040B8B4   add         esp,4
34:           break;
0040B8B7   jmp         $L815+1Ch (0040b8e4)
35:       case 108:
36:           printf("108\n");
0040B8B9   push        offset string "108\n" (00420024)
0040B8BE   call        printf (00401110)
0040B8C3   add         esp,4
37:           break;
0040B8C6   jmp         $L815+1Ch (0040b8e4)
38:       case 109:
39:           printf("109\n");
0040B8C8   push        offset string "109\n" (00420f90)
0040B8CD   call        printf (00401110)
0040B8D2   add         esp,4
40:           break;
0040B8D5   jmp         $L815+1Ch (0040b8e4)
41:       default:
42:           printf("Error\n");
0040B8D7   push        offset string "Error\n" (0042001c)
0040B8DC   call        printf (00401110)
0040B8E1   add         esp,4
43:           break;
44:       }
45:   }
0040B8E4   pop         edi
0040B8E5   pop         esi
0040B8E6   pop         ebx
0040B8E7   add         esp,44h
0040B8EA   cmp         ebp,esp
0040B8EC   call        __chkesp (00401190)
0040B8F1   mov         esp,ebp
0040B8F3   pop         ebp
0040B8F4   ret
0040B8F5   cmp         edi,dword ptr [eax-47B2FFC0h]
0040B8FB   inc         eax
0040B8FC   add         byte ptr [edi-48h],bl
0040B8FF   inc         eax
0040B900   add         byte ptr [esi-48h],ch
0040B903   inc         eax
0040B904   add         byte ptr [ebp-48h],bh
0040B907   inc         eax
0040B908   add         byte ptr [eax+edi*4-4764FFC0h],cl
0040B90F   inc         eax
0040B910   add         byte ptr [edx-46FFBF48h],ch
0040B916   mov         eax,0B8C80040h
0040B91B   inc         eax
0040B91C   add         ah,cl

根据大表计算

64 -- 十进制 100
106-100 = 6
edx*4+40B8F5h
从上面计算公式得出
6×4+40B8F5 意思就是0040B8F5所在的大表向下以4个字节移动6位

大表
0040B8F5  3B B8 40 00
0040B8F9  4D B8 40 00
0040B8FD  5F B8 40 00
0040B901  6E B8 40 00
0040B905  7D B8 40 00
0040B909  8C B8 40 00
0040B90D  9B B8 40 00
0040B911  AA B8 40 00
0040B915  B9 B8 40 00
0040B919  C8 B8 40 00
                                    
向下以4字节移动6位刚好就是大表地址 0040B90D  9B B8 40 00  对应的内存地址: 0040B89B

30:           printf("106\n");
0040B89B   push        offset string "106\n" (00420fa0)
0040B8A0   call        printf (00401110)
0040B8A5   add         esp,4

刚好打印106

所以此处结论是依然会生成大表

                                    
4.将连续的10项中抹去1项或者2项,观察反汇编有无变化(观察大表空缺位置的处理).                

抹去其中case语句 108

#include "stdafx.h"    
#include <string.h>

void fun(int x)
{
    switch (x)
    {
    case 100:
        printf("100\n");
        break;
    case 101:
        printf("101\n");
        break;
    case 102:
        printf("102\n");
        break;
    case 103:
        printf("103\n");
        break;
    case 104:
        printf("104\n");
        break;
    case 105:
        printf("105\n");
        break;
    case 106:
        printf("106\n");
        break;
    case 107:
        printf("107\n");
        break;

    case 109:
        printf("109\n");
        break;
    default:
        printf("Error\n");
        break;
    }
}

int main(int argc, char* argv[])
{
    fun(106);
    return 0;
}            


反汇编代码

4:    #include "stdafx.h"
5:    #include <string.h>
6:
7:    void fun(int x)
8:    {
0040B800   push        ebp
0040B801   mov         ebp,esp
0040B803   sub         esp,44h
0040B806   push        ebx
0040B807   push        esi
0040B808   push        edi
0040B809   lea         edi,[ebp-44h]
0040B80C   mov         ecx,11h
0040B811   mov         eax,0CCCCCCCCh
0040B816   rep stos    dword ptr [edi]
9:        switch (x)
10:       {
0040B818   mov         eax,dword ptr [ebp+8]
0040B81B   mov         dword ptr [ebp-4],eax
0040B81E   mov         ecx,dword ptr [ebp-4]
0040B821   sub         ecx,64h
0040B824   mov         dword ptr [ebp-4],ecx
0040B827   cmp         dword ptr [ebp-4],9
0040B82B   ja          $L813+0Fh (0040b8c5)
0040B831   mov         edx,dword ptr [ebp-4]
0040B834   jmp         dword ptr [edx*4+40B8E3h]
11:       case 100:
12:           printf("100\n");
0040B83B   push        offset string "100\n" (00420fc0)
0040B840   call        printf (00401110)
0040B845   add         esp,4
13:           break;
0040B848   jmp         $L813+1Ch (0040b8d2)
14:       case 101:
15:           printf("101\n");
0040B84D   push        offset string "101\n" (00420fb8)
0040B852   call        printf (00401110)
0040B857   add         esp,4
16:           break;
0040B85A   jmp         $L813+1Ch (0040b8d2)
17:       case 102:
18:           printf("102\n");
0040B85C   push        offset string "3\n" (00420f84)
0040B861   call        printf (00401110)
0040B866   add         esp,4
19:           break;
0040B869   jmp         $L813+1Ch (0040b8d2)
20:       case 103:
21:           printf("103\n");
0040B86B   push        offset string "103\n" (00420fb0)
0040B870   call        printf (00401110)
0040B875   add         esp,4
22:           break;
0040B878   jmp         $L813+1Ch (0040b8d2)
23:       case 104:
24:           printf("104\n");
0040B87A   push        offset string "104\n" (00420fa8)
0040B87F   call        printf (00401110)
0040B884   add         esp,4
25:           break;
0040B887   jmp         $L813+1Ch (0040b8d2)
26:       case 105:
27:           printf("105\n");
0040B889   push        offset string "105\n" (00420fa0)
0040B88E   call        printf (00401110)
0040B893   add         esp,4
28:           break;
0040B896   jmp         $L813+1Ch (0040b8d2)
29:       case 106:
30:           printf("106\n");
0040B898   push        offset string "106\n" (00420f98)
0040B89D   call        printf (00401110)
0040B8A2   add         esp,4
31:           break;
0040B8A5   jmp         $L813+1Ch (0040b8d2)
32:       case 107:
33:           printf("107\n");
0040B8A7   push        offset string "8\n" (00420024)
0040B8AC   call        printf (00401110)
0040B8B1   add         esp,4
34:           break;
0040B8B4   jmp         $L813+1Ch (0040b8d2)
35:
36:       case 109:
37:           printf("109\n");
0040B8B6   push        offset string "109\n" (00420f90)
0040B8BB   call        printf (00401110)
0040B8C0   add         esp,4
38:           break;
0040B8C3   jmp         $L813+1Ch (0040b8d2)
39:       default:
40:           printf("Error\n");
0040B8C5   push        offset string "Error\n" (0042001c)
0040B8CA   call        printf (00401110)
0040B8CF   add         esp,4
41:           break;
42:       }
43:   }
0040B8D2   pop         edi
0040B8D3   pop         esi
0040B8D4   pop         ebx
0040B8D5   add         esp,44h
0040B8D8   cmp         ebp,esp
0040B8DA   call        __chkesp (00401190)
0040B8DF   mov         esp,ebp
0040B8E1   pop         ebp
0040B8E2   ret
0040B8E3   cmp         edi,dword ptr [eax-47B2FFC0h]
0040B8E9   inc         eax
0040B8EA   add         byte ptr [eax+edi*4+40h],bl
0040B8EE   add         byte ptr [ebx-48h],ch
0040B8F1   inc         eax
0040B8F2   add         byte ptr [edx-48h],bh
0040B8F5   inc         eax
0040B8F6   add         byte ptr [ecx-67FFBF48h],cl
0040B8FC   mov         eax,0B8A70040h
0040B901   inc         eax
0040B902   add         ch,al
0040B904   mov         eax,0B8B60040h
0040B909   inc         eax
0040B90A   add         ah,cl


[edx*4+40B8E3h] 计算公式操作跟上面一样,其中有一个区别就是去掉了一个case语句会将default的对应内存地址放入这个大表中,下面所在位置
0040B903  C5 B8 40 00

大表

0040B8E3  3B B8 40 00
0040B8E7  4D B8 40 00
0040B8EB  5C B8 40 00
0040B8EF  6B B8 40 00
0040B8F3  7A B8 40 00
0040B8F7  89 B8 40 00
0040B8FB  98 B8 40 00
0040B8FF  A7 B8 40 00
0040B903  C5 B8 40 00
0040B907  B6 B8 40 00                     
                                    
得出结论:
(1)当抹去1个case语句会将default的内存地址编号放入大表中;
(2)当抹去2个case语句会将default的内存地址编号放入大表中,此时就有两个相同的default内存地址在大表中;
(3)当抹去3个case语句会将default的内存地址编号放入大表中,此时就有三个相同的default内存地址在大表中;
(4)当抹去4个case语句会将default的内存地址编号放入大表中,此时就有四个相同的default内存地址在大表中;
(5)当抹去5个case语句会将default的内存地址编号放入大表中,此时就有五个相同的default内存地址在大表中;
(6)当抹去6个case语句的时候会生成小表;
                                    
5.在10项中连续抹去,不要抹去最大值和最小值(观察何时生成小表).        

上述4例题中已经论证,当抹去6个case语句的时候会生成小表;    

源代码


反汇编代码

4:    #include "stdafx.h"
5:    #include <string.h>
6:
7:    void fun(int x)
8:    {
0040B800   push        ebp
0040B801   mov         ebp,esp
0040B803   sub         esp,44h
0040B806   push        ebx
0040B807   push        esi
0040B808   push        edi
0040B809   lea         edi,[ebp-44h]
0040B80C   mov         ecx,11h
0040B811   mov         eax,0CCCCCCCCh
0040B816   rep stos    dword ptr [edi]
9:        switch (x)
10:       {
0040B818   mov         eax,dword ptr [ebp+8]
0040B81B   mov         dword ptr [ebp-4],eax
0040B81E   mov         ecx,dword ptr [ebp-4]
0040B821   sub         ecx,64h
0040B824   mov         dword ptr [ebp-4],ecx
0040B827   cmp         dword ptr [ebp-4],9
0040B82B   ja          $L803+0Fh (0040b87b)
0040B82D   mov         eax,dword ptr [ebp-4]
0040B830   xor         edx,edx
0040B832   mov         dl,byte ptr  (0040b8ad)[eax]
0040B838   jmp         dword ptr [edx*4+40B899h]
11:       case 100:
12:           printf("100\n");
0040B83F   push        offset string "100\n" (00420fa0)
0040B844   call        printf (00401110)
0040B849   add         esp,4
13:           break;
0040B84C   jmp         $L803+1Ch (0040b888)
14:       case 101:
15:           printf("101\n");
0040B84E   push        offset string "101\n" (00420f98)
0040B853   call        printf (00401110)
0040B858   add         esp,4
16:           break;
0040B85B   jmp         $L803+1Ch (0040b888)
17:       case 102:
18:           printf("102\n");
0040B85D   push        offset string "104\n" (00420024)
0040B862   call        printf (00401110)
0040B867   add         esp,4
19:           break;
0040B86A   jmp         $L803+1Ch (0040b888)
20:
21:
22:       case 109:
23:           printf("109\n");
0040B86C   push        offset string "109\n" (00420f90)
0040B871   call        printf (00401110)
0040B876   add         esp,4
24:           break;
0040B879   jmp         $L803+1Ch (0040b888)
25:       default:
26:           printf("Error\n");
0040B87B   push        offset string "Error\n" (0042001c)
0040B880   call        printf (00401110)
0040B885   add         esp,4
27:           break;
28:       }
29:   }
0040B888   pop         edi
0040B889   pop         esi
0040B88A   pop         ebx
0040B88B   add         esp,44h
0040B88E   cmp         ebp,esp
0040B890   call        __chkesp (00401190)
0040B895   mov         esp,ebp
0040B897   pop         ebp
0040B898   ret
0040B899   aas
0040B89A   mov         eax,0B84E0040h
0040B89F   inc         eax
0040B8A0   add         byte ptr [ebp-48h],bl
0040B8A3   inc         eax
0040B8A4   add         byte ptr [eax+edi*4+40h],ch
0040B8A8   add         byte ptr [ebx-48h],bh
0040B8AB   inc         eax
0040B8AC   add         byte ptr [eax],al
0040B8AE   add         dword ptr [edx],eax
0040B8B0   add         al,4
0040B8B2   add         al,4
0040B8B4   add         al,4
0040B8B6   add         ecx,esp

对应的大表和小表

0040B899  3F B8 40 00
0040B89D  4E B8 40 00
0040B8A1  5D B8 40 00
0040B8A5  6C B8 40 00
0040B8A9  7B B8 40 00
0040B8AD  00 01 02 04   //小表
0040B8B1  04 04 04 04   //小表
0040B8B5  04 03 CC CC      //小表

其中反汇编 0040B832   mov         dl,byte ptr  (0040b8ad)[eax] 含义

将小表0040B8AD加上eax的值,就是结果,而eax值此时是6,所以向后移动6位即可

0040B8AD  00 01 02 04
0040B8B1  04 04 04 04   

00 01 02 04 04 04 04 04 ---> 向后移动6位,就是数6位,得到的结果是04,所以edx的结果是4 根据下面的公式

edx*4+40B899h  4×4+0040B899  可以得出结果是以4字节向后4位即可得到计算结果的内存地址编号:0040B8A9  7B B8 40 00

内存编号对应的内存地址:0040B87B

26:           printf("Error\n");
0040B87B   push        offset string "Error\n" (0042001c)
0040B880   call        printf (00401110)
0040B885   add         esp,4
                                    
6.将case后面常量表达式改成毫不连续的值,观察反汇编变化.                                    

源代码
#include "stdafx.h"    
#include <string.h>

void fun(int x)
{
    switch (x)
    {
    case 10:
        printf("100\n");
        break;
    case 201:
        printf("101\n");
        break;
    case 2:
        printf("102\n");
        break;
    case 692:
        printf("102\n");
        break;
    case 532:
        printf("102\n");
        break;
    case 308:
        printf("102\n");
        break;
    case 804:
        printf("102\n");
        break;
    case 749:
        printf("102\n");
        break;
    case 1033:
        printf("102\n");
        break;

    case 29:
        printf("109\n");
        break;
    default:
        printf("Error\n");
        break;
    }
}

int main(int argc, char* argv[])
{
    fun(308);
    return 0;
}            


反汇编代码

4:    #include "stdafx.h"
5:    #include <string.h>
6:
7:    void fun(int x)
8:    {
0040B800   push        ebp
0040B801   mov         ebp,esp
0040B803   sub         esp,44h
0040B806   push        ebx
0040B807   push        esi
0040B808   push        edi
0040B809   lea         edi,[ebp-44h]
0040B80C   mov         ecx,11h
0040B811   mov         eax,0CCCCCCCCh
0040B816   rep stos    dword ptr [edi]
9:        switch (x)
10:       {
0040B818   mov         eax,dword ptr [ebp+8]
0040B81B   mov         dword ptr [ebp-4],eax
0040B81E   cmp         dword ptr [ebp-4],214h
0040B825   jg          fun+74h (0040b874)
0040B827   cmp         dword ptr [ebp-4],214h
0040B82E   je          fun+0F9h (0040b8f9)
0040B834   cmp         dword ptr [ebp-4],1Dh
0040B838   jg          fun+59h (0040b859)
0040B83A   cmp         dword ptr [ebp-4],1Dh
0040B83E   je          fun+144h (0040b944)
0040B844   cmp         dword ptr [ebp-4],2
0040B848   je          fun+0DBh (0040b8db)
0040B84E   cmp         dword ptr [ebp-4],0Ah
0040B852   je          fun+0B7h (0040b8b7)
0040B854   jmp         fun+153h (0040b953)
0040B859   cmp         dword ptr [ebp-4],0C9h
0040B860   je          fun+0C9h (0040b8c9)
0040B862   cmp         dword ptr [ebp-4],134h
0040B869   je          fun+108h (0040b908)
0040B86F   jmp         fun+153h (0040b953)
0040B874   cmp         dword ptr [ebp-4],324h
0040B87B   jg          fun+0A5h (0040b8a5)
0040B87D   cmp         dword ptr [ebp-4],324h
0040B884   je          fun+117h (0040b917)
0040B88A   cmp         dword ptr [ebp-4],2B4h
0040B891   je          fun+0EAh (0040b8ea)
0040B893   cmp         dword ptr [ebp-4],2EDh
0040B89A   je          fun+126h (0040b926)
0040B8A0   jmp         fun+153h (0040b953)
0040B8A5   cmp         dword ptr [ebp-4],409h
0040B8AC   je          fun+135h (0040b935)
0040B8B2   jmp         fun+153h (0040b953)
11:       case 10:
12:           printf("100\n");
0040B8B7   push        offset string "100\n" (00420fa0)
0040B8BC   call        printf (00401110)
0040B8C1   add         esp,4
13:           break;
0040B8C4   jmp         fun+160h (0040b960)
14:       case 201:
15:           printf("101\n");
0040B8C9   push        offset string "101\n" (00420f98)
0040B8CE   call        printf (00401110)
0040B8D3   add         esp,4
16:           break;
0040B8D6   jmp         fun+160h (0040b960)
17:       case 2:
18:           printf("102\n");
0040B8DB   push        offset string "104\n" (00420024)
0040B8E0   call        printf (00401110)
0040B8E5   add         esp,4
19:           break;
0040B8E8   jmp         fun+160h (0040b960)
20:       case 692:
21:           printf("102\n");
0040B8EA   push        offset string "104\n" (00420024)
0040B8EF   call        printf (00401110)
0040B8F4   add         esp,4
22:           break;
0040B8F7   jmp         fun+160h (0040b960)
23:       case 532:
24:           printf("102\n");
0040B8F9   push        offset string "104\n" (00420024)
0040B8FE   call        printf (00401110)
0040B903   add         esp,4
25:           break;
0040B906   jmp         fun+160h (0040b960)
26:       case 308:
27:           printf("102\n");
0040B908   push        offset string "104\n" (00420024)
0040B90D   call        printf (00401110)
0040B912   add         esp,4
28:           break;
0040B915   jmp         fun+160h (0040b960)
29:       case 804:
30:           printf("102\n");
0040B917   push        offset string "104\n" (00420024)
0040B91C   call        printf (00401110)
0040B921   add         esp,4
31:           break;
0040B924   jmp         fun+160h (0040b960)
32:       case 749:
33:           printf("102\n");
0040B926   push        offset string "104\n" (00420024)
0040B92B   call        printf (00401110)
0040B930   add         esp,4
34:           break;
0040B933   jmp         fun+160h (0040b960)
35:       case 1033:
36:           printf("102\n");
0040B935   push        offset string "104\n" (00420024)
0040B93A   call        printf (00401110)
0040B93F   add         esp,4
37:           break;
0040B942   jmp         fun+160h (0040b960)
38:
39:       case 29:
40:           printf("109\n");
0040B944   push        offset string "109\n" (00420f90)
0040B949   call        printf (00401110)
0040B94E   add         esp,4
41:           break;
0040B951   jmp         fun+160h (0040b960)
42:       default:
43:           printf("Error\n");
0040B953   push        offset string "Error\n" (0042001c)
0040B958   call        printf (00401110)
0040B95D   add         esp,4
44:           break;
45:       }
46:   }
0040B960   pop         edi
0040B961   pop         esi
0040B962   pop         ebx
0040B963   add         esp,44h
0040B966   cmp         ebp,esp
0040B968   call        __chkesp (00401190)
0040B96D   mov         esp,ebp
0040B96F   pop         ebp
0040B970   ret


结论:此时switch语句不会生成大表和小表,跟if else if语句判断逻辑基本相同,不能提高效率,如果这样操作就没啥意义;

7.如果switch语句中的case语句常量是无序且每个数字之间大于256,那么这种情况也是无意义的,不能提高效率,这一种极端情况;

 

posted @ 2021-08-12 13:51  皇帽讲绿帽带法技巧  阅读(207)  评论(0编辑  收藏  举报