cs_notes

Nand To Tetris Coursera Course Part 2

https://www.youtube.com/playlist?list=PLF_hhCJzFptZEt37sFefFQHsbQi3uWhMA

1. nand2tetris coursera projekt 6 1

1. 编译器与虚拟机概述

本课程将讲解如何编译Jack语言到虚拟机指令,然后实现Jack语言运行在不同平台上的能力。

编译Jack语言的过程分为两个阶段:

  1. 编译Jack源代码到虚拟机指令。编译器将Jack语法树转化为VM指令码。

  2. 在不同目标平台上实现虚拟机,将VM指令码再转化为具体平台的机器语言。

实现此目的需要满足“写一次运行任意处”的需求。

2. 虚拟机概念

虚拟机是一种抽象构想,它可以模拟实际计算机的行为。编译高级语言如Java时,首先将源代码编译为可在虚拟机上运行的指令码。然后在各个平台上运行对应的虚拟机实现,将指令码转为本地机器码执行。

这种二层编译可以很好地隔离复杂的跨平台过程,简化各个转换阶段的任务。

3. Jack语言编译框架

本课程将用Jack语言作为示例。Jack源码首先编译为VM指令,然后运行于两类环境:

  1. PC上通过VM解释器直接执行VM指令

  2. 通过编写VM翻译器,将VM指令转换为Hack机器码在模拟器中运行

这样就实现了Jack程序同时在PC和Hack机器上运行。

4. 虚拟机设计抽象

会从抽象层面讨论虚拟机能做什么,比如堆栈操作、指针等。这可以帮助理解Java虚拟机和其它语言虚拟机的工作原理。

会实现一个完整的虚拟机,通过编程手段建立起虚拟机各个组成部分。

2. nand2tetris coursera projekt 6 3

1. 内存段概念

虚拟机指令使用内存段来表示变量的不同作用域,如本地变量、静态变量等。

VM指令使用push和pop指令操作对应内存段,如push static 0表示将0推入静态变量段的索引0位置。

2. Jack编译到VM指令

Jack语句被编译为VM指令序列。如let C = s1 + y编译为push s1 push y add pop C。

但VM指令中没有变量名称,只有内存段名称和索引来表示变量。

3. 虚拟机内存段

VM设计考虑高级语言的 object-oriented 特性,包含8个内存段:本地、参数、静态、指针、常量、This、That、临时。

push和pop根据内存段和索引操作其中的数据。

4. 操作内存段例子

例如操作argument 1的值赋给static 2,使用指令push argument 1 pop static 2。 通过堆栈交换数据实现从一个内存段到另一个内存段的赋值。

5. VM指令概览

前面单元学习了算术逻辑指令,本单元学习了内存段指令。下一步将学习如何实现这些指令。

3. nand2tetris coursera projekt 6 7

1. 虚拟机翻译器作用

VM翻译器接收VM指令作为输入,将其解析和翻译为目标平台HEC汇编指令输出。

2. 翻译器具体工作流程

VM翻译器首先将VM指令分解成词法元素如push和索引等,然后使用目标平台HEC汇编指令重新表达这些命令。

3. 翻译难点所在

翻译器需同时熟练掌握源语言VM和目标语言HEC汇编。需要决定数据结构在主机内存中的映射,以及如何将高级指令翻译为汇编指令。

4. 标准VM映射

提出标准VM映射约定,如栈和段的内存布局,指令翻译使用的特定标识符如SP和LCL等。此映射可确保互操作性,方便测试。

5. HEC标准VM映射细节

具体描述了HEC计算机内VM各内存段和数据结构的内存布局,以及翻译时使用的标识符约定。

6. 翻译器实现

使用高级语言如Java或Python来实现VM翻译器程序,生成注释的HEC汇编输出。

4. nand2tetris coursera projekt 6 8

1. VM翻译器原理

VM翻译器通过解析器和编码器将VM指令翻译成目标平台汇编指令。主类采用三个模块结构:解析器、编码器和主类。

