自制了一台计算机,可编程哦_涛歌依旧的博客-程序员信息网_制作计算机

技术标签: s4: 计算机组成  其他  

接触计算机多年,经常会有一种云里雾里的感觉。今天,一起动手来自制一台计算机,加深体会和理解。

必须说明的是,计算机有复杂的,也有简单的,但结构和原理基本相通,本文制作的是最简单的计算机。

我也会对自制的简单计算机进行编程,体会编程的感觉,知道编程是怎么回事,理解计算机工作的原理。

一. 自制计算机的外形

在很长一段时间内,总是搞不清楚一些基本的概念和原理:比如什么是硬件? 硬件内部是怎样运行的?什么是软件?软件在哪里?软件究竟是怎样在硬件上跑起来的?硬件究竟是怎样执行软件的?

我将自制一台简单计算机,从电路的角度理解计算机的工作原理,给这台计算机编程,体会硬件和软件之间的相互作用。如下图是我制作的一台最原始的计算机,先来一睹它的外形,看看长啥样:

图片

冯诺依曼结构

自制计算机

CPU运算器

U3加法器

CPU控制器

U1计数器

U4触发器

U5非门

时钟信号

存储器

U2存储器

输入设备

不涉及

(因为输入内容已提前存放于U2中)

输出设备

数码管显示器

二. 自制计算机的构成

接下来,我们一起看看自制计算机的构成,从简单到复杂,我们一步一步地制作和讲解。

1. RS锁存器

来看RS锁存器电路,其特殊在于:U3的输出作为U2的输入,U4的输出作为U1的输入:

图片

很容易分析出逻辑关系:

S

R

Q

Q’

1

0

1

0

0

1

0

1

0

0

保持

保持

1

1

0

0

有三点值得注意:

  • 当S=0,R=0时,对或门没有任何贡献,所以不会对电路产生影响。此时,Q和Q'是相反的,必有一个为0,另一个为1.

  • 当S=1,R=1时(这种输入并没有错),Q和Q'都为0,我们对这种情况并不感兴趣,所以可以忽略,故约定S和R不同时为1.

  • 不考虑S=1,R=1这种输入组合时,Q和Q'总是相反的。

2. D锁存器

来看D锁存器电路。可用多个器件来确保RS锁存器两个输入端不能都为1,下图R和S输出端永远不可能同时为1:

图片

来分析上图电路动图: 

  • 当E=0时,无论D怎么变, 经历R和S两个与门后,R和S的输出端总是0,所以Q和Q'总是保持原状。

  • 当E=1时,经历R和S两个与门时,R和S输出端的值完全取决于D, 显然有Q=D.

可以看出:E是一个控制者,只有当E=1时,D的值才会保存到Q上。当E=0时,无论D怎么折腾,Q总是无动于衷。

3. D触发器

来看D触发器电路,它由两个D锁存器组成,构思非常巧妙,仅在上升沿触发时才有效:

图片

来分析一下这个电路动图: 

  • 上下两个D锁存器的使能端是相反的,所以,无论控制开关E是0还是1,上下两个D锁存器必然有一个无效,导致不能把D数据保存到Q端。

  • 当E从1变为0时,下面的D锁存器无效,因此也不能把D数据锁存到Q端。

  • 当E从0变为1时,下面的D锁存器生效,上面的D锁存器无效,但U4的输出端之前已经获取了D端的数据,所以趁着下面的D锁存器的生效,把U4输出端的数据保存到Q端。因此,整体看来,当E从0变化到1时,能把D数据锁存到Q端。这种锁存,只在信号发生0到1的跳变瞬间,所以叫上升沿触发锁存。

可是,这个D触发器有点复杂,我们来抽象一下,直接使用封装好的D触发器,如下图,可以看到:当且仅当E从0变到1时,才把D保存到Q.

图片

D触发器只能触发保存1位二进制,我们可以直接用封装好的74175芯片实现4位二进制的保存,如下图:

图片

用开关提供上升沿,需要手动掰弄开关,非常麻烦。能不能搞一个自动上升沿呢?当然可以。

