写在前面
看了前言,发现这本书讲的内容和《程序是怎样跑起来的》有很大的重合,区别在于:后者注重“普及知识”,前者则强调体系而专业的学习。
第一章:欢迎阅读本书
计算机是一个包含了多层转换的系统。一个由自然语言(如英语)描述的问题,最终必须转化为计算机内部的电路工作(更具体地说是电子运动),才能得以解决。
计算机处理问题的7个层级:
- Problems
- Algorithm
- Language 代码语言
- 机器架构 ISA
- 电路 circuit
- device
计算机如何工作?程序在计算机中如何运行?
本书能提供一个体系的解答。
人类使用计算机解决问题,会经历一下几个层面的过程:
算法,语言,机器(ISA)结构,微结构,电路,器件。
- 算法:解决问题的步骤。
- 语言:包括高级语言(如C++,Python),汇编语言等等。用于实现算法。
- ISA结构(Instruction set architecture)
- The next step is to translate the program into the instruction set of the particular computer that will be used to carry out the work of the program
- the ISA of a computer specififies the interface between the computer program directing the computer hardware and the hardware carrying out those directions.
- ISA的定义包括:opcode:操作码;operand:操作数;data type:数据类型;addressing mode:寻址模式
- 编译器compiler负责把高级语言翻译为当前计算机的ISA
- 可以理解为CPU才能读懂的指令集(Instruction Set Architecture)。不同厂家的CPU所用的ISA不同,指令数目也不尽相同。而汇编语言的每个语句通常与ISA有一对一的关系。换言之,汇编语言是ISA操作码,逻辑和指令的抽象集合。
我们知道,汇编器(assembler)可以将汇编语言转换成相应的机器码(一堆指令集)。它们是一一对应的。而一种CPU只能理解一种机器码,因此不同CPU厂家的汇编语言也会不一样。
- 微结构:要想实现ISA中的许多功能,我们需要物理上的硬件帮助我们实现。不同操作(如加法,寻址)有不同的微结构实现方式(ALU,mux等等)。
- 逻辑电路。与、或、非
- CMOS、NMOS电子元器件。
一个厂家在更新CPU的时候,通常不希望改变自己的ISA,而是优化自己的微结构。否则一旦升级,从汇编语言到高级语言的代码都将不能在新版本上正常运行。
第二章 bits,数据类型及其运算
我们总能听到:计算机内部的所有东西都是以二进制形式存储的。但是为什么是二进制呢?二进制怎么实现十进制数据的运算呢?小数怎么表示成二进制呢? We don’t know。
Why 二进制?
我们可以用“1”表示一个高电位,用“0”表示一个低电位。这样一来,在计算机的微观结构中,我们只需要知道某个点的电位相较于某中间值的高低,而不需要知道其具体大小。减小电压波动带来的误差。How to use it?
二进制的加、减法,二进制转十进制、十六进制比较基础,在此不赘述。在此主要讲数据类型——各种数据在计算机中的表达方式。
整型
下图以5bit的数据为例,在不同的人为规定下,每个5位二进制代表的整数各不相同。
- 无符号整形
- 5-bit二进制共能表示0~2^5-1的整数
- 有符号整形
- 首尾表示符号
- 负数的二进制表示由其对应正数的二进制取反得到。如: 由5(00101)得到 -5(11010);11111表示-0
- 负数的二进制表示由其对应正数的补码得到。例如:
5(Oct)=(00101)(Bin)
得到-5(Oct)=(11011)(Bin)
31(Oct)=(01111)(Bin)
—>-31(Oct)=(10001)(Bin)
1(Oct)=(00001)(Bin)
—>-1(Oct)=(11111)(Bin)
正数的补码是其本身;负数补码将所有的二进制位取反加1。例如(1101)(Bin) —> (0010)(Bin) —> (0011)(Bin)。 二进制数1101的补码就是0011。
现代计算机中,使用的方法是最后一种。
Q :对
00000
取反加1,得到的应该是10000
, 为什么答案是00000
?A :因为我们规定了数据类型的长度为6bit,所以多出来的第7位自动被忽略掉
Q :用6bit的数据类型没法表示+32,那-32怎么来的呢?
A :我们按上述方法列数所有的负数,发现还有一个六位二进制组合没有用到。它就是
(10000)(Bin)
,我们就人为规定它表示-16。
那我们为什么需要用补码来表示负数呢?
相邻两个码子之间的差值正好是00001。
bit运算
加法直接加
减法先转换成其补码,后加。A-B=A+(-B)
逻辑运算
与、或、非、异或
摩根定律
位矢量bit-vector
不知道和矢量有什么关系。
浮点型
LC-3体系结构中,整数表示方法使用16-bit补码,能表示的数值范围是:
计算机不能精确地表示所有的小数。这也是为什么我们经常讲“精度损失”。原因在于,二进制小数只能用2^-N的组合来表示小数部分。例如 0.75(Oct)=0.5(Oct)+0.25(Oct)=(0.11)(Bin)
十进制数0.9, 就不能用二进制小数精确表示。
Most ISAs today specify more than one floating point data type. One of them, usually called float, consists of 32 bits, allocated as follows:
32-bit-float
- 符号位:1-bit
- 8-bit表示指数
- 23-bit表示精度
一串32位的浮点数表示的小数为:
infinity
当指数部分exponent = 0 或 254时
数电
晶体管
- N-type MOS
- p-type MOS
逻辑门
组合逻辑门
解码器
- k-bit输入,$2^k$ 个输出
多路复用器
从多个输入中选择一个,连接到输出。
$2^k$个输入端,k条线用于选择,1条输出。