0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

解答编译器是怎样运行的

GReq_mcu168 来源:码农的荒岛求生 作者:码农的荒岛求生 2021-03-09 15:20 次阅读

对于程序员来说编译器是非常熟悉的,每天都在用,但是当你在点击“Run”这个按钮或者执行编译命令时你知道编译器是怎样工作的吗?

这篇文章就为你解答这个问题。

编译器就是一个普通程序,没什么大不了的

什么是编译器?

编译器是一个将高级语言翻译为低级语言的程序。

首先我们一定要意识到编译器就是一个普通程序,没什么大不了的。

在没有弄明白编译器如何工作之前你可以简单的把编译器当做一个黑盒子,其作用就是输入一个文本文件输出一个二进制文件。

基本上编译器经过了以下几个阶段,等等,这句话教科书上也有,但是我相信很多同学其实并没有真正理解这几个步骤到底在说些什么,为了让你彻底理解这几个步骤,我们用一个简单的例子来讲解。

假定我们有一段程序:

while (y < z) { int x = a + b; y += x;}

那么编译器是怎样把这一段程序人类认识的程序转换为CPU认识的二进制机器指令呢?

提取出每一个单词:词法分析

首先编译器要把源代码中的每个“单词”提取出来,在编译技术中“单词”被称为token。其实不只是每个单词被称为一个token,除去单词之外的比如左括号、右括号、赋值操作符等都被称为token。

从源代码中提取出token的过程就被称为词法分析,Lexical Analysis。

经过一遍词法分析,编译器得到了以下token:

T_While whileT_LeftParen (T_Identifier yT_Less

就这样一个磁盘中保存的字符串源代码文件就转换为了一个个的token。

这些token想表达什么意思:语法分析

有了这些token之后编译器就可以根据语言定义的语法恢复其原本的结构,怎么恢复呢?

原来,编译器在扫描出各个token后根据规则将其用树的形式表示出来,这颗树就被称为语法树。

语法树是不是合理的:语义分析

有了语法树后我们还要检查这棵树是不是合法的,比如我们不能把一个整数和一个字符串相加、比较符左右两边的数据类型要相同,等等。

这一步通过后就证明了程序合法,不会有编译错误。

根据语法树生成中间代码:代码生成

语义分析之后接下来编译器遍历语法树并用另一种形式来表示,用什么来表示呢?那就是中间代码,intermediate representation code,简称IR code

上述语法树可能就会表示为这样的中间代码:

Loop: x = a + b y = x + y _t1 = y < z if _t1 goto Loop

怎么样,这实际上已经比较接近最后的机器指令了。

只不过这还不是最终形态。

中间代码优化

在生成中间代码后要对其进行优化,我们可以看到,实际上可以把x = a + b这行代码放到循环外,因为每次循环都不会改变x的值,因此优化后就是这样了:

x = a + bLoop: y = x + y _t1 = y < z if _t1 goto Loop

中间代码优化后就可以生成机器指令了。

代码生成

将上述优化后的中间代码转换为机器指令:

add $1, $2, $3Loop: add $4, $1, $4 slt $6, $1, $5 beq $6, loop

最终,编译器将程序员认识的代码转换为了CPU认识的机器指令。

总结

注意这篇简短的讲解不希望给大家留下这样的印象,那就是编译器是很简单的,恰恰相反,现代编译器是非常智能并且极其复杂的,绝不是短短一篇文章就能讲清楚的,能实现一个编译器是困难的,实现一个好的编译器更是难上加难。

本文的目的旨在以极简的方式描述编译器的工作原理,这样你就不用把编译器当做一个黑盒了,希望这篇文章能对你有所帮助。
编辑:lyn

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编译器
    +关注

    关注

    1

    文章

    1577

    浏览量

    48627

原文标题:编译器是如何工作的

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    QT开发学习笔记1(安装交叉编译器

    QT安装交叉编译器
    的头像 发表于 02-18 10:02 369次阅读
    QT开发学习笔记1(安装交叉<b class='flag-5'>编译器</b>)

    编译器的优化选项

    这一点,需要了解编译器的能力和限制;第三,要了解硬件的运行方式,针对硬件特性进行优化。本文着重展开第二点和第三点。 简单认识编译器 要写出高性能的代码,首先需要对编译器有基础的了解,原
    的头像 发表于 11-24 15:37 413次阅读
    <b class='flag-5'>编译器</b>的优化选项

    嵌入式javascript编译器的设计与实现

    电子发烧友网站提供《嵌入式javascript编译器的设计与实现.pdf》资料免费下载
    发表于 10-30 11:29 0次下载
    嵌入式javascript<b class='flag-5'>编译器</b>的设计与实现

    新版编译器的设计思路和优化方法

    小程序编译器在小程序开发、预览、发布各个阶段都需要使用,因此编译器性能会直接影响到开发者开发效率,也会影响到开发者工具的使用体验。 由于旧版的编译器(基于 webpack4)在构建大型项目时会很慢,内存占用也高,一直被开发者吐槽
    发表于 10-13 11:21 152次阅读
    新版<b class='flag-5'>编译器</b>的设计思路和优化方法

    嵌入式开发中的C语言编译器设置

    编译器的语义检查很弱小,甚至还会“掩盖”错误。现代的编译器设计是件浩瀚的工程,为了让编译器设计简单一些,目前几乎所有编译器的语义检查都比较弱小。为了获得更快的执行效率,C语言被设计的足
    发表于 10-11 12:43 280次阅读

    esp32除了用arduino编译器还可以用哪个编译器

    esp32除了用arduino编译器还可以用哪个编译器
    发表于 09-25 06:13

    Keil修改ARM编译器及配置方法

    Keil MDK自 V5.36 版本之后,默认就不带 Arm Compiler V5版本编译器。如果需要使用 V5 版本编译器,就需要自己下载并安装。
    发表于 09-19 10:41 2246次阅读
    Keil修改ARM<b class='flag-5'>编译器</b>及配置方法

    如何安装ARM编译器Linux版

    。 注意:ARM编译器Linux版运行在64位ARM硬件上,它不是交叉编译器。 有关兼容性的详细信息,请参阅支持的平台。
    发表于 08-28 06:45

    Arm编译器6.6版armclang参考指南

    Arm®编译器armclang参考指南提供了Arm编译器armclaang的用户信息。armclang是一个优化的C和C++编译器,它将标准C和标准C++源代码编译为基于Arm体系结构
    发表于 08-11 07:35

    如何实现VBA编译器崩溃

    本篇文章为VBA脚本隐藏技术的最后一篇,将介绍如何在保证VBA脚本正常执行的情况下,使分析人员无法打开编译器
    发表于 07-15 10:02 463次阅读
    如何实现VBA<b class='flag-5'>编译器</b>崩溃

    编译器的标准生命周期

    编译器的标准生命周期
    发表于 07-05 19:32 0次下载
    <b class='flag-5'>编译器</b>的标准生命周期

    Neuron 现场编译器用户指南

    Neuron 现场编译器用户指南
    发表于 07-04 20:47 0次下载
    Neuron 现场<b class='flag-5'>编译器</b>用户指南

    SDCC-Linux下的51 MCU编译器

    SDCC (小型设备C编译器)是为8位微控制器开发的免费C编译器。尽管兼容多种不同体系结构,但SDCC C编译器更适合8051内核。 SDCC是命令行固件开发工具,含预处理器、编译器
    的头像 发表于 06-16 15:19 3690次阅读

    使用Arduino IDE编译器指令的疑问求解

    代码中看到了很多编译器指令。LOCAL void ICACHE_FLASH_ATTR some_function(int a, char*c)之类的指令我假设这些指令告诉链接将代码放在运行串行闪存
    发表于 06-12 07:01

    CA850 Ver.3.20 C编译器运行

    CA850 Ver.3.20 C编译器运行
    发表于 05-04 19:03 0次下载
    CA850 Ver.3.20 C<b class='flag-5'>编译器</b><b class='flag-5'>运行</b>包