万本电子书0元读

万本电子书0元读

顶部广告

自制编译器电子书

贯穿编译、汇编、、加载的全过程!比“龙书”更具实践性! 1.实战    通过实际动手制作一个精简版C语言编译器,让读者深了解C语言程序编译、运行背后的细节。 2.全面    不仅限于编译器,对以编译器为中心的编程语言的运行环境,即编译器、汇编器、器、硬件以及运行时环境等,均有所涉及。 3.杰出    日本知名技术书作家青木峰郎耗时3年精心造,通过具体的例子讲解概念,通俗易懂,更适合门。

售       价:¥

纸质售价:¥78.20购买纸书

269人正在读 | 0人评论 6.2

作       者:青木峰郎

出  版  社:人民邮电出版社

出版时间:2016-06-01

字       数:33.2万

所属分类: 科技 > 计算机/网络 > 程序设计

温馨提示:此类商品不支持退换货,不支持下载打印

为你推荐

  • 读书简介
  • 目录
  • 累计评论(0条)
  • 读书简介
  • 目录
  • 累计评论(0条)
本书将带领读者从头始制作一门语言的编译器。笔者特意为本书设计了CЬ语言,CЬ可以说是C语言的子集,实现了包括指针运算等在内的C语言的主要部分。本书所实现的编译器就是CЬ语言的编译器, 是实实在在的编译器,而非有诸多限制的玩具。另外,除编译器之外,本书对以编译器为中心的编程语言的运行环境,即编译器、汇编器、器、硬件、运行时环境等都有所提及,介绍了程序运行的所有环节。 本书将带领读者从头始制作一门语言的编译器。笔者特意为本书设计了CЬ语言,CЬ可以说是C语言的子集,实现了包括指针运算等在内的C语言的主要部分。本书所实现的编译器就是CЬ语言的编译器, 是实实在在的编译器,而非有诸多限制的玩具。另外,除编译器之外,本书对以编译器为中心的编程语言的运行环境,即编译器、汇编器、器、硬件、运行时环境等都有所提及,介绍了程序运行的所有环节。
【推荐语】
贯穿编译、汇编、、加载的全过程!比“龙书”更具实践性! 1.实战    通过实际动手制作一个精简版C语言编译器,让读者深了解C语言程序编译、运行背后的细节。 2.全面    不仅限于编译器,对以编译器为中心的编程语言的运行环境,即编译器、汇编器、器、硬件以及运行时环境等,均有所涉及。 3.杰出    日本知名技术书作家青木峰郎耗时3年精心造,通过具体的例子讲解概念,通俗易懂,更适合门。
【作者】
青木峰郎(作者)程序员,著有《Ruby程序设计268技(第2版)》《Ruby源代码完全解说》《Linux程序设计》等多部编程相关著作,并积极参与标准库维护、文档维护等各种各样的活动。   严圣逸(译者)毕业于上海交通大学。8年软件发经验,期间赴日本工作。现就职于想能信息科技(上海)有限公司,从事基于云平台的客户关系管理及各类营销自动化系统的发工作。译有《高效团队发:工具与方法》。   绝云(译者)毕业于清华大学软件学院。曾在日本创意公司KAYAC从事即时通信软件及社交游戏的发工作,现任蚂蚁金服前端架构专家。译有《写给大家看的算法书》等图书,曾参与《像外行一样思考,像专家一样实践(修订版)》的审校。
目录展开

译者序

前言

必要的知识

不必要的知识

本书的结构

致谢

第1章 开始制作编译器

1.1 本书的概要

本书的主题

本书制作的编译器

编译示例

可执行文件

编译

程序运行环境

1.2 编译过程

编译的 4 个阶段

语法分析

语义分析

生成中间代码

代码生成

优化

总结

1.3 使用 C♭ 编译器进行编译

C♭ 编译器的必要环境

安装 C♭ 编译器