2. 三个模块设计

主类负责打开文件并调用解析器和编码器处理每个指令。解析器读取并解析单条指令,编码器输出对应汇编指令。

3. 解析器模块

解析器构造函数打开输入文件,hasMoreCommands判断指令是否完成,commandType判断指令类型,arg1、arg2输出参数。

4. 编码器模块

编码器构造函数打开输出文件,writeArithmetic根据指令类型生成汇编代码,writePushPop处理push和pop指令。

5. 使用VM翻译器

通过命令行调用主类,输入VM文件作为参数,生成对应汇编输出文件。检查输出是否正确实现了源程序。

6. 实现细节

翻译主类需要掌握文件操作,解析器和编码器是重点模块。后续项目将完善支持函数和分支指令的翻译。

5. nand2tetris coursera projekt 7 1

1. 程序控制流

用于控制程序执行顺序的控制流语句包括函数调用、条件分支和循环等。

2. 扩展语言功能

基本语言原语有限,但程序员可以根据需要定义新的抽象概念和函数。如定义计算表达式的函数。

3. 函数调用实现

虚拟机支持函数调用和返回,需要理解函数如何在虚拟机层面实现。调用时参数传递,返回值获取等细节。

4. 条件判断

使用if-goto语句实现条件判断,通过比较操作数后选择跳转到不同代码段执行。

5. 栈空间的动态分配

函数调用需要在栈上为每层函数调用分配存储空间,运行时根据调用需要动态管理内存。

6. 指针支持

函数调用通过指针传参和返回值,需要学习指针在虚拟机中的实现原理。

7. 项目实现

完善虚拟机的实现,支持函数调用及相关新指令。掌握运行时内存管理、参数传递等细节。

6. nand2tetris coursera projekt 7 2

1. 程序控制流

通过条件跳转和无条件跳转实现程序流程的分支控制。

2. 循环实现

通过使用标签和跳转指令实现循环的不同路径,如while循环通过goto实现。

3. 条件跳转

使用if-goto指令实现条件分支,需要先推入条件表达式的值,然后判断跳转。

4. 无条件跳转

goto指令直接跳转到标签位置继续执行。

5. 标签

为了实现跳转需要在特定位置定义标签标识。

6. 编译原理

高级语言循环结构编译成VM指令通过插入标签和跳转实现。

7. VM与汇编对应

VM指令经过翻译后在汇编层面也可以使用相应的跳转指令实现相同功能。

8. 项目要求

完善虚拟机的实现,支持条件跳转和无条件跳转指令。

7. nand2tetris coursera projekt 7 7

1. 虚拟机翻译器介绍

实现将虚拟机代码翻译成汇编指令的虚拟机翻译器。

2. HEC平台约定

定义HEC平台下虚拟机翻译器的一些约定,如主函数名、调用sis_init等。

3. 程序引导

引导程序从地址0开始,先设置栈指针SP,然后调用sis_init函数启动程序。

4. 内存空间说明

HEC计算机总内存32K,逻辑上分为RAM顶部2K等区域。虚拟机只操作RAM顶部2K。

5. 符号约定

为翻译器生成标签等使用额外的三类特殊符号。

6. 实现步骤

根据 modules中定义的语法和本模块中的HEC平台约定,使用 Java或Python等语言开发虚拟机翻译器。

7. 虚拟机翻译器作用

将虚拟机多个函数翻译成连续的汇编指令,实现源代码中的语义。

8. nand2tetris coursera projekt 7 8

1. 虚拟机翻译器功能

虚拟机翻译器可以将单个VM文件或包含多个VM文件的目录转译为汇编代码。

2. 实现模块

翻译器由main、passer和code writer三个模块组成,main负责输入输出,passer解析VM命令,code writer生成汇编代码。

3. Main模块

Main根据输入判断是否文件夹,如果是文件就调用passer,如果是文件夹就遍历文件夹内所有文件调用passer。

4. Passer模块

负责解析VM文件,将每个命令拆分为词素元素,过滤注释和空格。与前期Passer保持一致。

5. Code Writer模块

扩展前期Code Writer中的写入接口,添加设置文件名、引导代码和各种命令对应的汇编产生方法。

6. 关键实现

重点实现function、call、return三个命令对应的汇编产生方法,正确构建栈机制实现函数调用协议。

7. 项目建议

在下一课讨论具体项目内容和开发推荐。

9. nand2tetris coursera projekt 7 10

1. 虚拟机语言的优点

VM语言代码与高级语言源代码比例大约为1:4,代码量少但功能强大。

2. two-tier编译模式

编译器只需生成VM代码,无需考虑底层实现Details。VM转换工具负责将VM代码翻译为汇编代码。

3. 效率问题

两级编译会引入额外开销,效率较单级编译低。但对许多应用而言,效率损失不明显。

4. Java与C++效率对比

C++直接生成机器码,效率高于Java需要VM的中间过程。但对许多应用,效率差异较小,不值一提。

5. 安全性

VM代码易于分析,可以检测安全漏洞。VM实现可以控制程序运行权限,防止恶意代码访问系统资源。

6. managed代码概念

Microsoft用这个词描述在CLR等VM上运行的代码,强调其受VM管理特性。

7. 架构分离思想

VM代码仅描述内存访问抽象,与底层实现隔离,方便编译器开发与目标平台移植。

10. nand2tetris coursera projekt 8 1 1

1. Jack语言简介

Jack语言类似Java,支持对象和过程编程。编写Jack编译器和操作系统是课程重点。

2. 课程设计

模块4-5建Jack编译器,模块6建OS。Jack源码由若干类构成,主程序main类的main函数为执行入口。

3. 注释类型

Jack支持三种注释:文档注释、块注释和内联注释。语法类似C++/Java。

4. 语句结构

Jack支持if、while、do等控制流语句。还支持数组处理和OS调用函数。

5. 数据类型

Jack支持基本类型如int、bool;也支持类类型如数组类。允许自定义类类型。

6. Hello World程序

输出”Hello World!”,说明Jack程序由主类main构成,主函数main为执行入口点。

7. 平均值程序

从用户输入数组,计算平均值。说明Jack支持变量声明、循环、数组等基础语法。

11. nand2tetris coursera projekt 8 1 4

1.语法单元

本单元讨论Jack语法,以代码示例从语法角度进行分析。

2. 空白和注释

Jack支持内联注释、块注释和文档注释。空格可以随意使用但被忽略。

3. 关键词

Jack共有20多个关键词,包括标准关键词(if、while等)和特殊关键词(let、do)。

4. 符号

程序使用不同符号进行分组和其他目的。

5. 常量

Jack支持整数常量、字符串常量、布尔常量和null常量。

6. 标识符

标识符占据大部分代码,对应变量、类和方法名称。它们必须符合命名规则。

7. 语法元素

程序由关键词、符号、常量、标识符等语法元素构成。下一单元将讨论Jack的数据类型。

12. nand2tetris coursera projekt 8 1 5

1. 数据类型

Jack支持三种基本类型:int、boolean、char。 int范围为0-32767。还支持类类型如string、array。

2. 类型转换

char和int自由转换。string通过caret函数转换为char。int也可以表示内存地址。

3. 数组和对象

数组和对象内部结构相似,可以互相转换。数组可以表示对象,对象方法也可以在数组上调用。

4. 弱类型

Jack语言弱类型,任何变量都可以赋值给任何其他变量,带来灵活性但也有风险。

5. 负数表示

int只能是非负数,负数通过-运算符表示,实际上是一个表达式。

6. 类类型

除基本类型外,也支持像string、array之类的类类型,以及用户定义的类类型。

7. 下一步

将学习类和方法,深入了解Jack面向对象的支持能力。

13. nand2tetris coursera projekt 8 1 6

1. 类

