几个月前,我突然对自己对计算机硬件原理一无所知而感到震惊。 我仍然不知道
现代计算机是如何工作的。
我读了书
“但是他怎么知道?” 克拉克·斯科特(Clark Scott)详细描述了一个简单的8位计算机:从逻辑门,RAM,处理器晶体管开始,以算术逻辑设备和输入输出操作结束。 我想用代码实现所有这些。
尽管我对微电路的物理不是
很感兴趣,但是这本书只是沿着波浪滑动,并且很好地解释了电路以及位在系统中的运动方式-读者无需了解电气工程。 但是文字描述对我来说还不够。 我必须看到实际情况,并从不可避免的错误中学习。 所以我开始用代码实现电路。 这条路很棘手,但很有启发性。
我的工作结果可以在
简单的计算机存储库中找到:一个简单的计算器。 他很简单,他会计算。


样例程序处理器代码实现为
一堆打开和关闭的
可怕逻辑门 ,但它可以工作。 我
运行了单元测试 ,我们都知道单元测试是程序正常运行的无可辩驳的证明。
该代码处理
键盘输入,并使用为专业字体精心制作的字形集(我称为
Daniel Code Pro) 在显示屏上显示文本。 唯一的弊端:要接受键盘输入和输出结果,我必须通过
GLFW连接通道,否则,它是电路的完全软件仿真。
至少可以说,我什至写了一个
粗鲁的汇编程序 ,使我对很多事情都睁开了眼睛。 他并不完美。 实际上,甚至有些cr脚,但他向我展示了很多人在很多年前就已经解决的问题。
但是,为什么要这样做呢?
“十三岁的孩子正在Minecraft中建造处理器。 当您可以使用电报中继器制作真正的 CPU时,请致电我。”我对CPU设备的思维模型停留在初学者的计算机科学教科书级别。
我在2013年编写的Gameboy模拟器处理器实际上看起来并不像现代CPU。 即使仿真器只是一个状态机(状态机),它也不会在逻辑门级别描述状态。 仅使用
switch
并保持寄存器状态几乎可以实现所有功能。
我想更好地了解一切工作原理,因为例如,我不知道L1 / L2缓存和流水线是什么,而且我不确定我是否完全了解有关Meltdown和Spectre漏洞的文章。 有人说他们以一种使用处理器缓存的方式来优化代码,但是我不知道如何检查它,只说一句话。 我不太确定所有x86指令的含义。 我不了解人们如何向GPU或TPU提交任务。 一般来说,什么是TPU? 我不知道如何使用SIMD指令。
所有这些都是建立在需要首先学习的基础上的。 这意味着要回到基础并做一些简单的事情。 克拉克·斯科特(Clark Scott)的上述书籍描述了一个简单的计算机。 这就是为什么我从它开始。
斯科特的荣耀! 他工作!
斯科特的计算机是一个连接到256字节RAM的8位处理器,全部通过8位系统总线连接。 它具有4个通用寄存器和
17个机器指令 。 有人
为网络制作了一个
视觉模拟器 :这真的很棒。 想到跟踪电路的所有状态要花多长时间,真是令人恐惧!
用Scott处理器的所有组件进行电路。 版权所有2009-2016。 齐格伯特·菲尔宾格(Siegbert Filbinger)和约翰·克拉克(John Clark Scott)本书伴随您从适度的逻辑门到存储器和寄存器中的位的路线,并继续对组件进行分层,直到您获得与上图相似的内容。 我强烈建议您阅读本书,即使您已经熟悉这些概念。 只是不是Kindle版本,因为图表有时很难放大和分解屏幕上的“阅读器”。 我认为,这是一个长期存在的Kindle问题。
我的计算机与Scott的版本不同,不同之处在于我将其更新为16位以增加可用内存量,因为仅存储ASCII表的字形占用了Scott的8位机器的大部分,而为有用的代码留出了很少的空间。
我的开发过程
通常,开发是按照以下方案进行的:阅读文本,研究图表,然后尝试以通用编程语言实现它们,并且绝对不使用任何专用工具来设计集成电路。 我之所以在Go上编写模拟器,仅仅是因为我对这种语言有点熟悉。 怀疑论者可能会说:“愚蠢! 您不能学习
VHDL或
Verilog或
LogSim或其他东西。 但是到那时,我已经写了我的位,字节和逻辑门,并且跳得太深了。 也许下次我将学习这些语言并了解我浪费了多少时间,但这是我的问题。
在大型电路中,只需在计算机中传输一堆布尔值,因此适合布尔代数的任何语言都适用。
将方案应用于这些布尔值有助于我们(程序员)得出含义,最重要的是,确定系统将使用哪个
字节顺序,并确保所有组件都以正确的顺序在总线上传输数据。
这很难实现。 为了避免产生偏见,我选择了一个具有相反字节顺序的表示形式,但是在测试ALU时,我不明白为什么会出现错误的数字。 我的猫听到了很多很多无法表达的表情。
开发进展不快:也许我花了大约一两个月的空闲时间。 但是当只有处理器成功完成操作时
,我幸福地处在第七天堂。
一切都照常进行,直到涉及到I / O。 该书提出了一种系统设计,该系统设计具有简单的键盘和显示界面,可将数据输入机器并输出结果。 好吧,
我们已经走了很远 ,半途而废是没有意义的。 我设定了一个目标,以实现在键盘上打字并在显示屏上显示字母的目的。
周边设备
外围设备使用
适配器模板作为CPU与外界之间的硬件接口。 很容易猜出该模板是从软件设计中借用的。
I / O适配器如何连接到GLFW窗口通过这种分离,事实证明将键盘连接和显示到运行GLFW的窗口非常简单。 实际上,我只是从
仿真器中提取了大部分代码,并对其进行了一些修改,以使Go通道可以作为I / O信号工作。
我们启动电脑
这可能是最难的部分,至少是最麻烦的部分。 用如此有限的指令集编写汇编程序很困难,而在我的粗略汇编程序中,情况更糟,因为您不能欺骗任何人,除非您自己。
最大的问题是要处理四个寄存器,通过从寄存器中提取数据来跟踪它们并将它们临时存储在内存中。 在此过程中,我记得Gameboy处理器具有堆栈指针寄存器,以方便加载和加载寄存器。 不幸的是,这台计算机没有那么豪华,因此您不得不不断地手动在内存之间传输数据。
我决定花时间在一条
CALL
伪
CALL
以调用一个函数,然后返回到该点。 没有此功能,呼叫只能在一个深度上进行。
另外,由于机器不支持中断,所以我必须实现可怕的键盘状态轮询代码。 该书讨论了实现中断所必需的步骤,但这使电路变得非常复杂。
但是,别再抱怨了,我仍然编写了
四个程序 ,其中大多数都使用某种通用代码来呈现字体,键盘输入等。这不是操作系统,但是可以理解简单OS的功能。
这并不容易。 文本编写器程序中最困难的部分是正确确定何时跳转到新行或按Enter时会发生什么。
main-getInput: CALL ROUTINE-io-pollKeyboard CALL ROUTINE-io-drawFontCharacter JMP main-getInput
文本编写器程序的主要周期我没有费心实现Backspace键和修饰键。 但是我意识到文本编辑器的开发需要多少工作,并且它是多么乏味。
结论
对我来说,这是一个有趣且非常有用的项目。 在汇编语言编程中,我几乎忘记了下面的逻辑门。 我进入了抽象的更高层次。
尽管此处理器非常简单,并且与笔记本电脑中的CPU相距甚远,但在我看来,该项目教会了我很多东西,尤其是:
- 位如何在所有组件之间通过总线移动。
- 简单的 ALU如何工作?
- 简单的 Fetch-Decode-Execute循环是什么样的。
- 没有堆栈指针寄存器和堆栈概念的机器很烂。
- 那辆不间断的汽车也很烂。
- 什么是汇编程序,它是做什么的。
- 外设如何与简单的处理器交互。
- 简单字体的工作方式以及如何在显示器上显示它们。
- 一个简单的操作系统可能看起来像什么。
那接下来呢? 该书说,自1952年以来,没有人生产过这样的计算机。 这意味着我必须研究过去67年的材料。 我要花点时间 我可以看到
x86手册的长度为4,800页,足以让您睡前愉快,轻松地阅读。
也许我会对C语言的操作系统有所宠爱,我会用
PiDP-11构建套件和电烙铁来消磨夜晚,然后放弃这个东西。 我不知道,我们拭目以待。
认真地说,我正在考虑探索RISC体系结构,可能是RISC-V。 最好是从早期的RISC处理器开始,以了解其起源。 现代处理器具有更多功能:缓存等等,我想了解它们。 有很多东西要学。
这些知识会在我的主要工作中派上用场吗? 可能有用,尽管可能性不大。 无论如何,我都喜欢,所以没关系。 感谢您的阅读!