C♭ 的 Hello, World!

第2章 C♭ 和 cbc

2.1 C♭ 语言的概要

C♭ 的 Hello, World !

C♭ 中删减的功能

import 关键字

导入文件的规范

2.2 C♭ 编译器 cbc 的构成

cbc 的代码树

cbc 的包

compiler 包中的类群

main 函数的实现

commandMain 函数的实现

Java5 泛型

build 函数的实现

Java 5 的 foreach 语句

compile 函数的实现

第1部分 代码分析

第3章 语法分析的概要

3.1 语法分析的方法

代码分析中的问题点

代码分析的一般规律

词法分析、语法分析、语义分析

扫描器的动作

单词的种类和语义值

token

抽象语法树和节点

3.2 解析器生成器

什么是解析器生成器

解析器生成器的种类

解析器生成器的选择

3.3 JavaCC 的概要

什么是 JavaCC

语法描述文件

语法描述文件的例子

运行 JavaCC

启动 JavaCC 所生成的解析器

中文的处理

第4章 词法分析

4.1 基于 JavaCC 的扫描器的描述

本章的目的

JavaCC 的正则表达式

固定字符串

连接

字符组

排除型字符组

重复 1 次或多次

重复 0 次或多次

重复 n 次到 m 次

正好重复 n 次

可以省略

选择

4.2 扫描没有结构的单词

TOKEN 命令

扫描标识符和保留字

选择匹配规则

扫描数值

4.3 扫描不生成 token 的单词

SKIP 命令和 SPECIAL_TOKEN 命令

跳过空白符

跳过行注释

4.4 扫描具有结构的单词

最长匹配原则和它的问题

基于状态迁移的扫描

MORE 命令

跳过块注释

扫描字符串字面量

扫描字符字面量

第5章 基于 JavaCC 的解析器 的描述

5.1 基于 EBNF 语法的描述

本章的目的

基于 JavaCC 的语法描述

终端符和非终端符

JavaCC 的 EBNF 表示法

连接

重复 0 次或多次

重复 1 次或多次

选择

可以省略

5.2 语法的二义性和 token 的超前扫描

语法的二义性

JavaCC 的局限性

提取左侧共通部分

token 的超前扫描

可以省略的规则和冲突

重复和冲突

更灵活的超前扫描

超前扫描的相关注意事项

第6章 语法分析

6.1 定义的分析

表示程序整体的符号

语法的单位

import 声明的语法

各类定义的语法

变量定义的语法

函数定义的语法

结构体定义和联合体定义的语法

结构体成员和联合体成员的语法

typedef 语句的语法

类型的语法

C 语言和 C♭ 在变量定义上的区别

基本类型的语法

6.2 语句的分析

语句的语法

if 语句的语法

省略 if 语句和大括号

while 语句的语法

for 语句的语法

各类跳转语句的语法

6.3 表达式的分析

表达式的整体结构

expr 的规则

条件表达式

二元运算符

6.4 项的分析

项的规则

前置运算符的规则

后置运算符的规则

字面量的规则

第2部分 抽象语法树和中间代码

第7章 JavaCC 的 action 和抽象语法树

7.1 JavaCC 的 action

本章的目的

简单的 action

执行 action 的时间点

返回语义值的 action

获取终端符号的语义值

Token 类的属性

获取非终端符号的语义值

语法树的结构

选择和 action

重复和 action

本节总结

7.2 抽象语法树和节点

Node 类群

Node 类的定义

抽象语法树的表示

基于节点表示表达式的例子

第8章 抽象语法树的生成

8.1 表达式的抽象语法树

字面量的抽象语法树

类型的表示

为什么需要 TypeRef 类

一元运算的抽象语法树

二元运算的抽象语法树

条件表达式的抽象语法树

赋值表达式的抽象语法树

8.2 语句的抽象语法树

if 语句的抽象语法树

while 语句的抽象语法树

程序块的抽象语法树

