编译原理第一章

news2024/10/6 8:37:26

编译原理笔记

文章目录

  • 编译原理笔记
    • day1
      • 什么是编译?
      • 编译器的结构
      • 词法分析概述
        • 词法分析的主要任务
      • 语法分析概述
        • 主要目的
        • 主要任务
        • 具体实例
      • 语义分析概述
        • 主要目的
        • 主要任务
      • 中间代码生成和编译器后端
        • 常用的中间表示形式
        • 目标代码生成器
        • 代码优化器

day1

什么是编译?

在这里插入图片描述

机器语言:机器语言,又称机器码或二进制指令,是计算机能够直接执行的最底层的语言。它由“0”和“1”组成的二进制代码组成,代表了特定的操作指令和操作数。计算机利用硬件电路执行机器语言指令,它是一种非常原始和低级别的语言,通常很难被人类理解和编写。汇编语言:汇编语言是机器语言的一种相对易于理解和编写的形式,它通过使用助记符(mnemonics)来代替二进制码,使得程序更易于编写和理解。

汇编语言把程序员编写的指令翻译成具有相同功能的机器语言指令,并且提供了方便的符号和标签来引用内存地址和操作数。在汇编语言中,程序员需要手动处理计算机内存的分配和管理,这使得汇编语言在编写操作系统、设备驱动程序和嵌入式系统等方面非常有用。

高级语言:高级语言是相对于机器语言和汇编语言而言的,它是一种更为人性化和易于理解的程序设计语言。高级语言使用英语单词、符号和表达式等符号来表示计算机指令和操作,它提供了更高层次的抽象,隐藏了许多底层的细节,并且通常比机器语言和汇编语言更易于学习和编写。一些常见的高级语言包括C、C++、Python、Java、JavaScript等。在编写高级语言程序时,程序员无需关注计算机的底层细节,程序的执行由编译器或解释器负责将高级语言翻译成底层的机器语言或汇编语言,然后交给计算机执行。

在这里插入图片描述

预处理器:预处理器(Preprocessor)是一个独立于编译器的程序,它在编译源代码之前对代码进行处理。预处理器能够识别并处理以#开头的特殊指令,例如#include和#define,它们通常用于引入头文件、宏定义和条件编译等。预处理器的主要作用是对源代码进行预处理,生成一个被修改过的文本文件,这个文件将成为实际编译的源代码。

编译器:编译器(Compiler)是将高级语言源代码转换为目标机器的可执行代码的程序。编译器将源代码作为输入,并将其翻译成机器语言或汇编语言代码。编译器执行的过程包括词法分析、语法分析、中间代码生成、代码优化和目标代码生成等。编译器的主要功能是将高级语言源代码翻译成机器代码,使得计算机能够执行程序。

汇编器:汇编器(Assembler)是将汇编语言代码转换为机器语言代码的程序。它将汇编代码作为输入并将其翻译成二进制的机器码,这些机器码可以直接被计算机执行。汇编器的主要作用是将程序员编写的汇编语言代码翻译成机器语言代码,以便计算机可以理解和执行。

链接器:链接器(Linker)是一个程序,它将多个目标文件和库文件链接在一起,生成一个单独的可执行文件。目标文件是编译器生成的可重定位的机器代码文件,包含未解决的符号和地址信息。库文件是包含一组函数和变量定义的对象文件,它们被编译为可重定位的机器代码,并被组合成一个或多个库。链接器的主要作用是解决符号引用、地址重定位和代码合并等问题,生成一个完整的可执行程序。

编译器的结构

在这里插入图片描述

编译器通常由以下几个模块组成:

  1. 词法分析器(Lexer):将源代码输入到编译器中,词法分析器会对源代码进行扫描并将代码分解成多个词法单元(token),例如关键字、运算符、标识符等等。
  2. 语法分析器(Parser):对词法单元进行语法分析,检查代码是否符合语法规则。通常采用上下文无关文法(CFG)来描述语法规则,将词法单元转化为语法树。
  3. 语义分析器(Semantic Analyzer):在语法树的基础上进一步进行语义分析,如类型检查、变量声明等。如果存在语义错误,会报告错误并停止编译。
  4. 代码生成器(Code Generator):将语法树转化为目标代码,这个过程通常包括代码优化,包括去除无用代码、减少指令数等等。
  5. 目标代码生成器(Target Code Generator):将目标代码转化为机器码,完成编译过程。以上就是编译器大体的结构。当然,不同编译器在实现细节和组件划分上会存在差异。

词法分析概述

编译的第一个阶段,相当于你翻译一段英文语句你肯定是先看其词性

