switch語句逆向


switch語句逆向

通過反匯編深入了解switch語句,並從中理解為何在某些情況下其性能優於if...else語句

語句結構

switch (整形表達式) {
    case 常量表達式1:
        語句塊;
        break;
    case 常量表達式2:
        語句塊;
        break;
    ......
    ......
    ......
    case 常量表達式n:
        語句塊;
        break;
    default:
        語句塊;
        break;
}

語句特點

  1. switch后的表達式的返回值必須是整型
  2. case后的表達式只能是整型常量,或整型常量構成的表達式
  3. 如果case后的語句塊中沒有包含break;,則會按順序執行其下面的語句塊,直到結束或遇到break;

從反匯編的角度觀察:

  1. 添加case后面的值,一個一個增加,觀察反匯編代碼的變化(何時生成大表)
  2. case的順序打亂,觀察反匯編代碼(觀察順序是否會影響生成大表)
  3. case后面的值改成從100開始到109,觀察反匯編的變化(觀察值較大時是否生成大表)
  4. 將連續的10項中抹去1項或2項,觀察反匯編有無變化(觀察大表空缺位置的處理)
  5. 10項中連續抹去,不要抹去最大值最小值(觀察何時生成小表)
  6. case后面的常量表達式改成毫不連續的值,觀察反匯編的變化

實例

case分支少的switch語句

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類似

case分支多的switch語句

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]即可確定跳轉地址

case后的值打亂順序

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.使用樹型結構。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM