if-else, while/for, switch-case
编译器:
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
if-else
一段c的代码
1 |
|
用gcc -c if-else.c
得到目标文件
用objdump -S if-else.o
查看代码段的汇编
1 | 0: 55 push %rbp |
理解:
- 0-f:喜闻乐见的函数开头,压入rbp寄存器的值(保存堆栈帧的基址),把栈指针rsp保存到rbp,栈顶指针下移16字节,(为局部变量保留空间),把x=1,y=2,压入栈中
- 16-1c:把x=1放入eax寄存器中,与y=2比较大小,如果不相等,跳转到2f处执行
- 1e-28:调用printf的一套操作,清空edi,eax,然后调用
- 2d:无条件跳转到3e段
- 2f-39:同1e-28
- 3e-44:喜闻乐见的函数结尾,把eax清零(返回值为0),恢复堆栈帧(恢复esp的值,弹出ebp的值),函数返回
while/for
一段c代码
1 |
|
代码段的汇编
1 | 0: 55 push %rbp |
理解:
- 0-4:函数头部
- 8:局部变量x=0入栈
- f:跳转29处
- 11-20:打印x的值
- 25:增加x的值
- 29-2d:比较9与x的值,小于或等于时跳转11处
- 2f:局部变量x=0入栈
- 36:跳转50处
- 38-47:打印x的值
- 4c:增加x的值
- 50-54:比较9与x的值,小于或等于时跳转38处
- 56-5c:函数尾部
(for和while的实现方式貌似差不多)
switch-case
一段c代码
1 |
|
代码段的汇编
1 | 0: 55 push %rbp |
理解:
- 0-4:函数头部
- 8:x = 1入栈
- f-1a:与1相比较,如果相等的话,跳转2c处,与2相比较,如果相等的话,跳转38处
- 1c-1e:尝试x与x的and运算,只改变标志位C,O,如果结果不为0,跳转44处
- 20-2a:调用printf函数,跳转4f处(case 0)
- 2c-36:调用printf函数,跳转4f处(case 1)
- 38-42:调用printf函数,跳转4f处(case 2)
- 44-49:调用printf函数(default)
- 4e:空指令
- 4f-55:函数尾部