8.3 声明的抽象语法树

变量声明列表的抽象语法树

函数定义的抽象语法树

表示声明列表的抽象语法树

表示程序整体的抽象语法树

外部符号的 import

总结

8.4 cbc 的解析器的启动

Parser 对象的生成

文件的解析

解析器的启动

第9章 语义分析(1)引用的消解

9.1 语义分析的概要

本章目的

抽象语法树的遍历

不使用 Visitor 模式的抽象语法树的处理

基于 Visitor 模式的抽象语法树的处理

Vistor 模式的一般化

cbc 中 Visitor 模式的实现

语义分析相关的 cbc 的类

9.2 变量引用的消解

问题概要

实现的概要

Scope 树的结构

LocalResolver 类的属性

LocalResolver 类的启动

变量定义的添加

函数定义的处理

pushScope 方法

currentScope 方法

popScope 方法

添加临时作用域

建立 VariableNode 和变量定义的关联

从作用域树取得变量定义

9.3 类型名称的消解

问题概要

实现的概要

TypeResolver 类的属性

TypeResolver 类的启动

类型的声明

类型和抽象语法树的遍历

变量定义的类型消解

函数定义的类型消解

第10章 语义分析(2)静态类型检查

10.1 类型定义的检查

问题概要

实现的概要

检测有向图中的闭环的算法

结构体、联合体的循环定义检查

10.2 表达式的有效性检查

问题概要

实现的概要

DereferenceChecker 类的启动

SemanticError 异常的捕获

非指针类型取值操作的检查

获取非左值表达式地址的检查

隐式的指针生成

10.3 静态类型检查

问题概要

实现的概要

C♭中操作数的类型

隐式类型转换

TyperChecker 类的启动

二元运算符的类型检查

隐式类型转换的实现

第11章 中间代码的转换

11.1 cbc 的中间代码

组成中间代码的类

中间代码节点类的属性

中间代码的运算符和类型

各类中间代码

中间代码的意义

11.2 IRGenerator 类的概要

抽象语法树的遍历和返回值

IRGenerator 类的启动

函数本体的转换

作为语句的表达式的判别

11.3 流程控制语句的转换

if 语句的转换(1)概要

if 语句的转换(2)没有 else 部分的情况

if 语句的转换(3)存在 else 部分的情况

while 语句的转换

break 语句的转换(1)问题的定义

break 语句的转换(2)实现的方针

break 语句的转换(3)实现

11.4 没有副作用的表达式的转换

UnaryOpNode 对象的转换

BinaryOpNode 对象的转换

指针加减运算的转换

11.5 左值的转换

左边和右边

左值和右值

cbc 中左值的表现

结构体成员的偏移

成员引用(expr.memb)的转换

左值转换的例外:数组和函数

成员引用的表达式(ptr->memb)的转换

11.6 存在副作用的表达式的转换

表达式的副作用

有副作用的表达式的转换方针

简单赋值表达式的转换(1)语句

临时变量的引入

简单赋值表达式的转换(2)表达式

后置自增的转换

第3部分 汇编代码

第12章 x86 架构的概要

12.1 计算机的系统结构

CPU 和存储器

寄存器

地址

物理地址和虚拟地址

各类设备

缓存

12.2 x86 系列 CPU 的历史

x86 系列CPU

32 位 CPU

指令集

IA-32 的变迁

IA-32 的 64 位扩展——AMD64

12.3 IA-32 的概要

IA-32 的寄存器

通用寄存器

机器栈

机器栈的操作

机器栈的用途

栈帧

指令指针

标志寄存器

12.4 数据的表现形式和格式

无符号整数的表现形式

有符号整数的表现形式

负整数的表现形式和二进制补码

字节序

对齐

结构体的表现形式

第13章 x86 汇编器编程

13.1 基于 GNU 汇编器的编程

GNU 汇编器

汇编语言的 Hello, World!