我们引入时钟信号,它不停地在0和1之间做变换,从而产生上升沿。时钟信号很简单,看动图:

图片

想一下,为什么CPU需要时钟才能工作?这个问题很有趣,也很好回答,可以从两个方面来看:

  • 计算机的理论模型是图灵机,而图灵机是有限状态机,需要有时钟信号驱动状态变化。

  • 计算机中的数据需要按先后步骤进行保存和更新,以上述触发器为例,需要有上升沿信号来触发,所以需要时钟信号。

4. 计数器

利用D触发器,可以制作其他器件。如下动图中所示的计数器,遇到脉冲就计数:

图片

时钟周期是1秒,每秒会有一个上升沿信号输入到U1的CLK端,于是U1的Q端就会每秒在0和1之间跳动一次,显然U1的Q'也是每秒在0和1之间跳动一次。

也就是说,对于U2的CLK而言,遇到一次上升沿需要2秒,因此U2的Q在0和1之间跳动1次需要2秒,看下表:

第n秒

U1

U2

U3

U4

U4U3U2U1

0

0

0

0

0

0

1

1

0

0

0

1

2

0

1

0

0

2

3

1

1

0

0

3

4

0

0

1

0

4

5

1

0

1

0

5

6

0

1

1

0

6

7

1

1

1

0

7

8

0

0

0

1

8

9

1

0

0

1

9

10

0

1

0

1

A

11

1

1

0

1

B

12

0

0

1

1

C

13

1

0

1

1

D

14

0

1

1

1

E

15

1

1

1

1

F

一目了然,U1的Q变化最频繁,U2的Q变化不频繁,U3的Q变化更不频繁,U4的Q最懒惰。很显然,上述电路是一个计数器,从0到F,  一个一个地计数。

计数器很重要,若要不断地从存储中取出程序或数据,就得靠它了。所以,计数器被用作程序计数器,即Program Counter. 抽象封装好的计数器如下:

图片

5. 完整计算机

到此为止,我们制作并使用了计数器、加法器、触发器、时钟信号、非门以及数码管显示器,把上述器件组装在一起,形成一台完整的计算机,如下所示:

图片

这台简单计算机的电路图硬件都搭建好了,软件在哪里呢?软件就是程序,包括指令和数据。我们把软件程序存放在存储器U2中,其中存放的程序内容是:

000000000000000100000010000000110000010000000101

其功能是:计算1+2+3+4+5,这台计算机工作过程的动图如下,可以看到:1+2+3+4+5=FH=15

图片

现在最大的疑问是:为什么上面那段程序表示1+2+3+4+5呢?计算机电路又是如何执行程序的呢?我们来仔细分析一下。

U2存储器中的程序是:

000000000000000100000010000000110000010000000101

这个程序不直观,为便于阅读,我们来分割一下:

可以看到,第一行是0,第二行是1,第三行是2,第四行是3,第五行是4,第六行是5. 存储器U2的输入端和输出端对应的关系如下:

U2输入端

A3A2A1A0

U2输出端

D3D2D1D0

其具体内容与我们写的程序有关
 

0000

0000

0001

0001

0010

0010

0011

0011

0100

0100

0101

0101

U2存储器左边的U1刚好是计数器,从0一直数到F,因此,当计数器数到3时,U2输入端刚好就是3,而U2此处存储的数据刚好是3.

我们对照上面的动图,整体理解一下计算机电路图的执行流程:

第1步:

开始,U1的输出值0,左边数码管显示0,U2输出值为0,U3加法器的输出值0,U4的输出值是0,右边数码管显示0.

第2步:

时钟信号经历上升沿,U1开始计数到1,U2输出值为1,左边数码管显示1,U3加法器的输出值还是1,但U4没有经历上升沿,故U4的输出值是0,右边数码管显示0.

第3步:

时钟信号经历下降沿,U1保持在1,U2输出值为1,左边数码管显示1,U3加法器的输出值还是1,U4刚好经历上升沿,故U4的输出值是1,右边数码管显示1.     

还有很多步骤没有列出,我们把所有步骤放到表格中:

时钟信号

U1输出

U2输出

U3输出

U4输出

 

0

0

0

0

0

上升沿

1

1

1

0

下降沿

1

1

1

1

上升沿

2

2

3

1

下降沿

2

2

3

3

上升沿

3

3

6

3

下降沿

3

3

6

6

上升沿

4

4

A

6

下降沿

4

4

A

A

上升沿

5

5

F

A

下降沿

5

5

F

F

对照电路图看表格,一目了然。可以看到,由于引入了U4触发器来保存数据,电路再也不会出现之前文章中遇到的死循环了。到此为止,我们的连续加法器终于实现了。

而且,这个连续加法器是自动的,这完全是因为有了时钟信号,它不断地制造上升沿,触发着计数器往前走,去存储器获取指令和数据,也触发着把U3加法器输出端的值安全地保存到U4的输出端,让它再次输入到U3参与计算。

如果没有时钟信号,我们还要去一个开关一个开关地掰弄,去构造上升沿来控制电路。我在仿真时,时钟信号频率是1Hz,也就是周期是1秒,信号为0的时间占0.5秒,信号为1的时间占0.5秒,1秒之内有1个上升沿和一个下降沿。

我把时钟的频率调快到10Hz,发现连续加法的计算时间也变快了10倍,这是因为:时钟信号的频率快了,上升沿的次数就更频繁了,自然能更快地迫使其他器件上的值进行变化。

我电脑的主频是3.6GHz,这就是时钟频率,它每秒产生几十亿次上升沿/下降沿信息,迫使着其他器件快速变化。一般来说,主频越大,CPU的运算速度就越快,道理显而易见。

图片

6. 硬件与软件

电路是硬件,存储在U2中的信息是软件。我们买到手机后,基本不会对硬件进行变化,但经常安装或者卸载其中的软件,而正是不同的软件,使得手机有不同的功能。

在不改变上述电路硬件的情况下,我们可在U2中装入不同的软件,从而实现不同的功能。比如,我们写一个新程序:

00000000000000100000010000001000

把程序塞到U2存储器中,重新让电路通电。从如下动图中显而易见,这是在计算2+4+8=EH=14,由此可见:不同的软件程序,实现了不同的功能。

图片

三. 自制计算机的编程

用0和1写出来的程序,叫机器语言程序,直接在硬件上运行,比起掰弄电路开关,已经有很大进步。但是,如果一直用0和1来写程序,还不能出现一点点差错,谁受得了呢?

一大串的0和1,太难懂了,它是机器世界的语言,而人又有人的语言,这两种语言是不相通的,因此,我们需要探索出更好的编写程序的方法,让人更轻松点。怎么办?

我们回头看1+2+3+4+5的机器语言:

000000000000000100000010000000110000010000000101

怎么降低人编写程序的难度呢?我们可以考虑这么写:

​​​​​​​

ORG 0000HDB 00HDB 01HDB 02HDB 03HDB 04HDB 05HEND

这种语言叫汇编语言,看起来舒服多了。现在的问题是,需要一个工具把汇编语言转化为机器语言,这个转换的工具就叫汇编器,如下图:

图片

现在编程就简单多了:先用汇编语言写程序,然后用汇编器这个工具,把汇编语言程序转化为机器语言程序。

如果要计算2+4+8,我们再也不用与0和1这种折磨人的机器语言打交道了,直接用汇编语言写汇编程序,如下:​​​​​​​

ORG 0000HDB 00HDB 02HDB 04HDB 08HEND

经汇编器工具转换后,上述的汇编语言程序变为了机器语言程序,而这正是硬件电路所需要的语言,具体如下:

00000000000000100000010000001000

然后,我们自制的计算机执行这段机器语言程序,得到的结果是14. 可是,用汇编语言还是憋屈,不好理解,不近人情。

于是,需要再次抽象,越抽象越接近事物的本质,为了降低编程难度,我们再次优化编程方法,采用高级语言,如下:​​​​​​​

int a=1+2+3+4+5;printf("%d", a);

