• 精选
  • 会员

寄存器流程

2021年10月25日  来源:直觉泵和其他思考工具 作者:[美] 丹尼尔·丹尼特 提供人:zhaotou97......

如果你认为自己对这个程序的运作方式还不是很清楚,那么你可以尝试“手动模拟”整个过程。取出几个杯子充当寄存器(用铅笔在每个杯子上写一个数字,这是它们各自的地址),再找一些硬币或是豆子。在每个寄存器里都放置几枚硬币,然后记录下寄存器1和寄存器3中硬币的数目。接下来,依照程序按部就班地执行完毕,你会发现,寄存器1中硬币的数量与先前一致,而寄存器3中也拥有了与寄存器1数目相同的硬币。能将累加寄存器的基本运作过程都吸收内化是非常有必要的,我们得做到无需再去费劲思量它们。那么现在,就让我们先用几分钟去变成一部寄存器机吧(就像一个演员要去饰演哈姆雷特那样),因为接下来还要用到这种技能。

我发现好多学生常会犯这样的错误:他们认为,在做寄存器减量时,硬币从一个寄存器里取出之后就一定得放入到另一个寄存器中去。这是不对的。减量取出的硬币只需放回到那一大堆硬币中去即可,在简单的加减法套路中,有“无限多”的硬币可供你使用。

掌握了移动、复制还有归零这些技能之后,我准备重新回到之前的加法程序,对它进行改进。之所以要这样做是因为,程序1虽然成功地将加法运算的结果存进了寄存器2中,但在运行过程中,寄存器1和寄存器2中原有的内容却受到了破坏。我要设计出一个更加专业的加法程序,它能保留住原有的那些数值以备后用,将得出的结果放到另外一个地方。现在就让我们来思考这个程序,将寄存器1的内容与寄存器2的内容相加,两个寄存器中的数值保持不变,将结果显示在寄存器3中。

下面是完成这一程序的流程图:

现在,我们就来分析一下各个循环,看看每一步是怎样运行的。首先我们要将显示最终答案的寄存器3归零,同时清零那个空闲的寄存器4,让它充当临时的接受器或者缓冲器。然后,我们把寄存器1中的内容复制到寄存器3和寄存器4中,随后将寄存器4,也就是缓存器中的内容再次移动到寄存器1,让它恢复原有的数据;在这个过程中,作为缓冲器的寄存器4再次被清零,以备后用。接下来,我们将上一步的寄存器1替换为寄存器2再执行一遍,将寄存器2的数据加到寄存器3的数据上。待整个操作完成后,缓存器(寄存器4)清零,加法答案显示在寄存器3中,同时,我们选用的两个加数也保留在了原来的出处——寄存器1和寄存器2里。

将这套由13个步骤构成的RAP程序改写成下面的流程图,可供处理单元读录:

程序4:无损加法[1,2,3]

我不建议你拿杯子和硬币去手动模拟这个程序。人生苦短,一旦你把这些基本步骤都刻入脑海,那就可以切实享受一下“义肢”给你带来的便利了,这副义肢叫RodRego,你可以从网站http://sites.tufts.edu/rodrego/上下载到这部寄存器机。


最初的寄存器机RodRego的网站首页,1986年。

RodRego有PC、Mac(39)两个版本可在您的计算机上运行。20多年前,我和乔治在课程软件工作室里研发了这件思考工具,如今,成百上千的学生和其他行业的人员通过它成为了熟练的寄存器机思考者。你可以将自己编写的RAP程序键入电脑,观察它们如何运行,不管寄存器中的内容是数字还是豆子。另外,有的多媒体软件还可以顺着流程图将处理单元的程序路径淋漓尽致地展现出来,让你可以清楚地看到RAP指令与流程图各环节之间的相互对应。

接下来,我们再来看看减法。这是我的第一次尝试,从寄存器1中减掉寄存器2中的内容,将答案显示在寄存器4中。你能看出我这个流程图存在的问题吗?