基于GNU 汇编器的汇编代码

13.2 GNU 汇编器的语法

汇编版的 Hello, World!

指令

汇编伪操作

标签

注释

助记符后缀

各种各样的操作数

间接内存引用

x86 指令集的概要

13.3 传输指令

mov 指令

push 指令和 pop指令

lea指令

movsx 指令和 movzx指令

符号扩展和零扩展

13.4 算术运算指令

add指令

进位标志

sub指令

imul指令

idiv 指令和 div指令

inc指令

dec指令

neg指令

13.5 位运算指令

and 指令

or 指令

xor 指令

not指令

sal指令

sar指令

shr指令

13.6 流程的控制

jmp指令

条件跳转指令(jz、jnz、je、jne、……)

cmp指令

test指令

标志位获取指令(SETcc)

call指令

ret指令

第14章 函数和变量

14.1 程序调用约定

什么是程序调用约定

Linux/x86 下的程序调用约定

14.2 Linux/x86 下的函数调用

到函数调用完成为止

到函数开始执行为止

到返回原处理流程为止

到清理操作完成为止

函数调用总结

14.3 Linux/x86 下函数调用的细节

寄存器的保存和复原

caller-save 寄存器和 callee-save 寄存器

caller-save 寄存器和 callee-save 寄存器的灵活应用

大数值和浮点数的返回方法

其他平台的程序调用约定

第15章 编译表达式和语句

15.1 确认编译结果

利用 cbc 进行确认的方法

利用 gcc 进行确认的方法

15.2 x86 汇编的对象与 DSL

表示汇编的类

表示汇编对象

15.3 cbc 的 x86 汇编 DSL

利用 DSL 生成汇编对象

表示寄存器

表示立即数和内存引用

表示指令

表示汇编伪操作、标签和注释

15.4 CodeGenerator 类的概要

CodeGenerator 类的字段

CodeGenerator 类的处理概述

实现 compileStmts 方法

cbc 的编译策略

15.5 编译单纯的表达式

编译 Int 节点

编译 Str 节点

编译 Uni 节点 (1) 按位取反

编译 Uni 节点 (2) 逻辑非

15.6 编译二元运算

编译 Bin 节点

实现 compileBinaryOp 方法

实现除法和余数

实现比较运算

15.7 引用变量和赋值

编译 Var 节点

编译 Addr 节点

编译 Mem 节点

编译 Assign 节点

15.8 编译 jump 语句

编译 LabelStmt 节点

编译 Jump 节点

编译 CJump 节点

编译 Call 节点

编译 Return 节点

第16章 分配栈帧

16.1 操作栈

cbc 中的栈帧

栈指针操作原则

函数体编译顺序

16.2 参数和局部变量的内存分配

本节概述

参数的内存分配

局部变量的内存分配:原则

局部变量的内存分配

处理作用域内的局部变量

对齐的计算

子作用域变量的内存分配

16.3 利用虚拟栈分配临时变量

虚拟栈的作用

虚拟栈的接口

虚拟栈的结构

virtualPush 方法的实现

VirtualStack#extend 方法的实现

VirtualStack#top 方法的实现

virtualPop 方法的实现

VirtualStack#rewind 方法的实现

虚拟栈的运作

16.4 调整栈访问的偏移量

本节概要

StackFrameInfo 类

计算正在使用的 callee-save 寄存器

计算临时变量区域的大小

调整局部变量的偏移量

调整临时变量的偏移量

16.5 生成函数序言和尾声

本节概要

生成函数序言

生成函数尾声

6.6 alloca 函数的实现

什么是 alloca 函数

实现原则

alloca 函数的影响

alloca 函数的实现

第17章 优化的方法

17.1 什么是优化

各种各样的优化

优化的案例

常量折叠

代数简化

降低运算强度

削除共同子表达式

消除无效语句

函数内联

17.2 优化的分类