类是Jack语言的基本单元,每个类都定义在一个单独的文件中。类名须与文件名相同,首字母大写。

2. 类结构

类包含字段、静态字段、构造函数和方法等。字段和静态字段可选,但如果存在须定义在方法之前。

3. 类类型

提供功能型类,如Math类,仅包含函数。代表实体的类,如Fraction类,包含字段和方法。

4. 分离责任原则

将Math类中的GCD函数移出Fraction类,以避免混合功能和对象功能。

5. OS类

Jack提供8个OS类库支持常用I/O、数学等功能,封装低级硬件细节。如Keyboard支持键盘输入。

6. 应用

Jack应用由一个或多个J类组成,入口类需含main方法。类库与Java标准类库概念相同,提供广泛支持。

14. nand2tetris coursera projekt 8 1 11

1. Jack语言特点

Jack语言主要特点有:变量、循环、数组、子程序等过程编程特性,同时支持对象的创建和操作。类型系统仅有3种基本类型,只有if-else和while控制结构,不支持继承。

2. 与其他语言的区别

Jack语言设计目的不是强大,而是实现高级语言核心概念。所以特意 simplfied 许多特征,如类型系统、控制结构等,以实现语言精简而聚焦。

3. 弱类型设计

Jack允许任意类型间的自动转换,这简化了语法但可能导致 bug。此设计方便后期开发操作系统时利用语言覆写底层机制。

4. let和do组织

let声明变量,do调用无返回值函数,这些前缀词句设计用于简化编译器的解析工作。

5. Jack操作系统

Jack语言通过标准类库实现了完整的操作系统功能,提供输入输出、数学等支持。类库可无限拓展,实现语言向外自由扩展的特性。

6. 简单且可扩展

Jack语言设计追求语法精简而专注,同时通过类和函数机制让语言可以无限扩展,这是现代语言的杰出设计。

15. nand2tetris coursera projekt 8 2 1

1. 编译器设计概述

编译器的作用是将高级语言程序翻译成机器语言以实现执行。本课程采用两阶段翻译模式,高级语言代码先编译成虚拟机代码,再由虚拟机翻译成机器语言。

2. 模块设计

本课程将编译器开发分为两个模块设计与实现:语法分析器模块和代码生成器模块。语法分析器模块输出XML文件记录结果以分开测试。

3. 此模块工作

当前模块将开发语法分析器中的词法分析器和语法分析器。词法分析器负责标记化,语法分析器负责解析语法结构。两者合成语法分析器。

4. 后续模块工作

下一个模块将在此模块基础上添加代码生成器模块,将语法树转化为虚拟机代码。代码生成器模块实现生成XML文件的项目也在本模块阐述。

5. 学习语法分析的意义

理解编译器设计原理有利于编写结构化易维护的代码,并解决日益常见的大数据处理任务。分析结构化文件需要掌握词法和语法分析技术。

16. nand2tetris coursera projekt 8 2 2

1. 词法分析简介

词法分析是语法分析器的一个重要模块。它通过将字符流转换为tokens流,实现初步处理输入文件,为后续编译过程奠定基础。

2. 词法分析实例

以一个jack源码文件为例,词法分析将其转换为tokens流,包含keyword、symbol、整数常量、字符串常量、标识符等不同类型的词素。

3. 词法分析定义

jack语言定义了5类词素,包括关键字、符号、整数常量、字符串常量和标识符。每个类别都有明确定义,无歧义。这为编写词法分析器提供了依据。

4. 词法分析器设计

词法分析器实现词法分析功能,以类或模块的形式提供相应接口,如识别token类型、获取下一个token等。测试程序可以利用这些接口将源文件转换为带类型标签的tokens流。

5. 词法分析器使用实例

提供了一个使用词法分析器接口的测试程序示例。它构造分析器对象,循环识别每一个token,并输出带类型标签的token流,为后续语法分析提供输入。

6. 语法定义语言