这个流程图只有在寄存器1中的内容大于寄存器2的内容时才能正常工作。但如果实际情况不是这样,又该怎么办呢?寄存器1在不断减量的过程之中就已被“清零”,那接下来会发生什么?此时我们不能中止电脑运行,因为那样的话,寄存器4中会留下一个错误的答案“0”。事实上,在寄存器1归零时,我们可以开启一个新的程序,它会先倒退半个循环,将寄存器2中最后减去的1再加回来。此时,将寄存器2中(而不是寄存器1)的数字转化成负数,所得的结果就是正确答案。所以我们只需把此时寄存器2中的数字移动至寄存器4中(之前,其中的内容已清零),再将答案标注为负数即可。我们还需要另外一个寄存器,比如说寄存器3。与寄存器4一样,寄存器3也要首先清零,然后,通过程序设计,它要像一面“旗帜”那样为答案做标记,内容为0时表示正号“+”,为1时表示负号“-”。下面就是这个程序的流程图,各个循环和步骤都有相关注释。(这些注释也可以写入RAP程序中供你以及其他人参考阅读,你要用“#”在其首尾做出标记,这样RodRego就会自动忽略掉它们)。

练习2

a.请为这个流程图写出它的RAP程序。(请注意,由于程序有不同的分支,你可以采用不同的顺序为各步骤编号,只要“下一步”对应的步骤编号填写正确即可。)

b.如果从3中减3,或者从4中减4,这个程序会出现哪些不同?

c.将寄存器3在第三步之前就清零而不是推延到完成第四步之后,这样会避免哪些可能的错误?

熟练掌握了加法和减法的编程以后,再设计乘除运算就易如反掌了。n乘以m表示m个n相加。我们可以这样来设计程序:用一个寄存器作为计数器,从m递减到0,每完成一次加n的运算就减去1。

练习3

a.画一个流程图或者写一个RAP程序,让寄存器1中的数字与寄存器3中的数字相乘,将答案显示在寄存器5中。

b.(可选)(40)利用复制和移动改进你上面写出的乘法编程,使寄存器1与寄存器3在程序停止后都能保持原有的内容,方便你在运算完成后清楚地检查输出和输入的内容正确与否。

c.(可选)画一个流程图或者写一个RAP程序,要求它能识别寄存器1与寄存器3中的内容(同时保证这些内容不受损坏),将内容较大的寄存器地址(1或3)显示于寄存器2;当两个寄存器中的内容相等时,寄存器2中显示2。(程序完成后,寄存器1和寄存器3中的内容要保持不变,寄存器2显示出所含数字较大的寄存器地址,当内容大小相等时,寄存器2将报出数字2。)

与乘法类似,除法运算只需要从被除数中一次一次不断地减去除数并记录下相减的次数即可。如果有余数,我们可以留出一个专门的寄存器储存它。另外,我们还要小心地添加一个必要的检查项目:看看除数是不是0(0不能作除数,请问这是为什么?)。所以,在进行除法运算之前,我们得对除数作一个简单的核查——看看它能否被减量。如果可以,我们还必须再安排一次增量,以便使除数恢复原值,让除法运算继续进行。如果在进行减量核查时,除数真的是0,那就需要拉响警报了。为此,我们可以专门准备一个寄存器负责报错:寄存器5里如果有1出现就表示,“快!我就要除以0了!”

下面就是一个除法流程图,用寄存器1中的内容除以寄存器2中的内容,将答案写入寄存器3,余数显示在寄存器4,醒目的寄存器5用来提示“错误信息”(显示1表示“我将要除以0”)。


顺着这幅流程图梳理,你就能看到“除数为0”是如何中止掉整个运算的,报错的旗帜究竟是如何竖起的。另外还需要注意的是,寄存器4身兼双重职责,不仅要复制并恢复除数数据,以便下次继续成功地减量,而且,还要时刻准备着成为一个余数寄存器。如果在寄存器4将自己的内容倾倒回寄存器2以备下次减量之前,寄存器1中的内容就已经为0,那么留在寄存器4中的数字就是余数,它也正好显示在了余数寄存器中。

如涉及版权,请著作权人与本网站联系,删除或支付费用事宜。

0000