计算机是怎么工作的?零基础红石cpu教程【第四章-控制器,指令集设计与编程】

这篇教程的前三章介绍了计算机的组成,存储器与运算器的搭建以及如何把它们连接起来。在这章中,我们将制作一个发号施令的控制器,并编写和运行我们的第一个程序。

指令周期与程序计数器

程序是一系列按照顺序排列的指令。指令指示了在当前步骤CPU具体需要做什么,例如是将两个数相加,还是将数据从内存中载入到寄存器。在计算机开机时,程序以一系列指令的形式被载入到计算机的内存中。

计算机使用程序计数器来追踪程序运行到了哪里。程序计数器是保存当前指令内存地址的寄存器。每次开机时程序计数器将会重置并指向程序的第一条指令。当一条指令运行完毕后程序计数器将会将自身的值+1,指向内存中下一条指令。人为修改程序计数器的值可以改变程序的运行位置。这样做可以实现跳转操作,例如在执行完最后一条指令后跳转回程序头再次执行程序。这种执行方式叫做循环结构。

计算机执行指令的过程主要有以下四个步骤

1
取指令
CPU从内存中获得下一条要执行的指令。这条指令的指令内容将会被送入译码器以进行下一步操作。
2
指令译码
CPU将指令的值转换为具体的操作,例如打开寄存器,将数据发送给数码管显示器,等等。
3
指令执行
CPU通过控制总线依次发送控制信号让各部件完成工作。
4
数据写回
将操作产生的结果写回到内存中(如果有)。

计算机将会重复这四个步骤直到程序运行完毕。下面让我们用一条示例程序进行具体演示。

在执行这条程序前,我们需要首先将程序按照左侧的内存地址加载到内存中。在我们的红石计算机中,程序已经被提前编写进内存中。

复位

在开机以后,计算机向所有部件发送复位信号。串行总线接收器将准备好接收信号,寄存器将会被清空。程序计数器将被重置以指向内存地址0。

取指令

我们的计算机含有两个内存模块分别存储指令和数据。在每个指令周期的开始,程序计数器将保存的值通过内存地址总线发送给两个内存模块。控制器将发送一个取指信号给内存模块。内存模块收到信号后将输出连接到给译码器。至此取指令阶段完毕。

译码器

每条指令都对应了不同的具体操作,例如将当前地址上的数据写入寄存器A(DRDA)可以被分解为以下步骤:数据内存模块将当前数据在数据上广播;控制器在数据地址线上发出控制信号,指定该数据为寄存器A接收;寄存器A接收到控制信号,目标地址与自身id一致,更新自身数据。

将指令转换为具体操作,并依次在总线上发出控制信号的结构被称为译码器。首先,指令将被送入连接着所有译码器单元的多路复用器。多路复用器根据不同指令激活对应的译码器单元。单个译码器单元包含一系列预先编码的总线发送器。当接收到上一个器件发出的“执行完成”信号后,译码器将发送下一个信号。译码器的结构如下图:

图中为多层译码器的最顶层。图片的最右侧是八位多路复用器,图片中已设置为0001 0000指令。要往控制总线上发送的执行者id通过木块设置,从右往左分别是0000 1011,0000 1001,0001 0000和0010 0011。必要的数据写回也将在这一阶段完成。四个发送器都发送完毕后将会给程序计数器脉冲信号,代表本指令结束,进入下一个取指周期。

指令集与图灵机

指令集是CPU设计可运行的所有指令的集合,描述了所有可以被执行的操作。指令分为操作码和操作数两部分。前者描述要执行的操作,后者为所需要的补充信息。

例如在下图的指令集中,WRA 0001 1001代表一条操作码为WRA的指令(传送数据进寄存器A),操作数0001 1001代表要传送的数据在数据内存中的地址。

直接使用二进制来写的程序会难以阅读。与其直接记录二进制,我们不妨使用指令的名称来代替。这种编程方式被称为汇编。

指令集根据长度等特点分为很多种。在我们的示例中,操作码和操作数为固定的八位长度。它被称为十六位定长指令集(操作码和操作数加起来是十六位)。

现实生活中的大部分计算机为图灵机。图灵机的具体定义设计计算理论相关内容,具有图灵完备性的计算机能够执行所有的计算问题,具有一下基本操作:将线性的内存空间看做一条可以用来记录数据的纸带,计算机能够操作当前内存,进行值的修改(自增,减少,清零等),能够具有控制流操作(进行判断),能够进行循环(跳转回特定位置)等操作。对应到具体指令中则包括了条件判断(如果满足…条件则执行…),跳转(运行到这里时,跳转回程序头继续执行)。

我们已经实现了对数据的操作,让我们了解一下控制操作如何进行。

跳转与循环

循环结构是编程避不开的话题。在程序中实现循环需要跳转指令,即跳转到指定程序位置再继续运行。如果你写过visual basic等语言,你应该对goto关键字很熟悉——它们所作的事情基本一样。

程序中的跳转需要依靠程序计数器实现。程序计数器保存了当前执行到的代码位置,将程序计数器的值改为要跳转到的位置就能实现跳转。程序计数器中的值被改变后,计算机将会根据改变后的新值进行取指令操作。

没有条件的循环就是死循环,我们的程序会卡在里面反复执行,直到因为溢出等错误停下来。要跳出循环,我们可以对跳转指令加入判断,或者,在满足特定条件时跳过跳转指令。

编程中常见的判断可以用一些巧妙的方法来实现。加法器可以用来实现比大小类的判断。将一个数与另一个数的相反数相加(还记得怎样对负数进行运算吗?第二章中有讲解),结果如果为零可以确定两个数相等;将一个数与另一个数的负数相加,判断结果是否为负数(看补码的第一位!)就能实现比大小的操作。

试一试
本教程到这里(大概是)结束了哦,看完教程后,不妨自己在游戏中亲自动手试一试!如果觉得完整的红石计算机工程量太大,不妨试试简单一些的部件,例如计算器。

附:教程中的红石计算机的实际工作视频。

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
洛天依九周年
颜文字
Emoji
小恐龙
花!
上一篇
下一篇