学习词法分析后,下一步将介绍语法定义语言,以期为后续语法分析奠定理论基础。

17. nand2tetris coursera projekt 8 2 3

1. 语法定义的重要性

程序中的词元组合必须符合一定顺序和语法规则,否则无法形成有意义的语句。语法定义通过一组规则,明确词元的排列组合模式。

2. 英语语法示例

以英语句子结构为例,阐述了单词的组合方式,如名词短语和动词短语的组成。语法规则可以接受合法输入,如“狗吃了我的作业”。

3. Jack编程语言子集语法

设计了Jack语句、表达式和词元的定义规则。语句由if、while、let组成;表达式由变量、常量和运算符构成。规定词元顺序和结构,以判断语句是否符合语法。

4. 语法匹配input

举例说明了输入是否匹配语法规则。正确的输入如let语句将被接受;缺少左括号的while语句将产生错误。通过分析输入与规则的对应关系,验证语法结构。

5. 语法定义的数据结构

终结符规则右边仅含常量,非终结符规则含规则名称或常量。语法定义由终结符和非终结符规则组成。为语法分析提供理论支持。

6. 解析

判断输入是否匹配语法的过程叫做解析。解析过程中还可以还原输入的语法结构,为后续编译奠定基础。计算机程序需要严格匹配语法,否则会报错。

18. nand2tetris coursera projekt 8 2 4

1. 语法分析产出解析树

语法分析过程能够判断输入是否符合语法规则,并建立语法结构描述-解析树。解析树通过层级结构展示语句各部件间的关系。

2. 解析树以树形结构表示

解析树结构与树一样,由根节点开始分叉生长,形成子节点。顶层节点描述整个语句,下层节点描述各细节部分。树叶节点对应原始单词或词元。

3. 英语和Jack语言的解析树示例

给出了英语句子和Jack语句count+1的解析树图示。两者都展示语句结构,但表示方法不同。

4. 解析树以XML文件形式描述

解析树也可以用结构标记语言XML进行描述。XML文件通过标签定义树各节点及其组成部分,实现结构化表达。这是一种新的、更通用的解析树表示方法。

5. 解析逻辑生成解析树

解析过程将输入内容通过规则匹配,生成对应它的解析树。但本视频介绍的仅解析树结果,没有具体介述解析逻辑。这部分算法内容将在下一个视频单元中详细说明。

6. 解析树在编译中的重要性

正确构建的解析树,能够还原语句结构并反映语法关系,为后续语义分析和代码生成提供支持。它是编译过程中的基础结构。

19. nand2tetris coursera projekt 8 2 6

1. Jack语法概述

介绍Jack语法规则记法。方括号表示可选项,竖线表示选择,问号表示零或一次,星号表示零或多次。

2. Jack文件结构

Jack文件由一个或多个类组成。每个类包含成员变量、静态变量和方法定义。

3. 类定义格式

类由class关键字、类名、变量和方法组成。变量可以是静态或成员变量,类型有int、char、boolean和其他类名。

4. 方法定义格式

方法由关键字constructor、function、method开头,后跟返回类型和参数表,参数表是可选的。

5. 语句定义

语句由let、if、while、do、return组成。每个语句有专门的规则定义格式。

6. 表达式定义

表达式包含术元、操作符和操作对象,其中术元的处理较复杂,可能是变量、数组或调用。需要Lookahead解析接下来的 tokens。

7. Jack语法分析

将为每个非终结符规则编写对应的解析子程序。解析程序按语法规则匹配输入,生成相应的XML解析树输出。

8. 术元处理问题

变量名可能对应变量、数组或调用不同情形,需要查看后续tokens判断。这是Jack语法不完全LL(1)的地方。

20. nand2tetris coursera projekt 8 2 7

在之前的单元中,我们用常规的方式总结了词法分析和语法的概念。在本单元中,我们将专注于Jack语法分析器的输出要求。

语法分析器的主要任务是解析源代码并生成结构化的XML代表。为了进行独立测试,我们可暂时跳过代码生成器,直接生成XML输出。