然而,电路毕竟不认识高级语言,只认识高低电平,即1和0,所以,也需要工具来对高级语言进行转换,关系如下所示:

图片

       

我们从如下表格中,可以看到机器语言、汇编语言以及高级语言的对比。显然,用高级语言编程更容易,更加直观:

目的

机器语言

汇编语言

高级语言

计算

1+2+3+4+5

000000000000000100000010000000110000010000000101

ORG  0000H

       DB  00H

       DB  01H

       DB  02H

       DB  03H

       DB  04H

       DB  05H

END

int a=1+2+3+4+5;

printf("%d", a);

计算

2+4+8

00000000000000100000010000001000

ORG  0000H

       DB  00H

       DB  02H

       DB  04H

       DB  08H

END

int a=2+4+8;

printf("%d", a);

这里有两点补充说明:

  • 上述的汇编语言很简单,不涉及到指令,只涉及到数据存放的位置。有一些朋友可能觉得上述汇编语言的指令是伪指令,但没有关系,我们依然把它当汇编语言理解,并无副作用。而且经汇编器转换后,生成的机器代码,确实可以在我们制作的计算机上运行。

  • 上述的高级语言,经通用的编译器和汇编器转换得到的机器语言程序,没法在我们自制的计算机上运行,必须经过特定的编译器才可以,我们无需对这种特殊的编译器做进一步了解,毕竟编译器只是个转换工具。

我们已经从原始的掰弄开关来控制电路,上升到利用机器语言0和1来控制电路,然后上升到用汇编语言来控制电路,最后上升到利用高级语言来控制电路。

逐步地,我们从纷繁复杂的电路细节中解脱出来,这是一个不断进行抽象、不断远离具体细节、不断接近事物本质的过程,从此,也站在更高的维度上了。

好的,到此为止,本文也将告一段落。对于想搞懂计算机原理的朋友而言,如果能亲自动手完成本文的实验,那么肯定会加深对计算机原理的理解,加油!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/stpeace/article/details/122378132

智能推荐

前端学习日记3-如何设置网页背景图片_折り纸的博客-程序员信息网_网页背景图片怎么设置

法1:在html页面body后直接设置<body background="image/A.jpeg"></body>法2:在css文件中选择body进行设置背景body{background: url("image/A.jpeg")}法3:在head中设置css样式<style>body{background: url("image/A.jpeg")}</style>...

Redis集群都有哪些坑_aidanzheng的博客-程序员信息网_redis集群 坑

集群完整性检查默认情况下,如果redis的虚拟slot没有全部分配完,那么集群不可提供服务。那么在集群故障转移期间,redis集群没法提供服务,这在有些业务场景下是没法接受的。为此我们一般将参数cluster-require-full-coverage设置为no。这样只有故障的节点负责的slot不可用。pubsub广播Redis集群为了实现所有的订阅的客户端都可以接收到发布的消息,但是不同的客户端可能连接的是不同的主节点,为此redis会广播所有的发布的消息到所有的节点,如果发布的消息较大,网络开销将

数据结构与算法——专栏索引篇__为光的博客-程序员信息网

前言数据结构与算法在编程里是很重要的一个环节,走过这条路,就算是入了编程的门了。并且数据结构与算法的思想在各个编程语言中都能用到,是编程中重要的思想锻造历程。我在我的博客中,会用C语言讲解数据结构与算法中的重要知识点,不仅是因为C语言是基础,更是因为C语言的多变性,而且C语言是较为复杂的,我们需要自己手动去实现很多东西,不像Python,Java,很多东西已经在那里了,我们是得不到充足的锻炼...

Android APP启动时的黑白屏问题_牛角尖呀的博客-程序员信息网

