C语⾔汇编代码分析(switchcase)
我们来看下⾯的例⼦:
switch-case控制语句维护着⼀张跳转表(jump table),并不是⽤⼀系列的if-else来实现,在上例中就是标签L7标记的地⽅。
跳转表⽅式⼤体思想是这样的:
⽤case语句中的最⼤值减去最⼩值求出⼀个区间,这⾥是106-100 = 6,即 0到6共有7个可能的case,此时编译器为该switch-case控制分配长度为7的数组,然后编译器再去查询哪些case是出现了的,就在数组中对应位置填上该case的地址(即L3,L4,L9,L6),如果没有对应的case就填写default对应的地址(即L2)。最后在执⾏的时候,只要⽤switch的参数(即n)减去case中的最⼩值,就可以得到⼀个索引,⽤这个索引就可以直接跳转到对应的case语句。这样⽐⽤if-else判断效率更⾼。
下⾯来具体分析下上⾯的汇编代码:
swithcase_asm:
pushl %ebp;函数管理⽤
movl %esp, %ebp;函数管理⽤
movl 8(%ebp), %eax;得到x
movl 12(%ebp), %edx;得到n
subl $100, %edx;⽤n-100存到%edx中
cmpl $6, %edx;⽐较%edx 与 6
ja .L2;如果%edx的值⽐6⼤则直接跳转到标签L2,即default
jmp *.L7(,%edx,4);如果⼩于等于6,在索引表中查后跳转到对应的case .section .rodata
.align 4
.align 4
.L7: ;跳转表
.long .L3
.
long .L2
.long .L4
.long .L9
.long .L6
.long .L2
.long .L6
.text
.L2: ;default
movl $0, %eax
jmp .L8
switch的用法c语言.L3: ;case 100
leal (%eax,%eax,2), %edx
leal (%eax,%edx,4), %eax
jmp .L8
.L4: ;case 102
addl $10, %eax
.L9: ;case 103
addl $11, %eax
jmp .L8
.L6: ;case 104,106
imull %eax, %eax
.L8:
popl %ebp
ret
但是如果都采⽤跳转表的⽅式会有⼀个问题,那就内存消耗,如果case语句中最⼤值和最⼩值相差较⼤,
那么会消耗掉⼤量的内存,接下来我们来看编译器在这种情况下是如何处理的:
我们将case 106改为case 1106,我们再看汇编代码,已经没有了跳转表的踪影了,没错,你猜对了,这种情况下编译器还是⽤了if-else 控制⽅式。不过也⽤⼆分查进⾏了优化(上⾯红⾊矩形框住的区域)。
那么通过上⾯的汇编分析,我们可以看出,在编写switch-case结构的时候,为了使程序运⾏更快,应该避免使⽤区间差距
太⼤的数。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论