语法分析器会对源代码进行递归解析,根据Jack语法规则输出对应的XML标签。对于终结符号,直接用相应的标签包裹;对于大多数非终结符号,输出Non-terminal名称并递归解析其内容。但是对于一些“浅”规则,分析器会直接忽略而不生成XML。

举例来说,对于关键字“method”,输出将是method;对于一个类定义,输出将是......并递归解析类名、成员等。而对于变量名规则“VAR name”,分析器会直接解析其内容(标识符),而不输出标签。

通过以上方式生成的XML代表文档,可以反映分析器完全正确地根据语法规则进行递归解析的能力,从而实现对源代码的结构理解。

在之后的单元中,会给出Jack语法分析器具体的实现方法。综合本单元和后续单元,读者将掌握如何根据Jack语法规则编写出语法分析器。

21. nand2tetris coursera projekt 8 2 10

本模块主要回答了一些语法分析相关的常见问题:

是否会处理编译错误?根据初衷,我们暂时忽略错误处理,假设源代码无误。若移除这一假设,错误处理会复杂一些,需要精细的定位和输出。

语法分析技术是否能应用于其他语言?是的,分词和语法分析是通用的。我们掌握的方法适用于任何结构化文本的分析。但Jack语法很简单,不包含许多高级语言特性。

为什么不使用Lex和Yacc自动生成分词器和语法分析器?Nanodegree旨在从零开始实现,而不是使用外部工具箱。

语法分析器应如何处理终结符和非终结符?对于终结符直接输出标记,对于非终结符输出名称并递归分析内容。一些“浅”规则中直接忽略非终结符。

通过输出XML表示,可以查看语法分析器是否正确识别不同结构。后续模块将实现代码生成器,完成整个编译过程。

22. nand2tetris coursera projekt 9 1

本模块主要讨论代码生成(Code Generation)部分。

编译器的工作大多高级程序员都见怪不怪,但其实编译过程中的高级语言到机器代码的转换无疑是极其神奇的。理解编译器内部工作原理,可以让程序员更深入理解编程语言实现细节,同时也可以极大提升编程能力。

我们的编译器将Jack语言翻译成虚拟机语言(VM Language),而不是直接生成机器代码。将任务分为两个模块:语法分析器和代码生成器。语法分析器我们在前 modules 已经实现,现在继续进行代码生成器的开发工作。

Jack程序的编译可以看作是单独编译每个类文件的过程。每个类由类级代码和多个子例程组成,可以将其编译工作分解成先编译类级代码,后编译每个子例程。

代码生成的任务是将Jack各种语法元素如变量、表达式、数组等翻译成相应的VM指令实现。这是极其复杂的工作,需要桥接高级语言与低级语言之间的差异。

本模块将按照变量、表达式等元素,分步实现具体的代码生成算法。学习这个过程可以深入理解编程语言实现原理和通用编程技术。

23. nand2tetris coursera projekt 9 5

本模块将介绍如何使用VM指令来处理对象。

当使用高级语言编写物体导向程序时,可以直接使用对象和方法思考。但在VM语言层面,将丧失对象的概念,只能使用8个虚拟内存段和相关指令操作。

程序在编译阶段生成的就是VM指令代码。VM实现将指令翻译成RAM操作。

对象和数组的数据存储在称为堆(heap)的RAM区域。本地和参数变量存储在栈中。

通过this和that指针可以访问对象数据。但首先需要使用pointer段设置这两个指针,确定它们指向哪个对象数据在堆中的位置。

例如,如果对象数据从RAM地址8000开始,先push 8000到pointer 0,这样设置this指向8000。然后就可以使用push/pop this 0来读写RAM 8000位置的数据了。

数组使用相同的机制,不同的是使用that指针访问。

本模块重点解释了如何使用VM指令实现对对象数据的读写操作。这为后续讨论对象的构造生成法提供了基础。

24. nand2tetris coursera projekt 9 12