Android APP启动时黑屏或者白屏的问题很常见,解决起来也不复杂。下面总结一下出现的原因,以及常见的解决此问题的两种方案。问题出现先看一下黑屏或者白屏的情形吧,在SplashActivity加载布局文件之前设置主线程睡眠几秒钟,使黑/白屏必然出现@Overrideprotected void onCreate(Bundle savedInstanceState) { ...

JSNES:用JavaScript编写的NES模拟器_dingshi7798的博客-程序员信息网

今天在最不可能的,可能是毫无意义的,但仅仅是惊人的使用JavaScript奖将归本Firshman和他的任天堂娱乐系统模拟器,JSNES。 访问JSNES网页... 该仿真器是基于Java的端口vNES项目。 它使用HTML canvas虽然声音尚不支持屏幕渲染元素(对不起,Internet Explorer用户)。 有17个游戏尝试。 大多数人会在Firefox 3.5或Safari 4...

攻防世界之NewsCenter_行于其野的博客-程序员信息网

题目WP在searchnew中随意输入字符串,burpsuite抓包发现输入的字符串以post形式提交给了search参数将http请求打包,用sqlmap探测search参数是否存在sql注入风险注入成功接下来直接将后台数据库直接输出sqlmap -r searech -p search --dump找到flag啦~手动注入:发现哪一列可以回显打印数据库的表search=0' union select 1,group_concat(table_name),3 from

随便推点

windows下Jmeter5.2下载安装及100用户并发实战详解_秋9的博客-程序员信息网

windows下Jmeter5.2下载安装及100用户并发实战详解一、Jmeter5.2下载及安装官网下载地址:https://jmeter.apache.org/download_jmeter.cgi界面截图如下:下载后解压(注意解压后的目录中不能有空格和中文),双击apache-jmeter-5.2\bin\jmeter.bat启动,启动后的界面为:备注...

Vim 插件管理器对比(转)_weixin_33795833的博客-程序员信息网

为什么80%的码农都做不了架构师?>>> ...

linux安装Docker并配置阿里云加速镜像_林九的博客-程序员信息网

什么是Dockerdocker是解决了运行环境和配置问题的软件容器Docker三要素容器:容器是用镜像创建的运行实例,利用容器Docker可以运行一个或一组应用;可以把容器看成一个简易版的linux环境;容器和镜像一模一样,只不过容器可以操作;镜像:镜像就是个只读模板,用来创建docker容器,一个镜像可以创建多个容器;仓库:仓库是集中存放镜像的地方;Docker安装CentOS版本必须是7.0以上版本查询版本命令cat /etc/redhat-release

云运维的启示与架构设计_钱曙光的博客-程序员信息网

声明:本文首发于CSDN,禁止未经许可的任何形式转载,可咨询文末的责编。UPYUN 创业于2005 年,当时服务器使用的网卡还是Marvell的芯片,要通过自定义内核和驱动源代码做编译才能驱动起来。而十年后在运维方面已经产生了翻天覆地的变化,本文系统地总结了 UPYUN 的云运维的野蛮成长、踩过的坑以及现阶段的状况。运维的艺术运维的艺术是弹性。首先,从无到有,这非常重要。无论运维做得多厉害...

计算机创新发展战略,计算机行业投资机会报告:智能汽车创新发展战略发布_Baolimeowmeow的博客-程序员信息网

智能座舱有望进入普及阶段市场增量空间大:目前车载无线终端设备需求旺盛,智能化趋势明显。智能座舱融合了车内多屏,是未来车内智能化人机交互的核心,也是叠加ADAS、ARNR等新技术的关键接口:而ADAS作为无人驾驶的早期阶段,将会是未来几年增速最快的细分市场。受益于ADAS渗透率的提升,车内信息交互需求的快速增长肢术相对成熟的智能座舱产品将进入大众化普及阶段。车路协同拓展感知,LTE-V2X将是发展重...

计算机信息安全专业_莱词的博客-程序员信息网

信息安全专业信息安全专业,根据教育部《普通高等学校本科专业目录(2012年)》,专业代码为080904K,属于计算机类(0809)。具有全面的信息安全专业知识,使得学生有较宽的知识面和进一步发展的基本能力;加强学科所要求的基本修养,使学生具有本学科科学研究所需的基本素质,为学生今后的发展、创新打下良好的基础;使学生具有较强的应用能力,具有应用已掌握的基本知识解决实际应用问题的能力,不断增强系统的...