基于方法的优化分类

基于作用范围的优化分类

基于作用阶段的优化分类

17.3 cbc 中的优化

cbc 中的优化原则

cbc 中实现的优化

cbc 中优化的实现

17.4 更深层的优化

基于模式匹配选择指令

分配寄存器

控制流分析

大规模的数据流分析和 SSA 形式

总结

第4部分 链接和加载

第18章 生成目标文件

18.1 ELF 文件的结构

ELF 的目的

ELF 的节和段

目标文件的主要 ELF 节

使用 readelf 命令输出节头

使用 readelf 命令输出程序头

使用 readelf 命令输出符号表

readelf 命令的选项

什么是 DWARF 格式

18.2 全局变量及其在 ELF 文件中的表示

分配给任意 ELF 节

分配给通用 ELF 节

分配 .bss 节

通用符号

记录全局变量对应的符号

记录符号的附加信息

记录通用符号的附加信息

总结

18.3 编译全局变量

generate 方法的实现

generateAssemblyCode 方法的实现

编译全局变量

编译立即数

编译通用符号

编译字符串字面量

生成函数头

计算函数的代码大小

总结

18.4 生成目标文件

as 命令调用的概要

引用 GNUAssembler 类

调用 as 命令

第19章 链接和库

19.1 链接的概要

链接的执行示例

gcc 和 GNU ld

链接器处理的文件

常用库

链接器的输入和输出

19.2 什么是链接

链接时进行的处理

合并节

重定位

符号消解

19.3 动态链接和静态链接

两种链接方法

动态链接的优点

动态链接的缺点

动态链接示例

静态链接示例

库的检索规则

19.4 生成库

生成静态库

Linux 中共享库的管理

生成共享库

链接生成的共享库

第20章 加载程序

20.1 加载 ELF 段

利用 mmap 系统调用进行文件映射

进程的内存镜像

内存空间的属性

ELF 段对应的内存空间

和 ELF 文件不对应的内存空间

ELF 文件加载的实现

20.2 动态链接过程

动态链接加载器

程序从启动到终止的过程

启动ld.so

系统内核传递的信息

AUX 矢量

读入共享库

符号消解和重定位

运行初始化代码

执行主程序

执行终止处理

ld.so 解析的环境变量

20.3 动态加载

所谓动态加载

Linux 下的动态加载

动态加载的架构

20.4 GNU ld 的链接

用于 cbc 的 ld 选项的结构

C 运行时

生成可执行文件

生成共享库

第21章 生成地址无关代码

21.1 地址无关代码

什么是地址无关代码

全局偏移表(GOT)

获取 GOT 地址

使用 GOT 地址访问全局变量

访问使用 GOT 地址的文件内部的全局变量

过程链接表(PLT)

调用 PLT 入口

地址无关的可执行文件:PIE

21.2 全局变量引用的实现

获取 GOT 地址

PICThunk 函数的实现

删除重复函数并设置不可见属性

加载 GOT 地址

locateSymbols 函数的实现

全局变量的引用

访问全局变量:地址无关代码的情况下

函数的符号

字符串常量的引用

21.3 链接器调用的实现

生成可执行文件

generateSharedLibrary 方法

21.4 从程序解析到执行

build 和加载的过程

词法分析

语法分析

生成中间代码

生成代码

汇编

生成共享库

生成可执行文件

加载

第22章 扩展阅读

22.1 参考书推荐

编译器相关

语法分析相关

汇编语言相关

22.2 链接、加载相关

22.3 各种编程语言的功能

异常封装相关的图书

垃圾回收

垃圾回收相关的图书

面向对象编程语言的实现

函数式语言

附录

A.1 参考文献

A.2 在线资料

A.3 源代码

累计评论(0条) 0个书友正在讨论这本书 发表评论

发表评论

发表评论,分享你的想法吧!

买过这本书的人还买过

读了这本书的人还在读

回顶部