词法分析的主要任务

词法分析的主要任务是将源代码分解成词法单元(token),也称为词法分析单元(lexical unit),并将其传递给语法分析器。其主要任务包括:

1. 分离词法单元:对输入的源代码文件进行扫描,将代码分解成多个词法单元,如关键字、运算符、标识符、常数、字符串等等。

**2. 处理注释:**将注释从源代码中忽略掉,使其不被语法分析器处理。

**3. 处理空白符:**将空格、制表符和换行符等空白符忽略,不作为词法单元处理。

**4. 进行词法错误检查:**对无法识别的符号、不合法的标识符等进行错误检查,报告错误。

**5. 输出词法单元:**将词法单元以某种格式输出,方便后续的语法分析器处理。总的来说,词法分析器的主要任务是将源代码转化为为一系列词法单元,并将其传递给语法分析器进行后续处理。

相关例子

在这里插入图片描述

语法分析概述

主要目的

在语法分析的过程中,编译器会将词法分析器生成的词法单元流转化为抽象语法树(AST)。抽象语法树是一种树状数据结构,可以表示编程语言中的控制流、数据类型、操作符以及变量等等,是后续处理的基础。

主要任务

  1. 检查语法错误:对源代码进行扫描,检查代码是否符合语法规则,如果出现语法错误,将错误信息报告给程序员。
  2. 生成抽象语法树:将符合规则的代码转化为抽象语法树,方便后续的语义分析和代码生成处理。
  3. 语法分析器的设计:选择合适的语法分析算法,如递归下降分析、自底向上分析等,以及如何构建语法树等值得研究。

具体实例

在这里插入图片描述

在这里插入图片描述

语义分析概述

主要目的

语义分析是编译器中的一个重要组成部分,它的任务是在语法分析的基础上进一步检查程序的语义正确性。语义分析器会对抽象语法树(AST)进行处理,进行类型检查、变量声明、作用域检查等。

主要任务

语义分析的主要任务包括:

  1. 类型检查:检查变量、表达式、函数等的类型是否匹配,比如进行浮点数和整数类型之间的转换,或者检查类型不匹配的表达式计算。

  2. 变量声明:检查变量是否被正确声明,是否存在重复声明等问题。

  3. 作用域检查:检查变量、函数等的作用域是否正确,包括变量的生命周期、作用域的嵌套等。

  4. 常量折叠:常量表达式可以在编译时计算,将常量表达式折叠为常量值,提高代码的执行效率。

  5. 其他语义检查:如检查数组下标是否越界、函数调用参数数量是否匹配等。

    总的来说,语义分析是编译器中的一个重要环节,其主要目的是确保程序的语义正确性,发现并报告语义上的错误,并对程序进行必要的优化。语义分析通常在语法分析后进行,将抽象语法树(AST)作为输入,并生成带有语义意义的中间代码。

中间代码生成和编译器后端

常用的中间表示形式

三地址码|语法结构树/语法树

三地址码:

三地址码(three-address code)是一种中间代码表示形式,用于代码优化和生成的过程,在编译器、解释器等程序中广泛使用。它是一种将高级语言转化为低级机器语言的过程中间结果。

三地址码表示一个表达式时,将其分解为多个简单操作,每个简单操作只包含一个运算符和一些操作数。每个操作数都是一个临时变量或常量,被分配一个唯一的标识符。

三地址码通常由三个部分组成,分别是操作符、源操作数1源操作数2以及目标操作数,它们之间通过“=”符号分隔开来。例如:t1 = a + bt2 = 2 * t1c = t2 + d上面的代码包含三个简单操作,每个操作都有一个运算符和一些操作数。t1、t2、c 和 d 是临时变量或常量,它们在操作中被用作操作数和目标操作数。通过将高级语言转化为三地址码,可以方便进行代码的优化和生成。三地址码具有简洁、规范、易于生成和优化的优点,但其缺点是生成的代码比源代码更加冗长,会占用更多的存储空间。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

目标代码生成器

目标代码生成器是编译器的一个组成部分,主要用于将中间代码转化为目标机器代码,以便在目标计算机上运行程序。目标机器代码通常是特定机器或操作系统架构的二进制代码,如x86、ARM等。

