C语言拾遗(五):分析switch语句机制
来源:互联网 发布:gps照相机软件下载 编辑:程序博客网 时间:2024/04/29 03:15
想要深入地理解语言的运行机理,阅读汇编代码是很有帮助的。
前奏:我们这里用的汇编代码格式是AT&T的,这个微软的intel格式不一样。
AT&T格式是GCC,OBJDUMP等一些其他我们在linux环境下常用工具的默认格式。
今天就一起再来看看switch语句吧。
关键词:跳转,跳转表
先来一个最简单的例子:
1 int switch_eg(int x, int n) 2 { 3 int result = x; 4 5 switch (n) { 6 case 100: 7 result += 10; 8 break; 9 case 102:10 result -= 10;11 break;12 default:13 result = 0; 14 }15 16 return result;17 }
看一下其汇编代码:我会逐条注释。
命令是gcc -O1 -S test2.c
1 .file "test2.c" 2 .text 3 .globl switch_eg 4 .type switch_eg, @function 5 switch_eg: 6 .LFB0: 7 .cfi_startproc 8 movl 4(%esp), %ecx //x在esp+4的位置,存入寄存器ecx 9 movl 8(%esp), %edx //n在esp+8的位置,存入寄存器edx10 leal 10(%ecx), %eax //将ecx的值+10存入eax,也就是x+1011 cmpl $100, %edx //将n和100比较12 je .L2 //n==100,跳到L213 subl $10, %ecx //n!=100,x=x-1014 cmpl $102, %edx //n和102比较15 movl $0, %eax //eax=016 cmove %ecx, %eax //如果n==102,eax=ecx17 .L2:18 rep //返回,result存在eax19 ret20 .cfi_endproc21 .LFE0:22 .size switch_eg, .-switch_eg23 .ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"24 .section .note.GNU-stack,"",@progbits
好了,对着注释看,是不是很简单呢。由此我们知道,switch语句实际上也是一种条件语句,而条件语句的核心是跳转。聪明的你应该还会想到跳转的标签个数应该是和case语句的分支个数成正比的。
可是,当case语句分支很多时,岂不是各种jmp?编译器很聪明的使用了一种叫跳转表的方法来解决这个问题。
其实也简单,跳转表的思想就是将要跳转的代码的地址存入一个数组中,然后根据不同的条件跳转到对应的地址处,就像访问数组一样。
空说太枯燥了,还是看个例子吧。(例子来源:深入理解计算机系统3.6.7)
C:
1 int switch_eg(int x, int n) { 2 int result = x; 3 switch (n) { 4 case 100: 5 result *= 13; 6 break; 7 8 case 102: 9 result += 10;10 /* fall throuth */11 12 case 103:13 result += 11;14 break;15 16 case 104:17 case 106:18 result *= result;19 break;20 21 default:22 result = 0;23 }24 25 return result;26 }
同样的看一下对应的汇编。我省略了一些无关的代码。
1 movl 4(%esp), %eax 2 movl 8(%esp), %edx 3 subl $100, %edx 4 cmpl $6, %edx 5 ja .L8 6 jmp *.L7(,%edx,4) 7 .section .rodata 8 .align 4 9 .align 410 .L7:11 .long .L312 .long .L813 .long .L414 .long .L515 .long .L616 .long .L817 .long .L618 .text19 .L3:20 leal (%eax,%eax,2), %edx21 leal (%eax,%edx,4), %eax22 ret23 .L4:24 addl $10, %eax25 .L5:26 addl $11, %eax27 ret28 .L6:29 imull %eax, %eax30 ret31 .L8:32 movl $0, %eax33 ret
解释一下关键点:
首先生成了一张跳转表,以L7为基准,4自己为对齐单位,加上偏移就能跳转到相应的标签。
比如,L7+0就是跳到L3处,L7+4就是跳转到L8处,依次类推。
7 .section .rodata 8 .align 4 9 .align 4
10 .L7:11 .long .L312 .long .L813 .long .L414 .long .L515 .long .L616 .long .L817 .long .L6
第6行: jmp *.L7(,%edx,4)
表示 goto *jt[index],举个例子,假设现在n是102,edx里面是2(102-100),查表得L7+2*4处,即跳到L4处。
23 .L4:24 addl $10, %eax
将eax的值+10,这和C是对应的。
8 case 102: 9 result += 10;
注意到L4后面没有ret了,这就是我们上篇所说的fall through规则。不清楚可以看一下上篇的例子C语言拾遗(四):分析switch语句机制---上篇。
好了,其他的分支,各位可以自己用其他例子验证一下,看是不是跟C语言代码逻辑是一样的,欢迎讨论。
小结:
swith语句的本质是条件语句,条件语句的本质是跳转。
当case分支多了的时候(一般大于四个时),编译器巧妙地通过跳转表来访问代码位置。
---End---
<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
- C语言拾遗(五):分析switch语句机制
- C语言拾遗(四):分析switch语句机制
- C语言switch语句
- C 语言 switch 语句
- C语言switch语句
- C语言switch语句
- C 语言 switch 语句
- C语言switch语句详解
- C语言 switch 语句用法
- C语言中的switch语句
- 6.3 C语言switch语句
- 54 C语言switch语句
- 【C语言】switch..case语句
- C语言拾遗(三):分析C语言声明
- C语言switch语句的汇编语言实现
- C语言switch语句的汇编语言实现
- C语言的switch语句跳转问题
- C语言switch语句的汇编语言实现
- 【算法和数据结构】_3_线性结构_栈
- 每日一c--文件重定向-pdup = dup2(pf_1, pf_2);/
- uva562 - Dividing coins(简单动规)
- 【算法和数据结构】_2_顺序表
- 什么是DDOS攻击
- C语言拾遗(五):分析switch语句机制
- 栈(stack)与堆(heap)
- 调试单向链表遇到问题总结
- mini2440 安装OpenWrt 过程记录
- sourceinsight如何显示完整文件路径
- 写自己的分页控件
- 今天开学Oralce 现在坚持每天写技术文档,也就是笔记了!!
- OpenCV实现RGB颜色空间和HSI颜色空间的相互转换
- C++读书笔记之纯虚函数pure virtual function