本模块回答了几个常见问题:

Jack语言相对简单,没有类型系统,变量类型任意。这为编译器带来便利,可以简单处理类型转换等问题。

而其他语言如Java都有丰富的类型系统,变量类型不同需要分配不同内存,类型转换需要明确操作等,这对编译器难度大。

Jack没有继承特性,方法调用可以在编译时静态解析。但支持继承的语言需要在运行时动态决定调用哪个类的方法。

扩展Jack添加更完善的语法结构如for循环、switch等对编译器影响不大。但继承等需要重写较多代码。

语言扩展主要需要两个步骤:修改语法规范,更新编译器的解析器和代码生成器部分。每个扩展都需要谨慎设计。

编译器优化指生成低级代码高效率。例如单变量增量可以优化成两条机器码,而不是复杂翻译。但本模块编译器未进行这类优化。

本模块开发了一个将Jack编译成VM代码的编译器,这是重要而复杂的工程成果。在下一个模块将用Jack开发一个操作系统。

25. nand2tetris coursera projekt 10 1

本模块是Nand2Tetris课程的最后一个模块,主要讨论操作系统。

Jack语言开发的操作系统包含8个类:Math类提供基本数学运算;Memory类进行内存管理;Graphics类绘制图形;Output类输出文本;Keyboard类读取键盘输入;String类字符串处理;Array类数组支持;Sys类提供常用服务。

操作系统的功能包括:采用高效算法和数据结构管理内存和存储资源;驱动外设如键盘、显示器等;支持文件管理;提供多任务支持运行多个程序;控制与其他计算机的网络通信;保障系统安全性等。

操作系统开发需要考虑高级编程语言提供的标准类库,为用户提供输入输出、数据结构等抽象界面。同时操作系统还要处理低级细节,如驱动管理内存、存储、外设等。

课程将介绍操作系统需要的算法原理,并用Jack语言实现。这可以帮助了解算法设计思想和系统编程技术。

为提高效率,操作系统算法的实现必须考虑运行效率,不能任由程序运行缓慢。这与前模块只关注功能是否可行的方式不同。

本模块将通过介绍各个组件的算法原理和Jack实现,帮助学习操作系统的设计思想和编程技术。

26. nand2tetris coursera projekt 10 4

本单元讨论内存管理中的peek和poke操作。

操作系统需要为高级编程语言提供访问内存的接口,但是编程语言不知道如何直接访问物理RAM。peek允许读取指定地址的内存值,poke允许写值到指定地址内存。

初步想法是使用Jack数组保存整个RAM,但是会失败,因为数组太大无法在堆内存中分配。

于是使用内存类中静态RAM数组的解决方案。在init函数中,直接让RAM数组名等于0地址,这样RAM数组就可以直接访问整个物理内存了。

这是因为Jack语言对数组和变量的弱类型检查,允许直接使用数组名而不是下标访问。这样就实现了从Jack语言访问物理内存的”后门”。

实现peek只需从RAM数组中读取指定地址值,poke writing值。使用RAM数组后,peek和poke实现就非常简单了。

本单元实现了访问内存的基础接口peek和poke,为后续讨论内存管理提供了基础。

27. nand2tetris coursera projekt 10 6

本单元讨论了如何在Jack操作系统中实现绘制像素的基本绘图操作。

Jack操作系统采用向量图形技术,使用屏幕内存映射来绘制屏幕像素。某个位置的像素通过设置对应内存地址的某一位来绘制。

通过计算公式可以将二维屏幕坐标转换为一维内存地址。drawPixel函数首先通过计算获得需要修改bit的内存地址,然后读取修改後写回,以避免破坏周围像素。

绘制像素需要使用内存管理类Memory中的peek和poke函数访问内存。这是不同模块之间的依赖关系。

屏幕刷新采用定时刷新机制。操作系统在内存映射中绘制像素, hardware负责根据内存映射每隔一小段时间刷新一次实际屏幕。

