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,那么这种情况也是无意义的,不能提高效率,这一种极端情况;