switch case 分支语句汇编分析

switch汇编语句分析包含以下四种不同的情况:

1.当case分支较少的时候

2.当case分支较多且连续的时候

3.当case分支较多且连续,中间删除某一个分支的时候

4.当case分支较多且连续,中间删除多个分支的时候

情况一:当case当中的分支语句较少的时候,其对应的汇编分析

#include<stdlib.h>
#include<stdio.h>
void function(int a) {
	switch (a)
	{
	case 1:
		printf("1");
		break;
	case 2:
		printf("2");
		break;
	default:
		printf("3");
		break;
	}
}
int main() {
	function(2);
	//function(1);
	return 0;
}

对应的汇编程序为:

void function(int a) {
00007FF7704D18D0  mov         dword ptr [rsp+8],ecx  
00007FF7704D18D4  push        rbp  
00007FF7704D18D5  push        rdi  
00007FF7704D18D6  sub         rsp,0F8h  
00007FF7704D18DD  lea         rbp,[rsp+20h]  
00007FF7704D18E2  mov         rdi,rsp  
00007FF7704D18E5  mov         ecx,3Eh  
00007FF7704D18EA  mov         eax,0CCCCCCCCh  
00007FF7704D18EF  rep stos    dword ptr [rdi]  
00007FF7704D18F1  mov         ecx,dword ptr [rsp+118h]  
00007FF7704D18F8  lea         rcx,[__E4547C95_file1@c (07FF7704E1003h)]  
00007FF7704D18FF  call        __CheckForDebuggerJustMyCode (07FF7704D1082h)  
	switch (a)
00007FF7704D1904  mov         eax,dword ptr [a]  
00007FF7704D190A  mov         dword ptr [rbp+0C0h],eax  
00007FF7704D1910  cmp         dword ptr [rbp+0C0h],1  
00007FF7704D1917  je          function+54h (07FF7704D1924h)  
00007FF7704D1919  cmp         dword ptr [rbp+0C0h],2  
00007FF7704D1920  je          function+62h (07FF7704D1932h)  
00007FF7704D1922  jmp         function+70h (07FF7704D1940h)  
	{
	case 1:
		printf("1");
00007FF7704D1924  lea         rcx,[string "1" (07FF7704D9C10h)]  
00007FF7704D192B  call        printf (07FF7704D11D1h)  
		break;
00007FF7704D1930  jmp         function+7Ch (07FF7704D194Ch)  
	case 2:
		printf("2");
00007FF7704D1932  lea         rcx,[string "2" (07FF7704D9C14h)]  
00007FF7704D1939  call        printf (07FF7704D11D1h)  
		break;
00007FF7704D193E  jmp         function+7Ch (07FF7704D194Ch)  
	default:
		printf("3");
00007FF7704D1940  lea         rcx,[string "3" (07FF7704D9C18h)]  
00007FF7704D1947  call        printf (07FF7704D11D1h)  
		break;
	}
}

汇编分析:

情况一总结:

当switch当中case分支较少的时候,其对应的汇编程序和if else 语句当中所对应的汇编程序语言和逻辑基本相同。

先获到要比较的目标参数值对象,然够将该参数值对象存放到存放外部参数的栈内存空间当中去。

从栈内存空间当中获取到目标参数值对象,以此与case分支语句当中的条件值进行对比,当二者相同的时候,则直接跳转到对应case分支语句所在的内存空间位置处,否则继续和下一个case分支语句进行比较。

当所比较的所有case分支语句都不符合的时候,直接跳转到default所对应的分支语句当中去。

情况二:

       当switch当中的case语句有多条且有序的时候,其对应的汇编程序分析:

#include <stdlib.h>
#include<stdio.h>
void function(int a){
    switch (a)
    {
    case 1:
        printf("1");
        break;
    case 2:
        printf("2");
        break;
    case 3:
        printf("3");
        break;
    case 4:
        printf("4");
        break;
    case 5:
        printf("5");
        break;
    default:
        printf("error");
        break;
    }
}
int main(int argc, char const *argv[])
{
    function(3);
    return 0;
}

汇编分析:

情景二总结:当switch case语句当中多条case连续的时候将会进行以下执行方式:

       根据当前接收到的参数值a-1(case语句当中第一个值)来计算出偏移量

       判断当前偏移量是否大于default语句当中的偏移量,如果大于则直接跳转到default语句对应处进行执行。

       当偏移量小于default语句处所对应的偏移量的时候,通过计算查找记录所有case分支语句对应的内存位置的数据表来跳转到当前偏移量所对应的case分支语句所在的位置。

情景三:

       当在连续的case语句当中删除某一条语句之后对其对应的汇编进行分析。

程序依然为情景二当中的程序,不同的是将case3条件分支语句进行删除之后进行执行。对应的汇编如图所示:

情景三总结:

       当在多个连续的case分支语句当中删除某几个case分支语句之后,被删除的case分支语句所对应的大表当中所对应的程序内存的跳转地址将会被default分支语句所在的内存地址进行替代。

情景四:

       当在switch case语句当中删除多个连续的case语句之后,其存储方式将会发生改变。因为如果继续采用对删除的case分支语句当中大表对应处地址用default分支来进行替代的话,则会浪费大量的内存空间。

#include <stdlib.h>
#include<stdio.h>
void function(int a){
    switch (a)
    {
    case 1:
        printf("1");
        break;
    case 9:
        printf("9");
        break;
	case 10:
        printf("10");
        break;
	case 11:
        printf("11");
        break;
	case 12:
        printf("12");
        break;
    default:
        printf("error");
        break;
    }
}
int main(int argc, char const *argv[])
{
    function(12);
    return 0;
}

汇编分析:

根据小表当中的值在对大表进行二次查询:

情景四总结:

       当switch case语句当中有多个连续的case分支语句被省略之后,编译器将会改变数据的存放方式不在继续在大表当中用default分支语句所对应的内存地址来替代被省略的分支语句。

       首先获取参数值并计算偏移量和default分支编译量进行比较,当大于default分支的偏移量的时候,则直接跳转到default分支语句当中进行执行操作。

       当小于default分支语句的时候,对小表进行数据的查询,因为在小表当中存放了所有case分支语句所对应的一级偏移量(包括省略的case分支语句),并且由于小表当中的每个分支所对应的一级偏移量只有一个字节,而大表当中的二级偏移量则为4个字节,所以当有多个省略的case分支的时候,能够有效的节约内存空间。

       当找到小表当中对应的一级偏移量之后,然后到大表当中进行查询可以获取到二级偏移量,也就是当前偏移所对应的case语句所在的内存空间的位置。

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值