通过反汇编深入了解switch语句,并从中理解为何在某些情况下其性能优于if...else语句
switch (整形表达式) { case 常量表达式1: 语句块; break; case 常量表达式2: 语句块; break; ...... ...... ...... case 常量表达式n: 语句块; break; default: 语句块; break; }
switch
后的表达式的返回值必须是整型case
后的表达式只能是整型常量,或整型常量构成的表达式case
后的语句块中没有包含break;
,则会按顺序执行其下面的语句块,直到结束或遇到break;
从反汇编的角度观察:
case
后面的值,一个一个增加,观察反汇编代码的变化(何时生成大表)case
的顺序打乱,观察反汇编代码(观察顺序是否会影响生成大表)case
后面的值改成从100
开始到109
,观察反汇编的变化(观察值较大时是否生成大表)10
项中抹去1
项或2
项,观察反汇编有无变化(观察大表空缺位置的处理)10
项中连续抹去,不要抹去最大值
和最小值
(观察何时生成小表)case
后面的常量表达式改成毫不连续的值,观察反汇编的变化CPP代码:
#include "stdafx.h" void Fun(int x) { switch (x) { case 1: printf("%d",1); break; case 2: printf("%d",2); break; case 3: printf("%d",3); break; default: printf("None"); break; } } int main(int argc, char* argv[]) { Fun(2); return 0; }
反汇编:
Fun: 0040D490 push ebp 0040D491 mov ebp,esp 0040D493 sub esp,44h 0040D496 push ebx 0040D497 push esi 0040D498 push edi 0040D499 lea edi,[ebp-44h] 0040D49C mov ecx,11h 0040D4A1 mov eax,0CCCCCCCCh 0040D4A6 rep stos dword ptr [edi] 0040D4A8 mov eax,dword ptr [ebp+8] 0040D4AB mov dword ptr [ebp-4],eax 0040D4AE cmp dword ptr [ebp-4],1 0040D4B2 je Fun+32h (0040d4c2) 0040D4B4 cmp dword ptr [ebp-4],2 0040D4B8 je Fun+43h (0040d4d3) 0040D4BA cmp dword ptr [ebp-4],3 0040D4BE je Fun+54h (0040d4e4) 0040D4C0 jmp Fun+65h (0040d4f5) 0040D4C2 push 1 0040D4C4 push offset string "%d" (0042210c) 0040D4C9 call printf (0040d760) 0040D4CE add esp,8 0040D4D1 jmp Fun+72h (0040d502) 0040D4D3 push 2 0040D4D5 push offset string "%d" (0042210c) 0040D4DA call printf (0040d760) 0040D4DF add esp,8 0040D4E2 jmp Fun+72h (0040d502) 0040D4E4 push 3 0040D4E6 push offset string "%d" (0042210c) 0040D4EB call printf (0040d760) 0040D4F0 add esp,8 0040D4F3 jmp Fun+72h (0040d502) 0040D4F5 push offset string "None" (00422f6c) 0040D4FA call printf (0040d760) 0040D4FF add esp,4 0040D502 pop edi 0040D503 pop esi 0040D504 pop ebx 0040D505 add esp,44h 0040D508 cmp ebp,esp 0040D50A call __chkesp (004010a0) 0040D50F mov esp,ebp 0040D511 pop ebp 0040D512 ret
小结:
case
分支小于4
个时,其反汇编与if...else
类似
CPP代码:
#include "stdafx.h" void Fun(int x) { switch (x) { case 1: printf("1"); break; case 2: printf("2"); break; case 3: printf("3"); break; case 4: printf("4"); break; default: printf("None"); break; } } int main(int argc, char* argv[]) { Fun(2); return 0; }
反汇编:
Fun: 0040D490 push ebp 0040D491 mov ebp,esp 0040D493 sub esp,44h 0040D496 push ebx 0040D497 push esi 0040D498 push edi 0040D499 lea edi,[ebp-44h] 0040D49C mov ecx,11h 0040D4A1 mov eax,0CCCCCCCCh 0040D4A6 rep stos dword ptr [edi] 0040D4A8 mov eax,dword ptr [ebp+8] 0040D4AB mov dword ptr [ebp-4],eax 0040D4AE mov ecx,dword ptr [ebp-4] 0040D4B1 sub ecx,1 0040D4B4 mov dword ptr [ebp-4],ecx ;[ebp-4]=[ebp+8]-1 0040D4B7 cmp dword ptr [ebp-4],3 0040D4BB ja $L537+11h (0040d50b) ;如果[ebp-4]>3跳转到0040d50b 0040D4BD mov edx,dword ptr [ebp-4] 0040D4C0 jmp dword ptr [edx*4+40D529h] $L533: 0040D4C7 push offset string "1" (00422fac) 0040D4CC call printf (0040d760) 0040D4D1 add esp,4 0040D4D4 jmp $L539+1Ch (0040d510) $L535: 0040D4D6 push offset string "2" (00422fa8) 0040D4DB call printf (0040d760) 0040D4E0 add esp,4 0040D4E3 jmp $L539+1Ch (0040d510) $L537: 0040D4E5 push offset string "3" (00422fa4) 0040D4EA call printf (0040d760) 0040D4EF add esp,4 0040D4F2 jmp $L539+1Ch (0040d510) $L539: 0040D4F4 push offset string "4" (0042210c) 0040D4F9 call printf (0040d760) 0040D4FE add esp,4 0040D501 jmp $L539+1Ch (0040d510) 0040D503 push offset string "None" (00422f6c) 0040D508 call printf (0040d760) 0040D50D add esp,4 0040D510 pop edi 0040D511 pop esi 0040D512 pop ebx 0040D513 add esp,44h 0040D516 cmp ebp,esp 0040D518 call __chkesp (004010a0) 0040D51D mov esp,ebp 0040D51F pop ebp 0040D520 ret
Register:
EAX = 00000002 EBX = 7FFDE000 ECX = 00000001 EDX = 00000001 ESI = 00000000 EDI = 0012FF28 EIP = 0040D4C0 ESP = 0012FED8 EBP = 0012FF28 EFL = 00000293
Memory:
0040D521 C7 D4 40 00 窃@. 0040D525 D6 D4 40 00 衷@. 0040D529 E5 D4 40 00 逶@. 0040D52D F4 D4 40 00 粼@.
小结:
当
case
分支大于等于4
个且连续时,会在一段连续内存中存储每个case
所对应语句块的起始地址(称其为大表),根据[edx*4+40D529h]
即可确定跳转地址
CPP代码:
#include "stdafx.h" void Fun(int x) { switch (x) { case 2: printf("2"); break; case 1: printf("1"); break; case 4: printf("4"); break; case 3: printf("3"); break; default: printf("None"); break; } } int main(int argc, char* argv[]) { Fun(2); return 0; }
反汇编:
Fun: 0040D490 push ebp 0040D491 mov ebp,esp 0040D493 sub esp,44h 0040D496 push ebx 0040D497 push esi 0040D498 push edi 0040D499 lea edi,[ebp-44h] 0040D49C mov ecx,11h 0040D4A1 mov eax,0CCCCCCCCh 0040D4A6 rep stos dword ptr [edi] 0040D4A8 mov eax,dword ptr [ebp+8] 0040D4AB mov dword ptr [ebp-4],eax 0040D4AE mov ecx,dword ptr [ebp-4] 0040D4B1 sub ecx,1 0040D4B4 mov dword ptr [ebp-4],ecx 0040D4B7 cmp dword ptr [ebp-4],3 0040D4BB ja $L539+0Fh (0040d503) 0040D4BD mov edx,dword ptr [ebp-4] 0040D4C0 jmp dword ptr [edx*4+40D521h] $L533: 0040D4C7 push offset string "2" (00422fac) 0040D4CC call printf (0040d760) 0040D4D1 add esp,4 0040D4D4 jmp $L539+1Ch (0040d510) $L535: 0040D4D6 push offset string "1" (00422fa8) 0040D4DB call printf (0040d760) 0040D4E0 add esp,4 0040D4E3 jmp $L539+1Ch (0040d510) $L537: 0040D4E5 push offset string "4" (00422fa4) 0040D4EA call printf (0040d760) 0040D4EF add esp,4 0040D4F2 jmp $L539+1Ch (0040d510) $L539: 0040D4F4 push offset string "3" (0042210c) 0040D4F9 call printf (0040d760) 0040D4FE add esp,4 0040D501 jmp $L539+1Ch (0040d510) 0040D503 push offset string "None" (00422f6c) 0040D508 call printf (0040d760) 0040D50D add esp,4 0040D510 pop edi 0040D511 pop esi 0040D512 pop ebx 0040D513 add esp,44h 0040D516 cmp ebp,esp 0040D518 call __chkesp (004010a0) 0040D51D mov esp,ebp 0040D51F pop ebp 0040D520 ret
Register:
EAX = 00000002 EBX = 7FFDB000 ECX = 00000001 EDX = 00000001 ESI = 00000000 EDI = 0012FF28 EIP = 0040D4C0 ESP = 0012FED8 EBP = 0012FF28 EFL = 00000293
Memory:
0040D521 D6 D4 40 00 衷@. 0040D525 C7 D4 40 00 窃@. 0040D529 F4 D4 40 00 粼@. 0040D52D E5 D4 40 00 逶@.
小结:
在值连续的情况下,顺序并不会影响生成大表
CPP代码:
#include "stdafx.h" void Fun(int x) { switch (x) { case 100: printf("100"); break; case 101: printf("101"); break; case 102: printf("102"); break; case 103: printf("103"); break; case 104: printf("104"); break; case 105: printf("105"); break; case 106: printf("106"); break; case 107: printf("107"); break; case 108: printf("108"); break; case 109: printf("109"); break; default: printf("None"); break; } } int main(int argc, char* argv[]) { Fun(102); return 0; }
反汇编:
Fun: 0040D7E0 push ebp 0040D7E1 mov ebp,esp 0040D7E3 sub esp,44h 0040D7E6 push ebx 0040D7E7 push esi 0040D7E8 push edi 0040D7E9 lea edi,[ebp-44h] 0040D7EC mov ecx,11h 0040D7F1 mov eax,0CCCCCCCCh 0040D7F6 rep stos dword ptr [edi] 0040D7F8 mov eax,dword ptr [ebp+8] 0040D7FB mov dword ptr [ebp-4],eax 0040D7FE mov ecx,dword ptr [ebp-4] 0040D801 sub ecx,64h ;64h=100 0040D804 mov dword ptr [ebp-4],ecx 0040D807 cmp dword ptr [ebp-4],9 0040D80B ja $L551+0Fh (0040d8b7) 0040D811 mov edx,dword ptr [ebp-4] 0040D814 jmp dword ptr [edx*4+40D8D5h] $L533: 0040D81B push offset string "100" (00422fc4) 0040D820 call printf (0040d760) 0040D825 add esp,4 0040D828 jmp $L551+1Ch (0040d8c4) $L535: 0040D82D push offset string "101" (00422fc0) 0040D832 call printf (0040d760) 0040D837 add esp,4 0040D83A jmp $L551+1Ch (0040d8c4) $L537: 0040D83F push offset string "102" (00422fbc) 0040D844 call printf (0040d760) 0040D849 add esp,4 0040D84C jmp $L551+1Ch (0040d8c4) $L539: 0040D84E push offset string "103" (00422fb8) 0040D853 call printf (0040d760) 0040D858 add esp,4 0040D85B jmp $L551+1Ch (0040d8c4) $L541: 0040D85D push offset string "104" (00422fb4) 0040D862 call printf (0040d760) 0040D867 add esp,4 0040D86A jmp $L551+1Ch (0040d8c4) $L543: 0040D86C push offset string "105" (00422fb0) 0040D871 call printf (0040d760) 0040D876 add esp,4 0040D879 jmp $L551+1Ch (0040d8c4) $L545: 0040D87B push offset string "106" (00422fac) 0040D880 call printf (0040d760) 0040D885 add esp,4 0040D888 jmp $L551+1Ch (0040d8c4) $L547: 0040D88A push offset string "107" (00422fa8) 0040D88F call printf (0040d760) 0040D894 add esp,4 0040D897 jmp $L551+1Ch (0040d8c4) $L549: 0040D899 push offset string "108" (00422fa4) 0040D89E call printf (0040d760) 0040D8A3 add esp,4 0040D8A6 jmp $L551+1Ch (0040d8c4) $L551: 0040D8A8 push offset string "109" (0042210c) 0040D8AD call printf (0040d760) 0040D8B2 add esp,4 0040D8B5 jmp $L551+1Ch (0040d8c4) 0040D8B7 push offset string "None" (00422f6c) 0040D8BC call printf (0040d760) 0040D8C1 add esp,4 0040D8C4 pop edi 0040D8C5 pop esi 0040D8C6 pop ebx 0040D8C7 add esp,44h 0040D8CA cmp ebp,esp 0040D8CC call __chkesp (004010a0) 0040D8D1 mov esp,ebp 0040D8D3 pop ebp 0040D8D4 ret
Memory:
0040D8D5 1B D8 40 00 .谸. 0040D8D9 2D D8 40 00 -谸. 0040D8DD 3F D8 40 00 ?谸. 0040D8E1 4E D8 40 00 N谸. 0040D8E5 5D D8 40 00 ]谸. 0040D8E9 6C D8 40 00 l谸. 0040D8ED 7B D8 40 00 {谸. 0040D8F1 8A D8 40 00 娯@. 0040D8F5 99 D8 40 00 欂@. 0040D8F9 A8 D8 40 00 ㄘ@.
Register:
EAX = 00000066 EBX = 7FFDB000 ECX = 00000002 EDX = 00000002 ESI = 00000000 EDI = 0012FF28 EIP = 0040D814 ESP = 0012FED8 EBP = 0012FF28 EFL = 00000297
小结:
起始值并不影响大表的生成,
edx = switch表达式的值 - case整型常量起始值
CPP代码:
#include "stdafx.h" void Fun(int x) { switch (x) { case 100: printf("100"); break; case 101: printf("101"); break; case 102: printf("102"); break; case 103: printf("103"); break; case 106: printf("106"); break; case 107: printf("107"); break; case 108: printf("108"); break; case 109: printf("109"); break; default: printf("None"); break; } } int main(int argc, char* argv[]) { Fun(102); return 0; }
反汇编:
Fun: 0040D7E0 push ebp 0040D7E1 mov ebp,esp 0040D7E3 sub esp,44h 0040D7E6 push ebx 0040D7E7 push esi 0040D7E8 push edi 0040D7E9 lea edi,[ebp-44h] 0040D7EC mov ecx,11h 0040D7F1 mov eax,0CCCCCCCCh 0040D7F6 rep stos dword ptr [edi] 0040D7F8 mov eax,dword ptr [ebp+8] 0040D7FB mov dword ptr [ebp-4],eax 0040D7FE mov ecx,dword ptr [ebp-4] 0040D801 sub ecx,64h 0040D804 mov dword ptr [ebp-4],ecx 0040D807 cmp dword ptr [ebp-4],9 0040D80B ja $L547+0Fh (0040d893) 0040D811 mov edx,dword ptr [ebp-4] 0040D814 jmp dword ptr [edx*4+40D8B1h] $L533: 0040D81B push offset string "100" (00422fbc) 0040D820 call printf (0040d760) 0040D825 add esp,4 0040D828 jmp $L547+1Ch (0040d8a0) $L535: 0040D82A push offset string "101" (00422fb8) 0040D82F call printf (0040d760) 0040D834 add esp,4 0040D837 jmp $L547+1Ch (0040d8a0) $L537: 0040D839 push offset string "102" (00422fb4) 0040D83E call printf (0040d760) 0040D843 add esp,4 0040D846 jmp $L547+1Ch (0040d8a0) $L539: 0040D848 push offset string "103" (00422fb0) 0040D84D call printf (0040d760) 0040D852 add esp,4 0040D855 jmp $L547+1Ch (0040d8a0) $L541: 0040D857 push offset string "106" (00422fac) 0040D85C call printf (0040d760) 0040D861 add esp,4 0040D864 jmp $L547+1Ch (0040d8a0) $L543: 0040D866 push offset string "107" (00422fa8) 0040D86B call printf (0040d760) 0040D870 add esp,4 0040D873 jmp $L547+1Ch (0040d8a0) $L545: 0040D875 push offset string "108" (00422fa4) 0040D87A call printf (0040d760) 0040D87F add esp,4 0040D882 jmp $L547+1Ch (0040d8a0) $L547: 0040D884 push offset string "109" (0042210c) 0040D889 call printf (0040d760) 0040D88E add esp,4 0040D891 jmp $L547+1Ch (0040d8a0) 0040D893 push offset string "None" (00422f6c) 0040D898 call printf (0040d760) 0040D89D add esp,4 0040D8A0 pop edi 0040D8A1 pop esi 0040D8A2 pop ebx 0040D8A3 add esp,44h 0040D8A6 cmp ebp,esp 0040D8A8 call __chkesp (004010a0) 0040D8AD mov esp,ebp 0040D8AF pop ebp 0040D8B0 ret
Memory:
0040D8B1 1B D8 40 00 .谸. 0040D8B5 2A D8 40 00 *谸. 0040D8B9 39 D8 40 00 9谸. 0040D8BD 48 D8 40 00 H谸. 0040D8C1 93 D8 40 00 撠@. ;缺失的104和105都跳转到0040D893 0040D8C5 93 D8 40 00 撠@. ;而0040D893是Default的语句块地址 0040D8C9 57 D8 40 00 W谸. 0040D8CD 66 D8 40 00 f谸. 0040D8D1 75 D8 40 00 u谸. 0040D8D5 84 D8 40 00 勜@.
Register:
EAX = 00000066 EBX = 7FFDE000 ECX = 00000002 EDX = 00000002 ESI = 00000000 EDI = 0012FF28 EIP = 0040D814 ESP = 0012FED8 EBP = 0012FF28 EFL = 00000297
小结:
空缺地址通过填充
default
语句块地址解决,但会造成内存浪费
CPP代码:
#include "stdafx.h" void Fun(int x) { switch (x) { case 100: printf("100"); break; case 101: printf("101"); break; case 102: printf("102"); break; case 106: printf("106"); break; case 108: printf("108"); break; case 112: printf("112"); break; case 115: printf("115"); break; default: printf("None"); break; } } int main(int argc, char* argv[]) { Fun(110); return 0; }
反汇编:
Fun: 0040D7E0 push ebp 0040D7E1 mov ebp,esp 0040D7E3 sub esp,44h 0040D7E6 push ebx 0040D7E7 push esi 0040D7E8 push edi 0040D7E9 lea edi,[ebp-44h] 0040D7EC mov ecx,11h 0040D7F1 mov eax,0CCCCCCCCh 0040D7F6 rep stos dword ptr [edi] 0040D7F8 mov eax,dword ptr [ebp+8] 0040D7FB mov dword ptr [ebp-4],eax 0040D7FE mov ecx,dword ptr [ebp-4] 0040D801 sub ecx,64h 0040D804 mov dword ptr [ebp-4],ecx 0040D807 cmp dword ptr [ebp-4],0Fh 0040D80B ja $L545+0Fh (0040d888) 0040D80D mov eax,dword ptr [ebp-4] 0040D810 xor edx,edx ;edx清零 0040D812 mov dl,byte ptr (0040d8c6)[eax] ;dl=[小表地址+eax] 0040D818 jmp dword ptr [edx*4+40D8A6h] $L533: 0040D81F push offset string "102" (00422fb4) 0040D824 call printf (0040d760) 0040D829 add esp,4 0040D82C jmp $L545+1Ch (0040d895) $L535: 0040D82E push offset string "1003\n" (00422fd8) 0040D833 call printf (0040d760) 0040D838 add esp,4 0040D83B jmp $L545+1Ch (0040d895) $L537: 0040D83D push offset string "109" (00422fac) 0040D842 call printf (0040d760) 0040D847 add esp,4 0040D84A jmp $L545+1Ch (0040d895) $L539: 0040D84C push offset string "1009\n" (00422fd0) 0040D851 call printf (0040d760) 0040D856 add esp,4 0040D859 jmp $L545+1Ch (0040d895) $L541: 0040D85B push offset string "108" (00422fa4) 0040D860 call printf (0040d760) 0040D865 add esp,4 0040D868 jmp $L545+1Ch (0040d895) $L543: 0040D86A push offset string "109" (00422fc8) 0040D86F call printf (0040d760) 0040D874 add esp,4 0040D877 jmp $L545+1Ch (0040d895) $L545: 0040D879 push offset string "115" (00422fc0) 0040D87E call printf (0040d760) 0040D883 add esp,4 0040D886 jmp $L545+1Ch (0040d895) 0040D888 push offset string "error\n" (00422f6c) 0040D88D call printf (0040d760) 0040D892 add esp,4 0040D895 pop edi 0040D896 pop esi 0040D897 pop ebx 0040D898 add esp,44h 0040D89B cmp ebp,esp 0040D89D call __chkesp (004010a0) 0040D8A2 mov esp,ebp 0040D8A4 pop ebp 0040D8A5 ret
Memory:
;大表 0040D8A6 1F D8 40 00 .谸. 0040D8AA 2E D8 40 00 .谸. 0040D8AE 3D D8 40 00 =谸. 0040D8B2 4C D8 40 00 L谸. 0040D8B6 5B D8 40 00 [谸. 0040D8BA 6A D8 40 00 j谸. 0040D8BE 79 D8 40 00 y谸. 0040D8C2 88 D8 40 00 堌@. ;小表 0040D8C6 00 01 02 07 .... 0040D8CA 07 07 03 07 .... 0040D8CE 04 07 07 07 .... 0040D8D2 05 07 07 06 ....
小表的解释:
当空缺值太多时内存的浪费也会变多,编译器当然知道这样不是办法,所以利用小表来解决这个问题。小表可以看作是一个智能蹦床,对于不同的玩家会给出不同的力,遇到没有付费的玩家(空缺值)直接将他抛出场外(给出参数,使其跳转到default
的语句块),遇到付费玩家(存在的值)则按照他的等级给出不同的力(给出参数,使其跳转到其对应的语句块)
可以看出,在小表中所有的空缺值都是07
(因为在这个样例中,当edx=7
时[edx*4+40D8A6h]
的地址为default
语句块的地址),而存在的值的对应值从0
递增。
CPP代码:
#include "stdafx.h" void Fun(int x) { switch (x) { case 301: printf("301"); break; case 302: printf("302"); break; case 303: printf("303"); break; case 304: printf("304"); break; case 305: printf("305"); break; case 306: printf("306"); break; case 307: printf("307"); break; case 308: printf("308"); break; case 309: printf("309"); break; case 3: printf("3"); break; default: printf("None"); break; } } int main(int argc, char* argv[]) { Fun(102); return 0; }
反汇编:
Fun: 0040D7E0 push ebp 0040D7E1 mov ebp,esp 0040D7E3 sub esp,44h 0040D7E6 push ebx 0040D7E7 push esi 0040D7E8 push edi 0040D7E9 lea edi,[ebp-44h] 0040D7EC mov ecx,11h 0040D7F1 mov eax,0CCCCCCCCh 0040D7F6 rep stos dword ptr [edi] 0040D7F8 mov eax,dword ptr [ebp+8] 0040D7FB mov dword ptr [ebp-4],eax 0040D7FE cmp dword ptr [ebp-4],131h ;0x131 = 305 0040D805 jg Fun+75h (0040d855) ;[ebp-4] > 305 跳转到0040d855 0040D807 cmp dword ptr [ebp-4],131h 0040D80E je Fun+0D7h (0040d8b7) ;[ebp-4] == 305 跳转到0040d8b7 0040D814 cmp dword ptr [ebp-4],12Eh ;0x12E = 302 0040D81B jg Fun+5Eh (0040d83e) ;[ebp-4] > 302 跳转到0040d855 0040D81D cmp dword ptr [ebp-4],12Eh 0040D824 je Fun+0A7h (0040d887) ;[ebp-4] == 302 跳转到0040d887 0040D826 cmp dword ptr [ebp-4],3 0040D82A je $L549+0Fh (0040d902) 0040D830 cmp dword ptr [ebp-4],12Dh 0040D837 je Fun+95h (0040d875) 0040D839 jmp $L549+1Eh (0040d911) 0040D83E cmp dword ptr [ebp-4],12Fh 0040D845 je Fun+0B9h (0040d899) 0040D847 cmp dword ptr [ebp-4],130h 0040D84E je Fun+0C8h (0040d8a8) 0040D850 jmp $L549+1Eh (0040d911) 0040D855 mov ecx,dword ptr [ebp-4] 0040D858 sub ecx,132h 0040D85E mov dword ptr [ebp-4],ecx 0040D861 cmp dword ptr [ebp-4],3 0040D865 ja $L549+1Eh (0040d911) 0040D86B mov edx,dword ptr [ebp-4] 0040D86E jmp dword ptr [edx*4+40D92Fh] 0040D875 push offset string "301" (00422fc4) 0040D87A call printf (0040d760) 0040D87F add esp,4 0040D882 jmp $L549+2Bh (0040d91e) 0040D887 push offset string "302" (00422fc0) 0040D88C call printf (0040d760) 0040D891 add esp,4 0040D894 jmp $L549+2Bh (0040d91e) 0040D899 push offset string "303" (00422fbc) 0040D89E call printf (0040d760) 0040D8A3 add esp,4 0040D8A6 jmp $L549+2Bh (0040d91e) 0040D8A8 push offset string "304" (00422fb8) 0040D8AD call printf (0040d760) 0040D8B2 add esp,4 0040D8B5 jmp $L549+2Bh (0040d91e) 0040D8B7 push offset string "305" (00422fb4) 0040D8BC call printf (0040d760) 0040D8C1 add esp,4 0040D8C4 jmp $L549+2Bh (0040d91e) $L543: 0040D8C6 push offset string "306" (00422fb0) 0040D8CB call printf (0040d760) 0040D8D0 add esp,4 0040D8D3 jmp $L549+2Bh (0040d91e) $L545: 0040D8D5 push offset string "307" (00422fac) 0040D8DA call printf (0040d760) 0040D8DF add esp,4 0040D8E2 jmp $L549+2Bh (0040d91e) $L547: 0040D8E4 push offset string "308" (00422fa8) 0040D8E9 call printf (0040d760) 0040D8EE add esp,4 0040D8F1 jmp $L549+2Bh (0040d91e) $L549: 0040D8F3 push offset string "309" (00422fa4) 0040D8F8 call printf (0040d760) 0040D8FD add esp,4 0040D900 jmp $L549+2Bh (0040d91e) 0040D902 push offset string "3" (0042210c) 0040D907 call printf (0040d760) 0040D90C add esp,4 0040D90F jmp $L549+2Bh (0040d91e) 0040D911 push offset string "None" (00422f6c) 0040D916 call printf (0040d760) 0040D91B add esp,4 0040D91E pop edi 0040D91F pop esi 0040D920 pop ebx 0040D921 add esp,44h 0040D924 cmp ebp,esp 0040D926 call __chkesp (004010a0) 0040D92B mov esp,ebp 0040D92D pop ebp 0040D92E ret
Memory:
0040D92F C6 D8 40 00 曝@. 0040D933 D5 D8 40 00 肇@. 0040D937 E4 D8 40 00 湄@. 0040D93B F3 D8 40 00 筘@.
小结:
此时的结构称为树型结构,间断大于256时的一种反汇编结构,类似于二分查找
switch
适用于其值为连续近似的情况,在此情况下switch
的性能要高于if多分支
,其因为switch利用索引的原理,完成以空间换时间。在不同的情况下,switch
的反汇编会有所不同,大致分为四种情况,1.类似于if
;2.使用大表结构;3.使用大表+小表结构;4.使用树型结构。