c语言if语句是如何变成汇编代码的?
1. 要编译的测试代码:
int a;
int b = 3; int main(void)
{
if (3)
a = 4;
else
b = 5;
}
2. 词法分析
词法分析将c源代码解析成一个个的token。
关键的,将if两个字符解析成一个if token,后续语法分析的输入就从两个字符减少为1个token,减小了语法分析的难度。
3. 语法分析
if (equal(tok, "if")) {
Node *node = new_node(ND_IF, tok);
tok = skip(tok->next, "(");
node->cond = expr(&tok, tok);
tok = skip(tok, ")");
node->then = stmt(&tok, tok);
if (equal(tok, "else"))
node->els = stmt(&tok, tok->next);
*rest = tok;
return node;
}
如果当前处理的token是if,则
3.1创建新的类型为ND_IF的node。
3.2跳过if后面的"("。
3.3调用expr函数解析if语句()中的表达式,并将解析结果存储在node->cond。
3.4跳过“)”。
3.5调用stmt处理then语句块中的语句,这里是处理"a = 4;",将解析结果存储在node->then。
3.6如果if语句还有else部分,则调用stmt处理else语句块中的语句,这里是处理"b = 5;",将解析结果存储在node->els。
3.7node->cond,node->then,node->els都为node节点。
4. 代码生成
switch (node->kind) {
case ND_IF: {
int c = count();
gen_expr(node->cond);
cmp_zero(node->cond->ty);
println(" je .L.else.%d", c);
gen_stmt(node->then);
println(" jmp .L.end.%d", c);
println(".L.else.%d:", c);
if (node->els)
gen_stmt(node->els);
println(".L.end.%d:", c);
return;
}
...
如果当前处理的node节点类型为ND_IF,则
4.1gen_expr
这个函数处理if语句的条件部分,这里是处理3。判断node节点为NUM,会生成汇编语句"mov rax, 3",将3载入rax寄存器。
4.2cmp_zero
cmp_zero会生成汇编语句"cmp eax, 0",比较3和0。
4.3println(" je .L.else.%d", c);
该语句会生成汇编代码" je .L.else.1",当上条比较语句中eax为0时会执行跳转,跳转到else分支运行。这里由于eax为3,所以不跳转。
4.4gen_stmt(node->then);
这条语句会将then分支中的语句解析为汇编源码,这里是"a = 4;",这条语句是表达式语句,所以会调用gen_expr函数。
4.4.1gen_expr
"lea rax, a",将a的地址载入rax寄存器中。
"push rax",将rax入栈。
"mov rax, 4",将4载入rax寄存器中。
"pop rdi",将变量a的地址载入rdi寄存器。
"mov [rdi], eax",将4写入变量a。
4.5println(" jmp .L.end.%d", c);
执行完then分支代码后跳转到下一条语句处执行。
4.6println(".L.else.%d:", c);
插入一条标签,表示else分支代码的开始,如果if语句条件为0会跳转到这。
4.7gen_stmt(node->els);
生成else分支代码,处理"b = 5;"。
"lea rax, b",将变量b的地址载入rax寄存器。
"push rax",将rax寄存器入栈。
"mov rax, 5",将5载入rax寄存器。
"pop rdi",将b的地址载入rdi寄存器。
"mov [rdi], eax",将5写入变量b中。
4.8println(".L.end.%d:", c);
插入一条标签,表示if语句的结束,then分支语句执行完成后跳转到这里。
c语言if语句是如何变成汇编代码的?的更多相关文章
- 分析一个C语言程序生成的汇编代码-《Linux内核分析》Week1作业
署名信息 郭春阳 原创作品转载请注明出处 :<Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 C源码 这 ...
- c语言中函数调用的本质从汇编角度分析
今天下午写篇博客吧,分析分析c语言中函数调用的本质,首先我们知道c语言中函数的本质就是一段代码,但是给这段代码起了一个名字,这个名字就是他的的这段代码的开始地址 这也是函数名的本质,其实也就是汇编中的 ...
- [SQL]SQL语言入门级教材_SQL语言基本语句介绍(四)
SQL语言基本语句介绍 • 表的建立 关系数据库的主要特点之一就是用表的方式组织数据.表是SQL语言存放数据.查找数据以及更新数据的基本数据结构.在SQL语言中,表有严格的定义,它是一种二维表,对于这 ...
- 《Linux内核分析》week1作业-分析一个简单c语言的汇编代码
1.C语言源码 #include <stdio.h> int g(int x){ ; } int f(int x){ return g(x); } int main(){ )+; } 2. ...
- 解析c语言背后的汇编代码
源码 很简单的c语言代码,作用是交换两个数: #include <stdio.h> void swap(int * a, int * b) { *a = *a + *b - (*b = * ...
- Keil 中关于C语言编译生成汇编代码函数名规则
在keil 中 C语言的函数有带参数和不带参数之分. 一般的资料里说fun(void)类型的函数不带参数,所以,keil编译器生成的汇编的调用地址(函数名) 为fun.这没有错.事实上,不管C语言的函 ...
- php入门 数据类型 运算符 语言结构语句 函数 类与面向对象
php PHP-enabled web pages are treated just like regular HTML pages and you can create and edit them ...
- OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)
OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...
- 浅析VS2010反汇编 VS 反汇编方法及常用汇编指令介绍 VS2015使用技巧 调试-反汇编 查看C语言代码对应的汇编代码
浅析VS2010反汇编 2015年07月25日 21:53:11 阅读数:4374 第一篇 1. 如何进行反汇编 在调试的环境下,我们可以很方便地通过反汇编窗口查看程序生成的反汇编信息.如下图所示. ...
随机推荐
- SphereEx 登陆 ApacheCon Asia|依托 ShardingSphere 可插拔架构体系打造数据应用完整生态
2021 年 8 月 8 日,ApacheCon 首次亚洲大会于线上正式闭幕.作为久负盛名的开源盛宴,本届 ApacheCon Asia 受到了海内外众多开源领域人士的关注. 作为 Apache 软件 ...
- 七牛云的 python sdk 是如何 批量删除资源的
今天做项目的时候用到七牛云,关于对资源的操作是在后端做的,用的SDK,但是,在网上没找到详细的解析,官方文档也没有太详细的解说,所以无奈只好看下源码 这里做一下简单的记录 from qiniu imp ...
- 题解 [BJOI2019]奥术神杖
题目传送门 题目大意 给出一个残缺的字符串,每个位置都 \(\in[0,9]\).有 \(m\) 中贡献,即 \(s,k\),表示该字符串中没出现一次 \(s\),贡献便乘上 \(k\).最后对贡献求 ...
- 小数的十进制和二进数转换 “无限不循环”小数的IEEE 754表示
十进制 -> 二进制 将整数部分和小数部分分开处理 例:3.125(10) 其整数部分为11(2) 小数部分按照下面的步骤求解: 0.125 x 2 = 0.25 取0 0.250 x 2 = ...
- 【c++ Prime 学习笔记】第2章 变量和基本类型
2.1 基本内置类型 基本数据类型包含了算术类型(arithmetic type)和空类型(void) 算数类型,包含了字符.整型数.布尔值和浮点数 空类型,不对应具体的值 2.1.1 算术类型 算术 ...
- 【数据结构与算法Python版学习笔记】树——平衡二叉搜索树(AVL树)
定义 能够在key插入时一直保持平衡的二叉查找树: AVL树 利用AVL树实现ADT Map, 基本上与BST的实现相同,不同之处仅在于二叉树的生成与维护过程 平衡因子 AVL树的实现中, 需要对每个 ...
- MacOS安装使用Kettle
一.环境说明 操作系统版本:macOS Big Sur 11.6.1 机型:Intel版本 JDK版本:Amazon Corretto-openjdk8 Kettle版本:Kettle8.9 二.问题 ...
- Scrum Meeting 13
第13次例会报告 日期:2021年06月05日 会议主要内容概述: 团队成员均明确了下一步的目标,进度突飞猛进辣 一.进度情况 我们采用日报的形式记录每个人的具体进度,链接Home · Wiki,如下 ...
- 使用registry搭建docker私服仓库
使用registry搭建docker私服仓库 一.拉取 registry镜像 二.根据镜像启动一个容器 1.创建一个数据卷 2.启动容器 三.随机访问一个私服的接口,看是否可以返回数据 四.推送一个镜 ...
- sort命令的学习与实践
一.用man sort 查看sort的帮助文档 *sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出. [rocrocket@ro ...