本单元实现了底层绘制单个像素的drawPixel函数,为后续绘制更复杂图形奠定基础。

28. nand2tetris coursera extra 1

本单元概述了Nand2Tetris课程中可能实现的一些优化与扩展内容。

Nand2Tetris中实现的计算机系统虽然已完成,但在性能、功能等方面还有很大改进空间。

优化内容包括:实现乘法与除法的位运算算法,添加移位运算指令,优化虚拟机翻译器生成更紧凑的汇编代码等。这些都可以通过设计新的硬件逻辑电路来实现。

扩展内容包括:给指令集添加乘法opcode,扩展汇编语言,修改汇编器;将乘法算法实现为硬件电路而非软件函数来提升性能;给系统增加存储设备和网络功能。

良好的设计是任何项目成功的关键。Nand2Tetris项目采用了模块化、简单明了的设计,方便了后续的修改与扩展工作。

这些建议的优化与扩展项目都需要进行整体设计,实现系统各个层次的相应修改,包括硬件描述语言、指令集、汇编器、编译器、虚拟机翻译器等。项目采用模块测试可以实现隔离的验证。

本单元介绍了Nand2Tetris后续可能的一些研究方向,为学习者提供了更多玩法。

29. nand2tetris coursera extra 2

为将存储和网络功能导入HEC计算机中,可以采取以下方法:

  1. 假设已经有硬盘和网络接口卡设备。

  2. 将这些设备设计成内置芯片形式,集成到硬件仿真器中。

  3. 将内置硬盘芯片设计为存储大量比特的闪存单元。

  4. 使用内置硬盘为HEC程序保存和加载数据,需要修改硬件、添加文件系统和操作系统支持文件的加载与存储。

  5. 引入命令Shell窗口,用于访问和管理文件。

  6. 将内置网络接口芯片设计为同时与HEC硬件和物理网卡连接,支持以太网协议数据传输。

  7. 开发网络操作系统和通信程序,实现内网和外网连接。

  8. 可以开发HTTP网页浏览器利用网络功能。

  9. 内置芯片的开发需要规定接口和功能,以单独Java类实现。代码公开源可供学习和扩展。

  10. 任何优化或扩展项目都需要全面规划,明确功能和涉及子系统,参考现有架构进行分模块开发与测试。

  11. 开源优秀项目设计可供他人学习参考。

30. nand2tetris coursera extra 3

  1. Jack语言可以进行以下优化:修改语法结构,增加for和switch控制语句,扩展数据类型,添加继承等功能。需要修改语法规范和编译器。

  2. 可以实现其他高级语言,如Scheme解释器。

  3. 可以将HEC计算机实现成实际硬件。方法一是在手机或PC等设备上模拟虚拟机。方法二是使用VHDL等硬件描述语言重写Nand2Tetris一中的硬件设计,将其写入可编程逻辑器件(FPGA)板卡实现。

  4. FPGA技术成熟,可实现多种数字电路。市场上有低价FPGA开发板,也有免费软件FPGA模拟器可以在PC上开发。

  5. FPGA实际实现难度大,需要设计内置设备如内存、显示屏和键盘驱动等。

  6. Demi Seidner博士已经完成FPGA实现工程,将与课程合作推出Nand2Tetris三,教学如何使用硬件原子实现计算机。

31. nand2tetris coursera extra 4

  1. 这门课程的主要创意来源于教授诺姆·尼桑,但他本人没有出现在任何一节课中。

  2. 一个例子说,牛顿和莱布尼茨两位数学家都解决过同一难题,但只有牛顿留下名字,莱布尼茨不留。

  3. 就像莱布尼茨一看牛顿的答案便知是他一样,学生也可以从这门课中认出诺姆·尼桑的风格。

  4. 这门课很值得享受,它让我们分享应用计算机科学的美妙之处。

  5. 如果要了解后续课程、工具或项目,可以去Nand2Tetris网站报名邮件列表。希望与学生保持联系。