编译技术-第1章-编译概述

编译概述

  • 编译:高级程序设计语言 翻译成 汇编语言或者机器语言

  • 编译程序或编译器:完成这项翻译工作的软件系统

程序设计语言

定义

人与计算机之间需要通信,通信就需要载体,程序设计语言就是这样的载体

  • 低级语言

    • 机器语言:二进制代码组成,计算机可直接执行,没设计出一种类型计算机,就多一种机器语言

    • 汇编语言:机器语言符号化

  • 高级语言

    • 与机器无关的语言,低级语言与机器有关

  • 翻译

    • 汇编语言 -> 汇编程序/汇编器(Assembler) -> 机器语言

    • 高级语言 -> 编译器(Compiler) -> 低级语言

分类

  • 强制式语言

    • 过程式语言,命令驱动,直接面向语句;一个程序由一系列语句组成,每句执行都引起存储单元值改变

  • 应用式语言

    • 更加注重程序功能,从简单函数开发出复杂函数,也称函数式语言

  • 基于规则式语言

    • 检查一定条件,满足某些值,就执行适当动作,也称为逻辑程序设计语言

  • 面向对象语言

    • 支持封装、继承、多态,通过对象构造可以使对象程序拥有强制式语言的有效性

程序设计语言发展

  • 第一代语言

    • 即机器语言,与机器孪生,完全依赖于机器的指令系统

  • 第二代语言

    • 即汇编语言,将机器语言符号化

  • 第三道语言

    • 即高级语言,设计基础与冯·诺依曼体系有关,按照语句顺序执行,又称命令式语言,也称过程式语言

  • 第四代语言

    • 即说明性语言,只需要告诉计算机去“做什么”,不需要描述过程,这一类语言也被称为超高级语言,比如SQL语言

  • 新一代语言

    • 脱离传统的冯·诺依曼系统约束,如量子编程、神经网络编程、人工智能编程、嵌入式编程等,如QCL、Rust等

    • 量子编程语言:书写量子计算与描述量子算法,从海量信息提取有效数据

    • 神经网络编程语言:针对神经网络算法的领域专用语言,可在多种系统下开发

    • 人工智能语言

    • 嵌入式语言

处理系统

  • 编译型:采用编译方法的语言处理器

  • 解释型:采用解释方法的语言处理器

  • 混合型:兼有编译与解释两种方法的语言处理器

编译程序与解释程序

翻译器是一种计算机程序,将一种编程语言(源程序)编写的计算机代码翻译成另一种语言(目标语言),包括编译与解释两种

  • 编译:将高级语言程序翻译成低级语言程序,实现程序为编译程序(编译器),如果编译目标程序为汇编语言程序,则目标程序还需要经过汇编程序;源程序->目标程序

  • 解释:将源程序转换成比较容易执行的中间代码(与机器代码有点不同),中间代码解释由软件支持,因为硬件解释器在这里不能直接使用,通常称支持这种解释的软件为解释程序或者解释器;所谓中间语言可以认为是一种虚拟计算机的机器语言,解释程序就是软件实现该虚拟计算机的模拟程序;源程序、初始数据->计算结果

解释型与编译型区别
解释器与编译器
  • 编译器:将源代码直接编译成目标平台的机器码,即可执行代码。运行过程中不需要依赖编译器

  • 解释器:逐行解释源代码,并转化成对应的目标平台的机器码执行。在运行过程中需要依赖解释器

解释型语言与编译型语言
  • 编译型:在运行前,编译器将源代码生成目标平台的可执行代码,运行时不需要依赖编译器

    • 编译型的语言指使用专门的编译器、针对特定平台(操作系统)将某种高级语言源代码一次性“翻译”成该平台硬件执行的机器码(包括机器指令和操作数),并包装成该平台所能识别的可执行性程序的格式,这个转换过程称为编译(Compile)。编译生成的可执行程序可以以脱离开发环境,在特定的平台上独立运行

    • 有些程序在编译结束之后,还可能需要对其他编译好的目标代码进行链接,即组装两个以上的目标代码模块生成最终的可执行程序,通过这种方式实现低层次的代码复用

    • 因为编译型语言是一次性的编译成机器码,所以可以脱离开发环境独立运行,而且通常运行效率较高

    • 但因为编译性语言的程序被编译成特定平台上的机器码,因此编译生成的可执行程序通常无法移植到其他平台上运行;如果需要移植,则必须将源代码复制到特定的平台上,针对特定的平台进行修改,至少也需要采用特定平台上的编译器重新编译

    • 比如我们现在的C、C++、Objective-C、Pasca等高级语言都属于编译型语言

  • 解释型:在运行时,通过解释器解析源代码执行程序。运行过程中依赖解释器

    • 解释型语言是指使用专门的解释器对源程序进行逐行解释成特定平台的机器码并立即执行的语言。解释型语言通常不会进行整体的编译和链接处理,解释型语言相当于把编译型语言中的编译和解释过程混合在一起同时完成

    • 可以这样认为:每次执行解释型语言的程序都需要进行一次编译,因此解释型语言的程序运行效率通常较低,而且它不能脱离解释器独立运行

    • 但解释性语言有一个优势:跨平台比较容易,只需提供特定平台的解释器即可,每个特定平台上的解释器负责将源程序解释成特定平台的机器指令即可。解释性语言可以方便的实现源程序的移植,但这是以牺牲程序执行效率为代价的

    • 比如我们现在的Java、Ruby、Python等高级语言都属于解释型语言

    • java的编译器先将其编译为class文件,也就是字节码;然后将字节码交由jvm(java虚拟机)解释执行;所以很多地方都说“java是一种半编译、半解释执行”的语言