目标代码生成器的主要任务是将中间代码串转化为目标机器码指令串。这个过程包含以下几个主要步骤:

  1. 寄存器分配:将每个变量映射到目标机器的物理寄存器,以便在运行时快速访问变量的值。
  2. 指令选择:根据目标机器的指令集,将中间代码转化为目标机器的指令,同时进行一些指令的优化,例如使用寄存器移位操作代替乘法操作。
  3. 块划分:将中间代码串分成基本块,每个块包含一组顺序执行的指令,可以轻松地转化为目标代码的基本块。
  4. 代码重排:通过修改指令顺序来减少条件跳转的使用和增加指令的并行度,从而提高程序的执行效率。
  5. 代码生成:将指令块转化为目标指令序列,并生成目标二进制代码。

代码优化器

代码优化器是编译器的一个重要组成部分,主要用于对生成的中间代码进行优化,以提高程序的执行效率和减少运行时间、内存占用等资源消耗。

代码优化器的主要任务是在不改变程序语义的情况下,对中间代码进行优化。它可以对代码进行静态分析,找出其中的潜在问题和瓶颈,并采取一系列优化手段来改善代码性能。

优化的方式多种多样,包括但不限于以下几种:

  1. 常量折叠:将常量表达式在编译期间计算,提高代码执行效率。

  2. 减少函数调用次数:将同一函数的多次调用合并为一次,减少函数调用开销。

  3. 死代码消除:将代码中不会被执行的语句删除,减少程序运行时间和内存占用。

  4. 循环展开:将循环的迭代次数展开,减少循环次数,提高代码执行效率。

  5. 寄存器分配:为变量选择最优的寄存器,减少内存访问次数,提高代码执行效率。

  6. 指令选择:选择最优的机器指令,减少指令执行时间,提高代码执行效率。

  7. 数据流分析:在程序运行时收集程序数据,并进行优化。

    代码优化器的优化效果直接影响程序的性能和运行效率。但是,进行代码优化的代价也很高,过度的优化可能会导致代码变得复杂难以维护,甚至会引入新的错误。因此,编译器开发人员需要权衡优化和代码的可读性、可维护性,以及对编译器开发成本的影响等因素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/426031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql 学习(一)基础知识(待更新)

文章目录服务端处理客户端请求启动项系统变量启动项和系统变量的区别常见的字符集字符集比较规则服务端处理客户端请求 客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果&am…

Idea使用样式主题

目的 花里胡哨的idea显示主题 安装插件 在preferences>plugins中搜索“Material Theme”安装两个中的一个 重启>设置>选择主题 对比度(多选) Contrast Mode:对比度模式,目录结构,选项卡等非文本选择前后的颜色对比度。…

Docker部署RabbitMQ(单机,集群,仲裁队列)

RabbitMQ部署指南 1.单机部署 我们在Centos7虚拟机中使用Docker来安装。 1.1.下载镜像 方式一:在线拉取 docker pull rabbitmq:3-management方式二:从本地加载 在课前资料已经提供了镜像包: 上传到虚拟机中后,使用命令加载镜…

【论文阅读】(20230410-20230416)论文阅读简单记录和汇总

(20230410-20230416)论文阅读简单记录和汇总 2023/04/09:很久没有动笔写东西了,这两周就要被抓着汇报了,痛苦啊呜呜呜呜呜 目录 (CVPR 2023): Temporal Interpolation Is All You Need for Dynamic Neural Radiance …

RPC 漫谈:序列化问题

RPC 漫谈:序列化问题 何为序列 对于计算机而言,一切数据皆为二进制序列。但编程人员为了以人类可读可控的形式处理这些二进制数据,于是发明了数据类型和结构的概念,数据类型用以标注一段二进制数据的解析方式,数据结…

echarts formatter如何自定义百分比小数位置,比如取整数。{b} {d}%

echarts formatter如何自定义百分比小数位置,比如取整数。{b} {d}% 一、现状 我有一个 pie 的图表,option 中的 formatter 是这样的: label: {show: true,position: outside,fontSize: 12,formatter: {b} {d}% },图表数据是这样的 二、需…

获取本地电脑连接的所有WIFI密码(适合Windows 11/10/8/7)

背景 如果你的心入职同事问你公司WIFI密码是多少,恰好这时你也忘记密码,用次方法可以实现得到WIFI密码。 如果你忘记现在在WIFI密码,也可以用此方法获取。 实现 1. 使用管理员权限打开 cmd.exe 2. 获取本机所有连接的 WIFI 用户配置 ne…

如何交叉编译程序:以freetype为例

【记录所学】 本博客为学习Linux开发时的笔记。主要记录如何交叉编译程序。 内容会首先介绍程序运行的一些基础知识,其次介绍常见错误的解决方法,然后介绍交叉编译程序的万能命令,最后以一个实际例子介绍如何交叉编译程序。 简要说明&#…

使用篇丨链路追踪(Tracing)很简单:链路实时分析、监控与告警

作者:涯海 前文回顾: 基础篇|链路追踪(Tracing)其实很简单 使用篇|链路追踪(Tracing)其实很简单:请求轨迹回溯与多维链路筛选 在前面文章里面,我们介绍了…

快排非递归 归并排序

递归深度太深会栈溢出 程序是对的&#xff0c;但是递归个10000层就是栈溢出 int fun(int n) {if (n < 1){return n;}return fun(n - 1) n; }所以需要非递归来搞快排和归并&#xff0c;在效率方面没什么影响&#xff0c;只是解决递归深度太深的栈溢出问题 有的能直接改&am…

2023年Android开发现状~

随着Android 开发行业的快速发展&#xff0c;市场需求也在不断提升&#xff0c;导致低端Android 开发市场就业大环境不好、行业趋势下滑&#xff0c;使得不少初中级的Android开发开始失业&#xff0c;找不到工作。 为什么这么说&#xff1f; 现在不像2012年——2018年的这段期…

性能调优通用逻辑

调优准备 定目标&#xff1a;根据线上预估访问量评估单场景QPS及混合场景QPS&#xff0c;和对应的RT值 环境区分&#xff1a; 测试环境单机压测进行链路问题排查问题&#xff0c;通常需要把单机打到CPU到100%&#xff0c;如果CPU到不了100%且请求已经各种超时或RT高于目标值…

Voting_Averaging算法预测银行客户流失率

Voting_Averaging算法预测银行客户流失率 描述 为了防止银行的客户流失&#xff0c;通过数据分析&#xff0c;识别并可视化哪些因素导致了客户流失&#xff0c;并通过建立一个预测模型&#xff0c;识别客户是否会流失&#xff0c;流失的概率有多大。以便银行的客户服务部门更…

【大型互联网应用轻量级架构实战の一】轻量级架构概述

1、轻量级架构概述 1.1.1、前言 当下&#xff0c;互联网应用呈高速发展的趋势&#xff0c;要想不被市场淘汰&#xff0c;就必须与时间赛跑&#xff0c;故而&#xff0c;快 就成了所有互联网公司产品的特征&#xff0c;只有率先推出产品&#xff0c;才能获取主动权。 1.1.2、…

大模型时代下的paper生存= =

第一类&#xff1a;PEFT类论文 &#xff08;我还挺喜欢的&#xff0c;不知道自己什么时候可以搞出这种工作 &#xff08;为什么中英文穿插&#xff0c;利于自己写论文&#xff1a;&#xff09; COMPOSITIONAL P ROMPT T UNING WITH M OTIONC UES FOR O PEN - VOCABULARY V ID…

构建数字时代下的必要防线 消除医疗行业数据安全建设“盲区”

4月7日&#xff0c;由厦门市卫生健康信息学会和厦门大学附属第一医院、厦门服云信息科技有限公司举办的医疗数据安全学术研讨会顺利开展。 作为国内云原生安全领导厂商&#xff0c;安全狗除了协助举办此次活动&#xff0c;还以数据安全治理专家的身份参与演讲分享。 厦门服云…

全网最详细,Jmeter性能测试-性能进阶, 无界面命令运行CLI模式(六)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 如果使用jmeter.bat…

代码随想录算法训练营第四十一天-动态规划3|343. 整数拆分 ,96.不同的二叉搜索树

343整数拆分&#xff0c;有两种解法&#xff0c;一种是数学的方法&#xff0c;利用当f>4时&#xff0c;2*&#xff08;f - 2&#xff09;2f - 4 > f的性质&#xff0c;将所有的因子都拆成3&#xff0c;最后的余数再乘进去。另外一种是动态规划&#xff0c;把前面的数拆了…

算法---文件的最长绝对路径

题目 假设有一个同时存储文件和目录的文件系统。下图展示了文件系统的一个示例&#xff1a; 这里将 dir 作为根目录中的唯一目录。dir 包含两个子目录 subdir1 和 subdir2 。subdir1 包含文件 file1.ext 和子目录 subsubdir1&#xff1b;subdir2 包含子目录 subsubdir2&…

PHP快速入门11-文件操作,附写入文件、文件重命名等20个高频使用案例

文章目录前言一、文件操作介绍二、 20个文件操作的例子2.1 打开文件并写入数据2.2 读取文件中的一行数据2.3 读取文件中的一个字符2.4 读取整个文件内容2.5 向文件写入内容2.6 将整个文件读入一个数组中2.7 删除文件2.8 重命名文件2.9 复制文件2.10 判断是否为文件2.11 判断是否…