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语句是如何变成汇编代码的?的更多相关文章

  1. 分析一个C语言程序生成的汇编代码-《Linux内核分析》Week1作业

    署名信息 郭春阳 原创作品转载请注明出处 :<Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 C源码 这 ...

  2. c语言中函数调用的本质从汇编角度分析

    今天下午写篇博客吧,分析分析c语言中函数调用的本质,首先我们知道c语言中函数的本质就是一段代码,但是给这段代码起了一个名字,这个名字就是他的的这段代码的开始地址 这也是函数名的本质,其实也就是汇编中的 ...

  3. [SQL]SQL语言入门级教材_SQL语言基本语句介绍(四)

    SQL语言基本语句介绍 • 表的建立 关系数据库的主要特点之一就是用表的方式组织数据.表是SQL语言存放数据.查找数据以及更新数据的基本数据结构.在SQL语言中,表有严格的定义,它是一种二维表,对于这 ...

  4. 《Linux内核分析》week1作业-分析一个简单c语言的汇编代码

    1.C语言源码 #include <stdio.h> int g(int x){ ; } int f(int x){ return g(x); } int main(){ )+; } 2. ...

  5. 解析c语言背后的汇编代码

    源码 很简单的c语言代码,作用是交换两个数: #include <stdio.h> void swap(int * a, int * b) { *a = *a + *b - (*b = * ...

  6. Keil 中关于C语言编译生成汇编代码函数名规则

    在keil 中 C语言的函数有带参数和不带参数之分. 一般的资料里说fun(void)类型的函数不带参数,所以,keil编译器生成的汇编的调用地址(函数名) 为fun.这没有错.事实上,不管C语言的函 ...

  7. php入门 数据类型 运算符 语言结构语句 函数 类与面向对象

    php PHP-enabled web pages are treated just like regular HTML pages and you can create and edit them ...

  8. OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)

    OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...

  9. 浅析VS2010反汇编 VS 反汇编方法及常用汇编指令介绍 VS2015使用技巧 调试-反汇编 查看C语言代码对应的汇编代码

    浅析VS2010反汇编 2015年07月25日 21:53:11 阅读数:4374 第一篇 1. 如何进行反汇编 在调试的环境下,我们可以很方便地通过反汇编窗口查看程序生成的反汇编信息.如下图所示. ...

随机推荐

  1. 华为Awareness kit,您旅途路上的超智能管家

    前言 前段时间看了一部纪录片<中国游客在巴黎>,讲述了外国人眼中"中国式旅游":热衷景点打卡,沉迷拍照留念,无暇仔细欣赏:留足时间,买买买,不能枉此行.网友总结中国式旅 ...

  2. 题解 CF961G 【Partitions】

    题目传送门 题目大意 给出\(n,k\),以及\(w_{1,2,..,n}\),定义一个集合\(S\)的权值\(W(S)=|S|\sum_{x\in S} w_x\),定义一个划分\(R\)的权值为\ ...

  3. Windows用cmd编译运行C程序

    在Windows环境下用命令行编译运行程序 浙江大学-C语言程序设计进阶 配置gcc 准备一个Dev-cpp 找到gcc.exe所在目录 Dev-Cpp\MinGW64\bin 地址栏右键将地址复制为 ...

  4. git GUI Clients

    git GUI Clients Git 自带用于提交 (git-gui) 和浏览 (gitk) 的内置 GUI 工具,但也有一些第三方工具供寻求特定平台体验的用户使用. References Git ...

  5. Vim合并行

    日常常用到多行合并的功能,记录如下: 第一种, 多行合并成一行,即: AAAAABBBBBCCCCC 合并为:AAAAA BBBBB CCCCC 方法1: normal状态下 3J 其中的3是范围,可 ...

  6. 【UE4 C++】Tick的三种方式、异步蓝图节点

    Tick的三种方式 包括 默认 Tick (Actor.Component.UMG) TimerManager 定时器 FTickableGameObject 可以写原生 Object 也可以继承UO ...

  7. 395.至少有 K 个重复字符的最长子串

    题目 给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于k .返回这一子串的长度. 示例 1: 输入:s = "aaabb" ...

  8. Java:Object对象小记

    Java:Object对象小记 对 Java 中的 Object 对象,做一个微不足道的小小小小记 Object 的常用方法有哪些 clone() 方法:用于创建并返回当前对象的一份拷贝: 在Java ...

  9. 航胥:北航教务助手——Beta阶段发布声明

    下载地址在文章末尾! 这里是"航胥",一款更想要了解你的北航教务助手 Beta阶段,我们进化了! Beta阶段我们的新功能有: 课程评价功能 所有用户选过的课程都会在课程评价页面进 ...

  10. 2020BUAA软工个人博客作业

    2020BUAA软工个人博客作业 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业 我在这个课程的目标是 学 ...