1. 程式人生 > 其它 >Swithch反彙編(四種)

Swithch反彙編(四種)

------------恢復內容開始------------

Switch語法格式

Switch(表示式)
{
  case 常量表達式1:
       語句;
       break;
  case 常量表達式2:
       語句;
       break;
  case 常量表達式3:
       語句;
       break;
  default:
      語句;
       break;
}

Switch注意事項

  • case後面必須是常量表達式
  • case後常量表達式的值不一樣
  • switch後面表示式必須為整數型別其它型別諸如float double 等型別均不可以
  • case如果沒有新增break語句則會繼續向下執行下面的case
  • dafault語句可以沒有,如果所有case都不匹配會預設執行default語句

分支語句的增加之反彙編

分支語句少於等於3條與if—else語句的反彙編相同(case 值連續)

0040103E   cmp         dword ptr [ebp-4],1
00401042   je          tast+32h (00401052)
00401044   cmp         dword ptr [ebp-4],2
00401048   je          tast+41h (00401061)
0040104A   cmp         dword ptr [ebp-4],3
0040104E   je          tast+50h (00401070)
00401050   jmp         tast+5Fh (0040107f)
00401052   push        offset string "1" (00422028)
00401057   call        printf (00401130)
0040105C   add         esp,4
0040105F   jmp         tast+6Ch (0040108c)
00401061   push        offset string "2" (00422024)
00401066   call        printf (00401130)
0040106B   add         esp,4
0040106E   jmp         tast+6Ch (0040108c)
00401070   push        offset string "4" (00422020)
00401075   call        printf (00401130)
0040107A   add         esp,4
0040107D   jmp         tast+6Ch (0040108c)
0040107F   push        offset string "5" (0042201c)

分支語句大於三條生成一張大表(但是不一定,假如差值大的話就會生成if—else)(case後面的常量可以時無序的,並不影響大表的生成)編譯的時候就把地址排好了

#include "stdafx.h"
void test(int x)
{   
	
	switch(x)
	{
	case 2:
		printf("2");
		break;
	case 3:
		printf("3");
		break;
	case 4:
		printf("4");
		break;
	case 5:
		printf("5");
		break;
	case 6:
		printf("6");
		break;
	default:
		printf("5");
		break;
	}
}
int main(int argc, char* argv[])
{
	test(5);
	return 0;
}

case的值是從100-109彙編程式碼如下:

0040D7D8   mov         eax,dword ptr [ebp+8]
0040D7DB   mov         dword ptr [ebp-4],eax
0040D7DE   mov         ecx,dword ptr [ebp-4]
0040D7E1   sub         ecx,64h  // 這個是第一個case
0040D7E4   mov         dword ptr [ebp-4],ecx
0040D7E7   cmp         dword ptr [ebp-4],9  //這是case的總個數 :9+1
0040D7EB   ja          $L550+0Fh (0040d897)
0040D7F1   mov         edx,dword ptr [ebp-4]
0040D7F4   jmp         dword ptr [edx*4+40D8B5h]//這就是生成的表
$L532:
0040D7FB   push        offset string "100" (00422fc0)
0040D800   call        printf (00401130)
0040D805   add         esp,4
0040D808   jmp         $L550+1Ch (0040d8a4)
$L534:
0040D80D   push        offset string "101" (00422fbc)
0040D812   call        printf (00401130)
0040D817   add         esp,4
0040D81A   jmp         $L550+1Ch (0040d8a4)
$L536:
0040D81F   push        offset string "102" (00422fb8)
0040D824   call        printf (00401130)
0040D829   add         esp,4
0040D82C   jmp         $L550+1Ch (0040d8a4)
$L538:
0040D82E   push        offset string "103" (00422fb4)
0040D833   call        printf (00401130)
0040D838   add         esp,4
0040D83B   jmp         $L550+1Ch (0040d8a4)
$L540:
0040D83D   push        offset string "104" (00422fb0)
0040D842   call        printf (00401130)
0040D847   add         esp,4
0040D84A   jmp         $L550+1Ch (0040d8a4)
$L542:
0040D84C   push        offset string "105" (00422fac)
0040D851   call        printf (00401130)
0040D856   add         esp,4
0040D859   jmp         $L550+1Ch (0040d8a4)
$L544:
0040D85B   push        offset string "106" (00422f5c)
0040D860   call        printf (00401130)
0040D865   add         esp,4
0040D868   jmp         $L550+1Ch (0040d8a4)
$L546:
0040D86A   push        offset string "107" (00422028)
0040D86F   call        printf (00401130)
0040D874   add         esp,4
0040D877   jmp         $L550+1Ch (0040d8a4)
$L548:
0040D879   push        offset string "108" (00422024)
0040D87E   call        printf (00401130)
0040D883   add         esp,4
0040D886   jmp         $L550+1Ch (0040d8a4)
$L550:
0040D888   push        offset string "109" (00422020)
0040D88D   call        printf (00401130)
0040D892   add         esp,4
0040D895   jmp         $L550+1Ch (0040d8a4)
0040D897   push        offset string "6" (0042201c)
0040D89C   call        printf (00401130)

說明ja 指令 jump above,大於時跳轉(無符號),也就是比較引數x-1和3(case中的最大差值),最大差值就是最大值減最小值

得出的結論會給生成一個大表來直接查詢

我們假如把case裡面的值刪除兩個項會發生什麼變化

#include<stdio.h>
#include "stdafx.h"
void test(int x)
{   
	
	switch(x)
	{
	case 100:
		printf("100");
		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("5");
		break;
	}
}
int main(int argc, char* argv[])
{
	test(106);
	return 0;
}



總結刪除兩個時,編譯器仍然生成大表來儲存,沒有case的值 會儲存預設的地址

當刪除到6個時編譯器會幫我們建立小表

#include<stdio.h>
#include "stdafx.h"
void test(int x)
{   
	
	switch(x)
	{
	case 100:
		printf("100");
		break;

	case 107:
		printf("107");
		break;
	case 108:
		printf("108");
		break;
	case 109:
		printf("109");
		break;
	default:
		printf("5");
		break;
	}
}
int main(int argc, char* argv[])
{
	test(106);
	return 0;
}






小表用來存放並不存在的case,然後通過大表來尋找到default

case後面常量表達式改成好不連續的值

#include<stdio.h>
#include "stdafx.h"
void test(int x)
{   
	
	switch(x)
	{
	case 1:
		printf("100");
		break;

	case 5:
		printf("107");
		break;
	case 200:
		printf("108");
		break;
	case 9:
		printf("109");
		break;
	case 300:
		printf("109");
		break;
	default:
		printf("5");
		break;
	}
}
int main(int argc, char* argv[])
{
	test(103);
	return 0;
}

------------恢復內容結束------------