switch分支语句

程序举例:

#include <stdio.h>
  int main()
  {
    int i=0;
    int j=0;
    switch(i)
    {
      case 1:
        j+=1;
        break;
      case 2:
        j+=2;
        break;
      case 3:
        j+=3;
        break;
      case 4:
        j+=4;
        break;
      case 5:
        j+=5;
      case 6:
        j+=70;
        break;
      default:
        j+=5;
        break;
    }
    return 0;
  }

通过指令gcc -S daima.c -o daima.s得到反汇编代码

1)先看看main函数部分:
注意:由于i>6和i<0时是default,把i看做无符号数与6比较,如果比6大,就跳转到.L2(结束)

main:
.LFB0:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$16, %esp

	movl	$0, -4(%ebp)  //i=0
	movl	$0, -8(%ebp)  //j=0

	cmpl	$6, -4(%ebp)
	ja	.L2   
//i>6跳转到地址.L2(这里把i看作无符号数,所以i为负数时也会跳转)
	movl	-4(%ebp), %eax
	sall	$2, %eax     //%eax=4*i
	addl	$.L9, %eax   //%eax=$.L9+4*i(.L9是个地址值)
	movl	(%eax), %eax
	jmp	*%eax

2)跳转表
.L9是个地址值,跳转表显示从地址.L9开始的一段连续地址空间里面存的内容(每四个字节就会存一个对应的地址值)

.L9://跳转表 .L9是个地址值
	.long	.L2  //i=0 l9~l9+3这4个字节内存放l2的地址
	.long	.L3  //i=1  l9+4~l9+7这4个字节存放l3的地址,后面同理
	.long	.L4
	.long	.L5
	.long	.L6
	.long	.L7
	.long	.L8
	.text	

3)分支代码段

.L3://case1 j+1
	addl	$1, -8(%ebp)
	jmp	.L10
.L4://case2 j+2
	addl	$2, -8(%ebp)
	jmp	.L10
.L5://case3 j+3
	addl	$3, -8(%ebp)
	jmp	.L10
.L6://case4 j+4
	addl	$4, -8(%ebp)
	jmp	.L10
.L7://case5 j+5
	addl	$5, -8(%ebp)
.L8://case6 j+70
	addl	$70, -8(%ebp)
	jmp	.L10
.L2://default
	addl	$5, -8(%ebp)
	nop
.L10:
	movl	$0, %eax
	leave
	ret

将分支条件调整为case 6,case 2,case 5,case 3,case 4,case 1(即交换一下分支条件顺序),观察跳转表的变化情况

.L8:
    addl    $70, -8(%ebp)//j+70
    jmp .L10
.L4:
    addl    $2, -8(%ebp)//j+2
    jmp .L10
.L7:
    addl    $5, -8(%ebp)//j+5
    jmp .L10
.L5:
    addl    $3, -8(%ebp)//j+3
    jmp .L10
.L6:
    addl    $4, -8(%ebp)//j+4
.L3:
    addl    $1, -8(%ebp)//j+1
    jmp .L10
.L2:
    addl    $5, -8(%ebp)//j+5
    nop
.L10:
    movl    $0, %eax
    leave

结果分析:
可以看到除了分支代码段不一样其余部分保持不变。
(1)分支代码段只做了顺序的调整,按照了case 6,case 2,case 5,case 3,case 4,case 1的顺序排布。
(2)但是很有趣的是,虽然代码的顺序变化了,但是.L和操作仍然是一一对应的!和以前一摸一样!这也说明gcc编译内部不是按照代码的绝对顺序来对应地址的,而是有一定的规则,比如说这里是按照j+1,j+2,j+3……来设置的。这说明了一个问题,switch对执行代码段的顺序做了优化。

注意:如果case语句数量过少,不会有跳转表,汇编代码直接用cmp jmp等跳转指令表示

部分内容参考:https://blog.csdn.net/weixin_44307065/article/details/105478981

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值