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;
}

posted @ 2022-04-23 19:10  不会笑的孩子  阅读(102)  评论(0编辑  收藏  举报