一直想对计算机底层的实现与顶层的抽象接口间的关系进行下系统的学习,知乎上搜了下相关话题,大佬们都推荐——《深入了解计算机系统》。考虑本人并非科班,很多基础课程都没接触过,所以在啃经典之前,这本书就是“打基础”的不二之选。
全书知识点总结:
- 硬件:逻辑门,布尔运算,多路复用器(multiplexor和demultiplexor),触发器(flip-flop),寄存器(register),RAM单元,计数器(PC),硬件描述语言HDL;
- 体系架构:ALU(算数逻辑单元)和CPU(中央处理器)的设计与实现,机器代码,汇编语言程序设计,取址模式,I/O内存映像;
- 操作系统:内存管理,数学计算程序库,基本I/O驱动程序,屏幕管理,文件I/O,对高级语言的支持;
- 程序设计语言:ADT抽象数据类型,作用域(scope),语法和语义,引用机制(refrence),基于对象的设计及编程模式;
- 编译器:词法分析,自顶向下的语法分析,符号表(symbol),基于堆栈的虚拟机(stack-based),代码生成,数组和对象的实现;
- 数据结构和算法:堆栈,哈希表,链表,递归,算术算法,几何算法,运行效率;
- 软件工程:模块化设计,接口/实现范式,API设计和文档,主动式测试,广义的程序设计概念,质量保证体系;
第一章 布尔逻辑
1.门逻辑:输入管脚(input pins)和输出管脚(output pins)
2.硬件描述语言HDL 硬件仿真器
3.Nand门
4.基本逻辑门(logic gates):Not、And、Or、Xor、Multiplexor(两个输入数据位data bits+一个选择位selections bits+一个输出位)、Demultiplexor(一个输入位+两个输出位+一个选择位)
5.多位逻辑门multi-bit versions of basic gates 多位数据线(又称“总线”bus):使用数组的语法
多位Not(multi-bit not)、多位And、多位Or、多位Multiplexor
6.多通道逻辑门multi-way versions of basic gates
多通道Or、多通道/多位multiplexor、多通道/多位demultiplexor
注:按位运算bit-wise下,多通道一般为一个输出,多位一般为n个输出(n位)
第二章 布尔运算
1.有符号二进制数
编码方式:2-补码,又称基补码。各位取反,末尾加一。正数LSB为0,负数LSB为1。
2.算数逻辑单元ALU(arithmeticlogical unit)
第三章 时序逻辑
1.所有布尔芯片和算术芯片都是组合芯片(combinational chips);而保存数据需要用到记忆单元,所有记忆单元都有时序芯片(sequential chips)组成,而直接或间接地嵌入一个或多个DFF门的芯片就是时序芯片。
2.时钟clock :振荡器产生0-1两个信号值或称“低电平-高电平”,上升沿之间的时间间隙称为时钟的周期
3.触发器flip-flops:计算机中最基本的时序单元。
数据触发器Data flip-flop:DFF(1bit输入和1bit输出,此外还有个时钟输入),数据和时钟的输入使得DFF能够实现基于时间的行为。out(t)=in(t-1)
4.寄存器registers:具有记忆功能的设备,实现经典的存储行为。out(t)=out(t-1)
5.内存memories RAM随机存储内存random access memory :数据输入+地址输入+加载位
RAM的基本设计参数;数据宽度(每个字的宽度,16位宽或64位宽)和大小(字的数目)
6.计数器counter:每经过一个时间周期,该整数就增加一个单位,执行函数out(t)=out(t-1)+1
第四章 机器语言
——借由机器语言,程序员用符号指令表达的抽象思维被转换成执行在硅片上的物理操作。
机器语言包括二进制版本和符号汇编(symbolic assembly)版本。
1.机器语言可以被看做一种约定的形式,它利用处理器和寄存器来操作内存。
2.内存:用来存储数据和指令的硬件设备 结构:一个连续的固定宽度的单元序列(字,或称内存单元),及每个字唯一的一个地址。对于独立的字(代表一个数据项或是一个指令),可以通过提供它的地址来描述。
3.处理器 执行一组固定操作的设备,包括算数操作和逻辑操作、内存存取操作和控制操作。
4、寄存器 内存访问是相对偏慢的操作,需要较长的指令格式(一个地址可能需要32位),而寄存器只存储一位,它紧挨着处理器,相当于处理器的一个高速本地内存,使得处理器快速的操控数据和指令。从而加速程序的执行。
5.语言 纯二进制编码——> 二进制编码+助记符——> 汇编语言
6.内存访问时的寻址方式:直接寻址(“所见即地址”)+间接寻址(基地址+偏移量)+立即寻址(“所见即数据”)
7.Hack机器语言规范
7.1内存地址空间分为两类:指令地址空间A + 数据地址空间D,故寄存器也分为D和A两类寄存器。
D仅用来存储数值;A既可作为数据寄存器也可作为地址寄存器(包括指向指令的地址和指向数据的地址)
7.2语法规定:内存的存取指令是对隐式的内存地址“M”进行操作。而规定M总是代表一个内存单元中的数值,该内存单元的地址就是当前A寄存器的数值!
任何jump操作总是执行这样的跳转:跳转到“A寄存器所指定的指令”。
7.3命令解释 @value :value可以是数值或者是代表数值的符号。该命令将特定的值(value)存到A寄存器中。
总结起来,hack机器语言的赋值操作分两步走: @i // i指代某个内存单元,将i存到A寄存器中。
M=1 // 将A寄存器的数值设为数值为1的内存单元地址,则 i=1
7.4 A-指令:为A寄存器设置15-位的值,有三种不同的用途,首先,提供唯一一种“将常数存入计算机”的方法;其次,通过将目标数据内存单元的地址放入A寄存器,
来为将对该内存单元进行操作的C指令提供必要的条件;将跳转的目的地址放入A寄存器,为执行跳转的C指令提供条件。
7.5 C-指令,包含三个域(dest=comp;jump)对应三个域的翻译表
第五章 计算机体系结构
前三章只是静态的构建计算设备,第四章描述了程序的最底层表达,即机器语言。最后第五章是对前四章的总结,构建了一个完整的动态的计算机系统工作的模型。
计算机工作的要点就在于:程序存储和程序控制。而程序存储即表明计算机中将程序和数据都存放在存储器中,程序控制即是通过译码将机器指令转换为具体的控制信号进行控制。
1.冯洛伊曼结构:1CPU(ALU+寄存器+控制器)+内存(数据内存和指令内存)+输入输出
2.I/O(输入/输出)设备:包括键盘、鼠标、显示器、扫描仪、网络接口卡(网卡)、光驱等等。
最简单的实现方式:I/O映像。
第六章 汇编编译器
1.机器语言分类:二进制型(binary)和符号型(symbolic)
符号化的机器语言即称为汇编,对应的翻译程序称为汇编编译器(assembler)
符号的用途:变量(variables)和标签(lables),以及预定义符号(predefined symbols)
2.汇编编译器实际上是个文本处理程序(遵守完整的汇编语法说明文档和相应的二进制编码——机器语言规范)
有四个功能:解析出符号命令在内的域;对于每个域,产生机器语言中相应的位域;用内存单元的数字地址来替换所有的符号引用(关键);将二进制码汇编成完整的机器指令。
3.Hack机器语言指令类型:寻址指令(A指令)+计算指令(C指令)
4.汇编编译器的实现:
a.语法分析器模块(Parser)对输入文件进行语法分析;
b.编码模块(code)用来提供所有汇编命令所对应的二进制代码;
c.符号表模块(symbol table)用来处理符号
d.主程序模块 用来驱动整个编译过程
5.符号表:用来建立和维持标签符号与其数字地址之间的关联。哈希表是表示这种关系的经典数据结构之一。
第七章 虚拟机I:堆栈运算
java虚拟机JVM(java virtual meachine)
1.VM语言包括4种类型的命令:算术命令;内存访问命令;程序流程控制命令和子程序调用命令。
2.两层结构:高级语言——编译器——>VM指令(中间语言)——VM翻译器——>机器语言(基于硬件)
模块化
3.堆栈数据结构,LIFO 最简单的实现方式:创建一个数组(所谓的堆栈)+一个堆栈指针变量(stack pointer,sp 指向位于栈顶的元素)
4.高级语言中:对象是封装了数据(成员字段fields/属性properties)和相关代码(方法methods)的实体。
从本质上讲,每个对象实例(object instance)的数据是在RAM上被序列化(serialized)成一串数字,这串数字代表对象中各个字段的值。
第八章 虚拟机II:程序控制
高级语言抽象级别越高,在地层要做的工作就越多。特别是,必须在底层控制子程序和子程序调用者之间的相互影响。
对于在运行期间的每个子程序调用,底层必须处理下面的一些细节:
a.将参数从调用者传递给被调用者;
b.在跳转并执行被调用者之前,先保存调用者的状态;
c.为被调用者使用的局部变量分配空间;
d.跳转并执行被调用者;
e.将被调用者的运行结果返回给调用者;
f.在被调用者返回之前,先回收其使用的内存空间;
g.恢复调用者的状态;
h.返回调用语句之后的下一条语句继续执行。。
1.程序控制流 计算机程序默认的执行顺序是线性的(“one line by one line”)
利用标签指令(labeling directive)描述即将执行的指令的物理地址,从而实现分支逻辑。
2.子程序调用 在子程序调用的实现过程中,这种后进先出(LIFO)的处理方式和堆栈数据结构的操作方式完全吻合。
帧(frame):代表子程序的局部变量的集合,包括子程序的参数、工作堆栈和运行过程中所使用的内存段。
return命令:它将程序的执行重定向到调用语句call命令的下一条命令所在的内存地址,即返回地址(return address)(返回地址保存在调用者的帧里面)
3.引导程序代码(bootstrap)——sys.init 主程序/主函数main
第九章 高级语言
主要讲的是jack语言的各种规范
第十章 编译器I:语法分析
编译器的两个任务:语法分析(syntax analysis)+代码生成(code generation)
1.构建语法分析器相关的四个概念:
a.词法分析(lexical analysis)/字元化
b.上下文无关语法(context-free grammar)
c.语法分析树(parse trees)
d.递归下降算法(recursive-descent)
2.语法分析器的两个模块:字元化(tokenizing)模块,用于将输入的字符分组成语言原子元素(language atoms);
语法分析(parsing)模块,用于将所得到的的语言原子元素集合与语法规则想匹配。
3.词法分析:将字符分组成字元(不是字符,而是由语言语法所定义),忽略空格和注释等,又称字元化。
对程序进行词法分析后得到一系列字元(即字元流, token stream)。
4.上下文无关语法:用来指定语言中的语法元素如何由更简单的元素组成。
将给定的输入(字元集合/字元流)解析成非终结符(non-terminals)、较低级的非终结符,以及最后不能继续分解的终结符(字元)。
语法规则一般是高度递归的。
5.语法分析:检查语法是否将所输入的文本看作合法输入的过程。
语法分析器生产的输入可以用语法分析树(parse tree)或导出树(derivation tree)的树状数据结构来描述。
6.递归下降分析/自顶向下分析:应用由语法规则描述的嵌套结构来尝试递归地分析字元集合形成的输入流。
第十一章 编译器II:代码生成
双层结构编译器:一个处于后端(back-end)的虚拟机和一个前端(front-end)模块(是高级语言和VM语言间的桥梁,由语法分析器和代码生成器组成)
1.程序本质上就是一系列操纵数据的操作。so,翻译程序的关键问题即为:数据的翻译和操作命令的翻译。
2.符号表(symbol table) 第一次遇到的新标识符(identifiers)时将其添加到表中(名称,类型,种类,偏移量),再次遇见时即可查表。
符号表除了保存标识符的上述信息之外,还需以某种方式记录标识符的作用域。解决此问题的典型数据结构即为由哈希表(hash table)组成的链表,
每个哈希表反映了一种作用域,该作用域被嵌套在链表中下一个哈希表所描述的作用域中。
3.变量处理——全局堆栈和虚拟内存段;
数组处理——声明时只分配一个指针(或称引用),指向数组内存段的基地址。程序运行期间数组被真正构造时才会被分配合适的内存段。
从内存堆(heap)中经由动态内存分配(dynamic memory allocation)得到的内存段。
对象处理——包括对象实例中的数据项及方法两种。
a.数据:指向基地址的指针变量+索引(偏移量)+
b.方法:被调用方法的引用(隐含参数)+方法重载method overriding(不同类中不同方法具有相同的名字)
4.表达式求值——后缀表示法/逆波兰表示法RPN
5.程序流程控制表达式的编译——标签命令+递归
第十二章 操作系统
1.数学操作 加法在ALU级的硬件中已经实现(第三章),乘法——二进制移位,除法——乘法+递归,平方根——二叉查找+乘法(反函数)
2.动态内存分配: 链表 最优适应算法(best-fit) 最先适应算法(first-fit)碎片整理
3.I/O管理 设备驱动(device driver)——封装设备接口的物理细节
最后,都说读一本书就像是一次旅途,那就用本书前言末尾处的一句话来结束“这趟旅途”——基本逻辑门是利用基于固态物理理论以及量子理论的技术,由晶体管构建而成。正是在这里,自然世界之抽象(物理学家来研究和描述)才演化成人造世界之抽象(计算机科学家构建和研究)的构建模块。