这是最精彩的一章。
先存再加
前面使用累加器来计算求和运算的电路为:
使用这个设备时,必须首先按下清零开关使锁存器的存储内容清零,然后用开关来输入第一个数字。加法器简单地把这个数字与锁存器输出的零相加,因此其结果就是你刚输入的数字。按下相加开关可在锁存器中保存该数并且通过灯泡显示出来。现在从开关上输入第二个数,加法器把这个数与存储在锁存器中的数相加,再按下相加开关把总和存储在锁存器中并通过灯泡显示出来。通过这种方法,你可以加上一串数字并显示出运算总和。
上面这个加法机存在的最大问题已经相当明显:如果想把1 0 0个二进制数加起来,你就得坐在加法机前耐着性子输入每一个数字并累加起来。当你完成时,却发现有两个数字是错误的,你只好又重复全部的工作。
如果你向R A M阵列中输入1 0 0个二进制数字,而不是直接输入到加法机中,那么进行数据修改会容易得多。
解决思路:先把要计算的数保存到RAM里面。计算结果也要保存到RAM里面。
先通过控制面板把数据输入到RAM中,再按clear清零,然后开启振荡器,进行自动加法计算。
坐着等结果吧。。。
但问题是,什么时候停呢?除了加法,还想干点别的呢?
指令
不是让自动加法器只做一件事情—在最初的加法器中,只是把R A M地址中的内容加到称为累加器的8位锁存器中—实际上是让它做四件不同的事。
要做加法,需先从存储器中传送一个字节到累加器中,这个操作叫作L o a d(装载)。
第二项所要执行的操作是把存储器中的一个字节加( A d d )到累加器中。
第三项是从累加器中取出结果,保存( S t o r e )到存储器中。
最后,需要有一些方法使自动加法器停止( H a l t )工作。
目标:假设我们希望先把三个数字加在一起,然后把另两个数字加在一起,最后再把另外三个数加在一起。我们可能会将这些数字存储在从地址0 0 0 0 h开始的R A M阵列中,存储器的内容如下所示:
详细说来,让自动加法器所做的工作如下所示:
• 把地址0 0 0 0 h中的数装载到累加器中
• 把地址0 0 0 1 h中的数加到累加器中
• 把地址0 0 0 2 h中的数加到累加器中
• 把累加器中的数保存到地址0 0 0 3 h中
• 把地址0 0 0 4 h中的数装载到累加器中
• 把地址0 0 0 5 h中的数加到累加器中
• 把累加器中的数保存到地址0 0 0 6 h中
• 把地址0 0 0 7 h中的数装载到累加器中
• 把地址0 0 0 8 h中的数加到累加器中
• 把地址0 0 0 9 h中的数加到累加器中
• 把累加器中的数保存到地址0 0 0 A h中
• 停止自动加法器的工作
改进:
数据和指令分开
使用两个RAM,分别存储数据和指令。
指令操作码为:
指令和数据RAM里面的内容分别为:
电路为:
指令扩展
还可以扩展其他指令,比如增加“减法”运算:
要计算:0x56 + 0x2A - 0x38
数据位数扩展
如何计算16位数的加法?把低8位和高8位分开存放,分别计算,并考虑进位。这时就是再增加一条指令:进位加。
比如,计算:0x76AB + 0x232C
使用同样的办法,甚至可以计算32位数的加法,比如计算:0x7A892BCD + 0X65A872FF
新的问题又出现了:
- 存储数据不连续;
- 代码RAM和数据RAM的空间必须一一对应,不能在随后的计算中重复利用计算结果;
再进一步改进:
操作码和操作数混合编排
除了“停止”代码外,现在希望每条指令在存储器中占3个字节,其中第一个字节为代码本身,后两个字节存放一个1 6位的存储器单元地址。对于装载指令来说,其地址指明数据在数据R A M阵列中的存储单元,该存储单元存放要装载到累加器中的字节;对于加法、减法、进位加法和借位减法指令来说,地址指明要从累加器中加上或者减去的字节的存储单元;对于保存指令来说,地址指明累加器中的内容将要保存的存储单元。
比如计算:
更改前:0x4A + 0xB5:
改进后:
每条指令(除了“停止”)后跟2个字节,用来表示在数据R A M阵列中的1 6位地址。这三个地址碰巧为0 0 0 0 h、0 0 0 1 h和0 0 0 2 h,它们可以是任何其他地址。
比如,把4000H和4002H位置的内容相加,保存到4004H处。
这里出现了“间接寻址”的概念了。
将指令和数据合并到同一个RAM中
经过上述改进,现在有条件可以把指令和数据输入到一个RAM中了。
比如,把两个8位数相加,再减去第三个数:
需要增加“2-1选择器”来确定如何寻址RAM陈列:
R A M数据输出仍然连接到用来锁存指令代码及其2字节地址的三个锁存器上,但它们的1 6位地址是2 - 1选择器的第二个输入。在地址被锁存后,选择器允许被锁存的地址作为R A M阵列的地址输入。
跳转指令
通常,自动加法器顺序寻址R A M阵列。转移指令改变其寻址模式,而从R A M阵列的某个特定地址开始寻址。这样的命令有时也叫分支( b r a n c h)指令或者g o t o指令,即“转到另外一个地方”的意思。
更有用的是“条件跳转”:
有了条件判断和分支跳转,于是就有了“顺序”、“分支”和“循环”,于是就有了软件世界。。。
汇编语言
使用助记符来代替二进制代码:
写出来的代码就是汇编程序: