对计算机的抽象
摘要
本篇介绍对计算机的一些抽象视角,通过这些视角,你可以在脑中构造一个简化版本的计算机,这种简化将会有利于更好理解计算机的工作原理,从而便于你后续进行 PA1 的实验。
在继续阅读前,请先完成实验手册中的“开天辟地的篇章”部分。
什么是计算机?
这个问题估计你在前面的课程中已经接触过很多次了。我们在这里可以理解计算机为:由处理器(CPU)、存储器、控制器(用于指令解析等)、输入输出设备组成的一个系统。
计算机的工作原理无非是:在时钟的驱动下,执行“取指令→解析指令→执行指令”的循环。而其中每一个阶段的进行,都是有逻辑完整严密的电路支持的。
我们学过,计算机数字电路的本质其实就是一个个元件中电压的高低,我们将其对应到数学中的1和0,那也就是说,计算机可以拆分成两个部分:一部分是负责存储的01串,主要位于存储器中;另一部分是负责控制的01串,主要位于控制器中。(其他的部件更多是这两部分兼有)
所以我们可以抽象计算机为一个函数f(x),函数的输入是旧的存储部分,输出是下一个时钟的存储部分,函数本身是控制部分。那也就是说,对于一个确定的存储,确定的控制,下一周期的的计算机状态就是确定的
更进一步,由于控制部分是通过指令驱动的,而指令是存储在存储器中的,那么某种程度上,上面的函数f也可以视作存储的一部分(但不完全一样),所以我们还可以进一步抽象计算机为一个新函数g(f, x),其中函数g就可以理解成 ISA ,也就是计算机工作方式的约定。
看完了抽象的函数视角,我们换到数字逻辑电路的视角,其中,存储部分和控制部分都是01串,也就是说,我们可以将计算机视作一个海量01串(寄存器、内存、指令等)的集合,对计算机某一时刻的01串状态做一个“截图”,那么我们就明确了当前正在执行的指令(它是01串)、当前时钟周期(它是01串)、当前的寄存器和内存状态(它也是01串),也就是说,我们也就明确了它下一个周期中的状态(同样,是01串),以此类推,我们就知道了这个程序接下来n步会怎样运行。
输入输出的地位?
我们讲了这么多计算机内部的抽象,但似乎没有抽象过外部的输入输出设备,我们该怎么理解输入输出设备在这些视角中的地位呢?
在了解了这些抽象视角后,实验手册中所说的状态机视角对你而言可能就不难理解了。每个时刻的计算机都对应函数g(f, x)中的参数 f 和 x,即当前指令(和PC有关)和存储情况(即寄存器、内存等)。我们将每个时刻称为一个状态,那么每过一条指令,就应当进入下一个确定的状态,因为每个指令的行为都是 ISA 确定了的。
状态机的本质与 debug
实验手册中说“计算机是个状态机”,这个视角有什么作用呢?
对于一个计算机,它的晶体管数量是有限的,也就是存储的01数是有限的,假设一共有 n 个存储位,那么它可能的总状态就是有限的(2^n个)。也就是说,计算机可能的状态数是有限的,行为是确定的。这样,我们面对计算机就不必慌张,对于寻找 bug 也会更有信心。
我们后面要实现的简易调试器(sdb),类似于 gdb ,实际上就是一个状态机管理器,调试器每次控制程序执行一条指令(从一个状态迁移一步到下一个状态),我们通过预期状态和实际状态的比对(如比对变量的值),就能够找出 bug 。
状态机视角的局限性
正如我们刚刚所说,状态机可能的总状态数是 2^n 个,即使绝大多数状态都是无效的状态(如非法的指令等),你也可以想象,如果对着状态一个个比特位对比,将会面临多大的困难。对此,我们只能通过人为限定条件,缩小排查范围等方式,尽可能减少需要检查的变量数,从而降低排查难度。
有的人可能提出:是否能将 gdb 这种状态机式的 debug 方式自动化?但问题在于,如果你能够准确地找到每一个状态对应的下一个正确状态,那么实际上你已经写出了一个正确的程序,也就不存在 debug 的前提了。
不过我们也不必沮丧,虽然我们无法实现一个万能的自动 debug 机器,但我们依然可以通过排查出及其明显的错误状态(通过 assert),跟踪关键变量的值等方式,实现尽可能精确快速的 debug 。
人是状态机吗?
人脑是由大量神经元的状态组成的,那人是状态机吗?换而言之,人的行为是确定可预知的吗?更进一步,人的意识是完全自主的吗?