转载请遵循GNU开源宣言。Copyleft ! <2013>, <http://www.cnblogs.com/sciencefans from buaa 华罗庚班>
阅读此文,你需要拥有以下基础:
1.能理解本系列第2节和第4节;2.已经阅读了第4节。
=========================================================================
(为什么mac总是配图失败呢,,)
很久没有更新本系列了诶。。。有一个月了吧。但是经过这接近一个月来对code的重新阅读以及对其他一些书的草草翻翻,更加进一步的对计算机领域本身,计算机的数学发展以及计算机的哲学发展这三个方面进行了了解和深入理解与思考。作为一个数学系的计算机系学生,加上这些理解,自然会有自己一些会对或错的想法。或许这些将会在以后的文章中隐隐约约地显现出来。
一直在纠结到底应该先写汇编还是先写自动操作。csapp一书是直接从寄存器开始讲汇编,刚开始开的时候还真有些不好理解,有些东西没有听说过(毕竟是数学系的),而计算机组成与设计(以后简称COD H/S)一书却索性放到了附录,唯独code一书是从最简单慢慢在不知不觉中让读者发现:哇,我现在看的原来就是汇编啊!那么我决定走code路线~
那么进入正题吧~
之前我们已经做出了最简易的加减器,单位存储器。其中加减器可以认为是一个非常不完善的cpu,而存储器可以认为是最简陋的RAM。面对上一次提出的三个问题,今天开始的接下来三节一共要搞明白以下几件事:
- 多位存储器;
- 怎样自动就能不停地进行累加;
- ‘累加’该怎么停止;
- 怎么让‘硬件’通过‘代码’自动化。
首先是多位存储器。上一次已经做出了一个单位存储器,在本文中我用下面这个集成小块儿来代表它(具体电路见第四节):
根据之前我们制作多位运算器的经验,多位存储器应该也是多个单位存储器的某种形式的链接,唯独不同的一点就是需要增加一些调度电路——它必须知道总线发过来的信号应该给多位存储器中的哪一‘位’,它也应该知道怎么进行‘读’‘写’操作。
首先要解决的问题是‘调度’电路怎么设计。现在以8位存储器为例,想要确定某一时刻数据应该往8个子位的哪一位存,应该消耗多少输入端口来确定呢?或者说,假设这八个单位存储器的地址分别是1,2,3,。。。,8,需要多少个输入端口来把他们区分开呢?这里要引入一个新的东西——3-8译码器。我们知道,想要表达8种不同的状态最少需要3个二进制位(还记得小白鼠的实验那个游戏吗?8杯水只有一杯有毒,只喂一次的情况下最小需要3只小白鼠才能知道哪杯有水)。所以输入地址位应该是3个。下面就是3-8译码器(顾名思义)的电路:
左下角的DI代表的意思是数据输入,这个输入的数据应该给右边8个端口中的哪一个呢?由左下角的S0,S1,S2确定。仔细看看电路就不难发现这个电路的精妙所在。S0,S1,S2三个端口的原本信号和取反信号分别构成了1,0,三个1,0位的全部结合构成了这8个输出口的‘地址’——000,001,010,。。。,111.
解决了数据输入调度,现在该解决数据输出调度了,输出和输入是两个相反的过程,所以输出调度就是把输入调度元件反着画一下就好了,他有一个新名字——8-1选择器:
左边的输入口自上向下分别是8个单位存储器的输出,三个S地址调度器代表特定的某个输出口被打开。右边的输出端口就代表被选中的那一‘位’存储器的输出值。
现在准备工作都完成了,分别把3-8译码器,8个单位锁存器,8-1选择器进行连接,变成下面这个样子:
蓝色,红色和绿色本别是3-8译码器,单位锁存器和8-1选择器。
大功告成之后,该做测试了:现在这个8位存储器初期的状态是:EEEE EEEE(未知状态)
现在我想写入0001 0111怎么办呢?只需要两步:1.全部复位成0:0000 0000
2.将0,1,2,4位写入1
具体来说,只需要先将D(data)位一直输入0,打开W位(输入1),再依次在A(address)0,A1,A2位输入000,001一直到111即可完成归零操作,再将D输入1,打开W,地址依次输入000,001,010,100即可完成写入工作。最后的状态如下图:
画红圈代表该位存储值为1,不画代表为0.各位存储器的编号已经标出,很容易读出:0001 0111 和我们的预期相同。
我们知道,8bit=1byte,也就是说一个8位存储器的存储能力是1byte。我们可以并联很多个这样的8位存储器,比如如果把1073741824个这样的8位存储器并连到一块儿,就变成了一个容量为1GByte的大存储器,而那时候我们的地址位就不仅仅是3个就能存下这么简单的了。思考一个问题:现在主流的32/64位操作系统分别最大支持4G和16EB,(1EB=1024PB=1048576TB=......)(实际也到不了那么大,这和总线寻址,操作系统有关),这是为什么呢?再想想刚才3-8译码器的原理,不难得出以下公式:
1 BitNum = Log(2)(MaxMemBit)
也就是说地址位数(比如3-8译码器的地址位为3,32位操作系统地址最大是32位)等于最大内存寻址大小对2取对数。
事实上,这里所说的‘地址’只是一个我们想当然的某一个‘位’的地址,事实并非如此。人们把存储器分为很多区,每个区分为很多存储器板,每个存储器板会有一定量的存储体,每一个存储体可以存储很多位,每一个位在存储体里有特定的地址。这就相当于我们把100000个学生不仅仅从学号进行寻找,还给他们分配了班级,系别,年级等等嵌套式的整理,这使得管理起来非常明了,但是本质上和我们对他们直接进行‘学号寻址’是一样的。这些内容将在以后的总线设计中提到。
综上,我们对内存和地址的关系或许有了一定的了解,这样一来我们就有了一些大胆的猜想——既然所有计算机操作在处理器上都可以归结成‘加法’,‘移位’等非常少的基本逻辑运算,那么实现自动‘累加’就是实现自动化的一大进步。累加的加数的存储问题已经在本节被解决了,而怎么让处理器来处理‘累加’呢?每次‘累加’的结果怎么存储才有效率?这些将在不久以后解决。
至此,一个多位存储器也基本完成了。