程序语言处理系统
  • 输入程序:源程序,编写输入程序为源语言

  • 编译或者翻译:将高级语言源程序变换成语义等价的某种目标语言程序

    • 分析部分:当输入该语言程序后,程序语言处理系统首先确定是否符合语言定义,并且分析含义

    • 综合部分:语言处理系统必须把源程序变换成某种可以在计算机执行形式,并且输出的程序为目标程序或者目标代码,相应语言为目标语言

  • 目标程序:与源程序等价的目标语言程序

编译程序相关处理系统

将源程序翻译为目标程序,把某种语言程序变换与之等价的别的语言程序称为翻译程序或者变换程序

翻译程序

将一种语言编写程序转换为另一个完全等价的另一种语言的程序->翻译

源程序->翻译程序(宿主机)->目标程序

翻译程序的源程序除了通常的高级语言以外,还可以有说明、描述等形式非过程型语言

目标语言除了机器语言之外,还可以是其他高级语言、中间语言等

预处理器

在计算机科学中,预处理器(预编译器)是一种程序,它处理其输入数据以产生用作另一个程序输入的输出,输出被称为输入数据的预处理形式

预处理器把源程序变换为其他语言程序以后再进行编译,所以编译时出错信息的显示很难与源程序对应,程序调试也很困难

宏处理器

所谓宏,就是替换源程序中字符串的功能,或者通过inline把函数调用采用“所调用函数函数体”方式替换

宏处理器通常嵌入其他程序中,如汇编器和编译器,宏处理器和预处理器区别并不严密,C语言就在预处理器里包括了宏处理功能

编译程序

把源语言变换为目标语言

主要任务
  • 对源程序分析

  • 生成目标代码

分析部分将源程序分解为语言的各个基本语法成分,生成等价源代码中间形式

分析部分分成词法分析、语法分析、语义分析3个阶段

综合部分接收分析部分产生的中间代码,然后根据具体目标机系统生成目标代码,并且对代码进行优化

一般综合部分分为目标代码生成、代码优化两个阶段

  • 词法分析

    • 把源程序看成很长的字符串,从左到右scan,并且进行分析,识别符合语法规则单词,若出现不符合规则单词符号,就做出词法出错处理,给出出错信息

  • 语法分析

    • 对词法分析识别出来的符号流,按照语法规则进行分析,识别各类语法单位,比如表达式、短语、子句;语法分析是一种结构分析,分析结果形成一颗语法树(分析树),若分析过程出现不符合语法规则,就按照语法出错处理

  • 语义分析

    • 前两项检测没有问题,就可以进行语义分析,按照语义对各种语法单位进行翻译,这个时候产生目标程序,但是这样产生的目标程序比手工编写执行效率低,所以大多采用中间语言来描述程序语义

  • 优化

    • 语义分析产生的中间代码不依赖任何实际机器,易于等效变换,使生成目标程序占用空间少,执行快,从而目标程序优化

  • 目标代码生成

    • 根据优化后的中间代码及相关信息,可以生成有效的目标代码,即目标机的机器语言程序或者汇编语言程序

以上是编译器5个阶段,从逻辑上看,编译器就是按照这5个阶段对源程序进行编译,但是按照这5个步骤编译处理的目标程序不能执行,因为有的语言允许各个模块独立编译,生成各自的目标程序(目标模块),这些需要通过链接程序,成为可重定位程序,才能被装入程序装入内存

  • 符号表管理

    • 在编写程序时,对各类数据对象与实体进行说明,编译程序根据这些说明,为各种实体建立描述符,以供编译各个阶段使用

    • 描述符实际是存放实体属性的表格,根据实体不同,表格形式也不同

  • 出错处理

    • 在编译的各个阶段都可能出现错误,特别是语法分析方面,发现错误后,编译程序就要进行处理,报告错误性质,错误位置,将错误范围尽量限制,以便源程序剩余部分继续编译,查出其他部分错误

程序设计环境

在早期开发环境中,各个工具独立执行,随着控制台或者终端开发成为可能,集成开发环境(IDE)诞生

现代IDE不仅提供许多可视化多窗口集成工具,还集成了编辑、文件管理、编译、调试和执行等功能,大大提高程序开发与维护效率

开源编译器

GCC

GCC是一个复杂的软件系统,应该gcc软件包包含了许多个文件

  • 使用GCC的源代码内容

    • 高级语言相关代码:GCC每种编程语言都有对应的处理代码

    • 与编程语言和目标机器无关的通用代码:用于完成GIMPLE与RTL生成,以及数量庞大基于GIMPLE和RTL的处理与编译优化

    • 机器描述代码:对于GCC支持的每种目标机器,在代码中都有一个子目录,用于存放与该目标机器相关的机器描述代码及相应头文件于C文件

    • 与目标机器相关生成器代码

  • 使用gcc/ccl表示使用GCC源代码编译生成的编译器程序

LLVM/clang

是一套编译工具链,包括中间语言LLVM、IR、调试器、LLVM C++标准库、静态分析工具等,LLVM是一个编译框架,可以作为多种语言后端,提供与编程语言无关的优化和针对多种CPU代码生成功能

LLVM架构

核心思想:全时优化,即从编译到执行都能优化

  • 编译时优化:强度减少、去除死代码、并行优化

  • 链接时优化:进行一些过程分析,优化分析有限,链接时可以看到所有代码,可以采用全局优化算法

  • 安装时优化:对代码进行插装以收集运行时信息

clang架构

clang/LLVM将C/C++语言转为机器语言为两步

  • clang将C/C++转换为LLVM IR

  • LLVM基础框架优化LLVM IR并将其翻译成特定体系结构的机器语言

clang/LLVM特色
  • 模块化:clang基于库模式,组件之间耦合性低,容易利用组件写出一些有用的工具

与GCC相比
  • 更快编译速度、

  • 更少的内存占用

  • 更友好的错误检测结果显示

  • 兼容GCC

其他开源编译器

  • NVCC

    • 在CUDA架构为GPU异步编程设计的专用编译器

  • V8

    • JavaScript引擎的实现,采用延时思想,代码编译在运行时才发生

  • 方舟

    • 华为推出,支持多种语言编译,运行采用统一程序优化

编译技术应用

程序理解工具

  • 通过对程序进行分析,逆向提取面向对象程序的类关系图和程序中模块(函数)间调用关系,记录程序数据的静态属性和结构属性,并且画出程序控制流程,帮助用户理解程序

软件测试工具

  • 软件测试:为了发现错误而执行程序或者系统的过程,有静态与动态两种软件测试方法

    • 静态分析器:在不运行时对其分析,类似语法分析程序

    • 动态分析器:在给定一组测试用例下执行程序

自然语言处理

关注计算机与人类语言的交互,特别是如何对计算机进行编程以处理和分析大量自然语言数据,挑战涉及语音识别、自然语言理解、自然语言生成

数据库查询优化

  • 词法分析:对SQL语句保留字进行词法分析并且转换为内部码

  • 语法分析:对SQL语句进行语法分析和语义分析检查,并且将语句转换为适于内部处理形式

  • 查询重写:优化器将查询语句重新编写视为高效形式

  • 计划优化:根据可用存取路径生成一组可能执行计划

  • 计划求精:根据数据分布和统计信息评估每一个执行计划代价

  • 查询执行引擎:根据计划执行具体物理操作

练习

典型编译程序在逻辑功能由几部分组成

  • 编译程序主要由以下几个部分组成:词法分析、语法分析、语义分析、中间代码生成、中间代码优化、目标代码生成、错误处理、表格管理

  • 词法分析器:将源代码转换为词法单元(tokens)

  • 语法分析器:根据语法规则将词法单元组织成语法树

  • 语义分析器:检查语法树的语义正确性,确保所有操作合法

  • 中间代码生成器:生成中间表示代码,作为优化和生成目标代码的中介

  • 优化器:对中间代码进行优化,提高程序效率

  • 目标代码生成器:将优化后的中间代码转换为目标机器代码

  • 汇编器:将目标代码转换为机器码,并生成可执行文件

实现编译程序的主要方法有哪些

  • 主要有:转换法、移植法、自展法、自动生成法

  • 递归下降法:通过递归函数实现语法分析,直接将文法规则映射为程序代码

  • 自顶向下分析:从高层次的语法结构出发,通过规则推导分析源代码,如LL(1)分析

  • 自底向上分析:通过构建语法树从底层开始,逐步归约到开始符号,如LR(1)分析

  • 语法制导翻译:结合语法分析和语义动作生成中间代码

  • 中间代码生成:创建与目标机器无关的中间表示,简化目标代码生成过程

  • 优化技术:在中间代码层进行各种优化以提高代码执行效率

将用户使用高级语言编写的程序翻译为可直接执行的机器语言程序有哪几种主要的方式

  • 编译:将整个源代码一次性转换为机器语言,生成一个完整的可执行文件

  • 解释:逐行解释源代码,并直接执行,通常不生成独立的可执行文件

  • 混合模式:结合编译和解释的特点,先将源代码部分编译为中间代码,然后通过解释器执行中间代码

编译方式和解释方式的根本区别是什么

  • 编译方式:是将源程序经编译得到可执行文件后,就可脱离源程序和编译程序单独执行,所以编译方式的效率高,执行速度快

  • 解释方式:在执行时,必须源程序和解释程序同时参与才能运行,其不产生可执行程序文件,效率低,执行速度慢

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值