逻辑控制篇幅较长,我会分为两部分来讲解。
开篇,冯诺依曼讲解了模拟计算机的逻辑控制原理。模拟计算机为了实现一系列的计算,会将很多子部件(如差分齿轮、积分器等)形成一个序列,它们之间通过机械或者电的方式连接。你理解就像是一台很复杂的机器,一个齿轮带动另一个(实际并非只有齿轮),形成一部很复杂的机器。而这部机器能做的事,是实现根据要求来定制的,它的组件按一定的序列方式安装。如果要解决另一个问题,则要重新组合这些零部件(也就是冯诺依曼称之为的“器官”)。
冯诺依曼总结道:任何这种形式的连接,都是一种固定装置。
插入式控制,是一种更加友好的方式。这里面用到了元器件“继电器”。继电器又是什么呢?
继电器(英文名称:relay)是一种电控制器件,是当输入量(激励量)的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器。它具有控制系统(又称输入回路)和被控制系统(又称输出回路)之间的互动关系。通常应用于自动化的控制电路中,它实际上是用小电流去控制大电流运作的一种“自动开关”。故在电路中起着自动调节、安全保护、转换电路等作用。
所以呢,有了继电器的加入,就可以去控制电路,而继电器的工作,又可以通过打孔纸带的方式进行控制。咱们不要小看了打孔纸带,这其实是一项非常不错的发明。在图灵设计的计算机模型里,就用纸带来存储指令和对计算进行控制。这虽然是种原始方式,但是从基本面上解读了最简实现,而科技日新月异,实际上只是以更好的方式替代了这种原始方式,从原理本身来说是没有区别的。现在实现的各种新玩意儿,实际上从技术上就是等效的图灵机实现。
想想大师们当年是在什么样的有限技术背景下,能够勾勒出计算机的基本面,而推动了科技的持续发展。
冯诺依曼的讲解方式,似乎跟我们当前的想法并不太一样。他在模拟计算机的逻辑实现收尾处,还展开讲了正负值的模拟实现,即转盘是零点位置偏左还是偏右,而判断一个数是否超过另一个数,就是通过判断其差的正负号。之所以反复强调模拟计算机,我想有两点原因:1、模拟计算机在当时甚至挺长一段时间里,是不可取代的,二战时期在密码加密及破译中,都大量使用了机械方式;2、模拟计算机是数字计算机的实现的参考,数字计算机实际就是模拟计算机的“器官”的进一步封装提炼,不去考虑器官具体实现的细节,而是实现了数学上的逻辑效果。
数字计算机的每一个运算只需要一个器官。这个原理,冯诺依曼实际讲的并不算太清晰,反而提出了这条并非是铁律而是一种通用的说法,或是一种“历史的事实”。模拟计算机通常要完成一个运算,需要多个器官的组合,而数字计算机通常用一个器官来完成,但也有模拟计算机完成一个运算只需要一个器官的实现,反之也并非所有的数字计算机每个运算只需要一个器官。但通常来说,是这样的。这两者之间有一定的灰度区域,模拟计算机在一定的封装后,实际上也朝着“运算”的方向发展。而数字计算机,应该是不用去纠结具体器官的实现(不像模拟计算机会更纠结这块,数字计算机更容易把这块抽象化和统一化),而是更关注数学逻辑的组合运算。
“每一个基本运算只需要一个器官”,导致第一这需要大量的器官,第二这些器官要具备存储某个数的能力。它能够从别的器官接收某个数,然后在需要的时候,还可以将这个数“复述”出去。它是个存储单元,这种器官就叫做“存储寄存器”(这个名称倒是挺现代的)。这些器官的全体,叫做“记忆”,而寄存器的数量,就是容量。
计算机包括一定数量的逻辑控制器官,叫做“控制序列点”。控制序列点会连接到若干寄存器,最简单的是1个,有时需要多个。如果运行时间是不定的,则还需要引入时间控制的寄存器连接点。在这里虽然冯诺依曼洋洋洒洒扩展了不少,但是基本的观点差不多就是这样。
之后,他又讨论了现在看来已经是编程语言里的常识逻辑方式:分支和循环。因为某种条件,默认分支A可能切向B,最终也可能再次合并;某个分支运行时,也可能重新回到起初那个控制序列点。他讲述的方式有点绕,估计是哪个时候这些概念还没有沉淀成常识。
在学习C语言的时候,也会提到类似概念,是运行语句的最小执行单位。不过在我理解,冯诺依曼提到的控制序列点,应该是更底层的实现(汇编层级的),每条汇编运算会调用一系列的寄存器,也存在分支与循环(但也不排除我理解的狭隘性)。高级语言用到的控制序列概念,应是更高层级的,我们并不需要分解到汇编层级即可调用,当然如果能够理解其汇编实现,则能更好的进行如性能等的优化。