在 Excel 中构建 16 位 CPU!国外大牛极限“整活”:128KB RAM、16 色显示,还有自定义汇编
文章讲述了一位技术爱好者在 Excel 中构建了一个全功能的 16 位 CPU 的过程。该 CPU 不仅配备了 128 KB RAM,支持 16 色显示,还能够使用一种自定义汇编语言。这个项目不仅展现了 Excel 在非传统领域的应用潜力,也体现了创新思维如何使复杂的计算机工程项目成为可能。
原文链接:https://www.tomshardware.com/pc-components/cpus/functional-16-bit-cpu-built-and-runs-in-excel-including-128kb-of-ram-16-color-display-and-a-custom-assembly-language
未经允许,禁止转载!
YouTube 视频截图展示了 Inkbox 创建的 Excel CPU 功能。(图片来源:YouTuber Inkbox)
Microsoft Excel 是深受很多人喜爱的电子表格程序,它的功能极为灵活,能够适应多种不同的用途——甚至只要有足够的能力和毅力,任何人都可以利用 Excel 的强大功能构建出实用的 CPU。尽管很多人知道可以,但真正去做而且做出来的人却少之又少。
但近日,一位 YouTuber Inkbox 发布了一段 16 分钟的视频,详细展示了他在 Microsoft Excel 中构建出一款 CPU 的过程。这款 CPU 的时钟频率为 3Hz,配备了 128KB 的 RAM,能显示 16 色,并且有一个分辨率为 128x128 像素的屏幕。(GitHub 地址:https://github.com/InkboxSoftware/excelCPU)
值得一提的是,Inkbox 完成这项工作时没有使用任何 Visual Basic 脚本或插件,完全依赖 Excel 的原生功能。正因如此,这个项目可以在任何安装了 Excel 的 PC 上重现。
在这个 Excel CPU 项目中,最为引人注目的成就之一是 Inkbox 为了这款实用的 Excel CPU,设计了一门功能完整的汇编语言。他把这门汇编语言命名为 Excel-ASM 16。这门汇编语言包含了 23 种不同的指令,并支持变量、标签以及二进制文件。虽然这些都是汇编语言的基础功能,但对于运行在 Microsoft Excel 上的 16 位 CPU 来说,已经是相当完备的功能了。
Inkbox 发布的 Excel CPU 视频截图。深入介绍了他设计的 Excel-ASM16 汇编语言,包括其指令及命名规则。(图片来源:YouTuber Inkbox)
强烈建议你观看作者发布的原始视频,这将帮助你深入理解 Excel 的底层功能,以及如何利用这些功能创建出功能完备的 16 位 CPU。Inkbox 详尽地解释了构建 16 位 Excel CPU 的每一个步骤,成功地演示了 CPU 的基础功能。虽然这些功能演示的时间被大幅度压缩——因为该 CPU 不超过 3 Hz 实际运行速度极慢,但依然足够给观众展示 CPU 内部的运行机制。
下面是 Inkbox 视频中的主要内容:
在更高级别的自定义 ISA 上设计 CPU 会更简单
不借助 Visual Basic 脚本和任何插件,在一个普通的 Excel 文件中实现一个配备有 128 KB RAM 和 4K 显示器的系统,你觉得这可能吗?从理论上讲,这是可行的。
Excel 是一个高级计算器,可以通过公式根据输入计算出对应的输出。
计算机则相对更为复杂,主要包括中央处理器(CPU)、随机存储器(RAM)和基于像素的显示器等组件。但其本质仍是一个“计算器”,由多个组件组成的 CPU 能够执行更高级的运算。
在 Excel 中模拟这个过程并不难。比如,这里有一个 3 位到 8 位的解码器芯片,它接收一个能表示 0 到 7 的三位二进制信号,并输出相应的 8 进制结果。也就是说,通过公式可以将输入和输出进行关联和运算。
Excel 如今已极为强大,能够模拟线路连接,但用其现有功能来设计 CPU 的难度极大。
不过 Inkbox 指出,在更高级别的自定义指令集体系结构(ISA)上设计 CPU 会更简单。ISA 是一本描述 CPU 工作规则的手册,它定义了一系列 CPU 指令及处理器的其他特性,包括一组寄存器,这些寄存器是用于存储和操作数据的内存单元,主要位于所谓的寄存器文件中。尽管基于 x86-64 体系结构的典型 CPU 拥有 981 个指令助记符,比如 MOV、ADD 和 OR,但实际上总共存在着 3,684 种变体。
但许多指令很少使用,对于 Excel CPU 来说已足够完善,无需全部实现。最终,Inkbox 决定仅实现 25 个操作码和 23 个指令助记符,包括加载、存储、寄存器间传输、算术运算、位运算、循环、比较、跳转、设置标志和 NOP。
提到编程,程序即是存储在内存中的一系列指令。它通过获取内存中的指令,解码并生成所需信号,执行操作,然后将输出存回寄存器文件或计算机内存,以执行每条指令。可以使用一个特殊的寄存器程序计数器来跟踪下一个指令的位置,这更多是基本 CPU 设计。按照该周期,第一个要构建的部件是取指单元,它读取程序计数器中指向的内存地址。
作者设计的 ISA 中的指令长度不是固定的。有些是 16 位,有些是 32 位,但取指单元在此总是检索一个完整的 32 位值,即 PC 和 PC+1 的值。但是,由于 PC 单元和内存单元还没有构建,必须跳过其中大部分逻辑。在获取指令后,被传递给控制单元。在此,指令被分解为指定的操作码、第一个寄存器操作数、第二个寄存器操作数和附加的 16 位立即数。因此,即使从内存中检索了一个完整的 32 位值,大多数指令的第二个 16 位也不会影响任何内容。该单元的每个输出针脚都有一个独特的公式,根据操作码,它会根据此表设置这些信号。
这些信号被传递到 CPU 的不同部分,比如算术逻辑单元(CPU 的核心)。ALU 对某些操作数执行操作。ALU 操作和操作数 1 直接来自控制单元,但操作数 2 实际上来自上面的多路复用器,因为它可以是 6 个不同的值之一,即 0、第二个寄存器的值、第二个寄存器中的内存值地址、4 位立即数、16 位立即数,或者该 16 位立即地址中的内存值。再次说明,内存单元还没有构建,所以作者会手动填充一些内容作为临时替代。
ALU 操作本身是一个 4 位值,因此它可以运行 16 种不同的函数,包括一些非算术操作,这会产生一个 32 位输出,即 16 位高位和 16 位低位。这些是整个电子表格中最重要的公式,因为它确定了处理器的输出。大多数操作都是直接的,不会影响高 16 位,但 MULT 指令确实会产生一个完整的 32 位结果,因此低 16 位将存储在第一个指定的寄存器中,高 16 位将存储在第二个寄存器中。除法将导致结果存储在第一个寄存器中,余数结果存储在第二个寄存器中。
滚动左移或右移位有点棘手。这里的第二个操作数是 4 位立即值,这意味着位可以向左或向右滚动多达 15 次。幸运的是,Excel 有一个 BITLSHIFT 和 BITRSHIFT 函数,再加上一点代数,Inkbox 就解决了这个问题。
在下一个单元之前,Inkbox 需要通过另一个多路复用器传递这两个结果,该多路复用器在高结果和低结果之间进行选择,可将每个结果分解成二进制。该输出连接到寄存器文件中寄存器 1 的输入,其中保存了 16 个通用寄存器。寄存器 2 的输入始终是 ALU 的高 16 位输出,REG1、REG2 和两个写入信号直接来自控制单元,如果任一写入信号设置为真,则指定的寄存器根据输入进行更改。在寄存器文件中,Inkbox 保留了四个系统标志,进位标志、零标志、符号标志和溢出标志。
如果 ALU 低 16 位结果大于 2^16 ,则会设置进位标志。提到这里的诀窍,Inkbox 表示:“还记得那个重要的 ALU 公式吗? 如果我告诉你,那不是最终输出公式呢? 我别出心裁地把那个长公式放在一个单元格上面,并通过将颜色设置为与背景相同的值来隐藏文本,然后使用模运算将结果保持在 16 位以内的最终结果,如果此上方单元格的结果大于 2^16,则会将进位标志设置为 true。其他标志更简单,如果低 16 位结果等于 0,则设置 ZF,SF 等效于低 16 位结果中的顶部位,OF 是通过溢出条件设置的。”
CPU 中的最后一个单元是程序计数器。当时钟信号为高电平时,PC 会检查是否需要重置为 0,步进两个字节或四个字节(等于一个或两个内存单元),或者如果 PC 设置立即标志被设置,则根据跳转条件是否满足,它将被设置为指令中指定的 16 位立即值。这些通常在 CMP 指令之后使用,并帮助创建循环和程序中的其他分支,这在编写一些代码时会更有意义。
这就构成了整个 CPU,情况还算不错,采用了合理的封装方式。但当 Inkbox 开始构建 RAM 单元时,情况有些不同了。带 16 位地址总线,有 65,536 个可寻址的 16 位内存单元,总共 128KB RAM,他将它们装入一个 256x256 表中,并在顶部安装了一个内存管理单元。这里的关键信号是来自控制单元的内存写入,即来自第一个多路复用器的地址以及来自 ALU 的值。该地址转换为基于 Excel 空间的 X 和 Y 坐标,如果内存写入信号设置为高,则此坐标处的单元格将更新为保存此新值。
当然,单元格不能自行决定其他单元格的写入,每个单元格都必须有其自定义的公式。但 Inkbox 并没有去疯狂地编写 65,000 个不同的方程,而是写了一个通用方程,适用于所有单元格。只需将其输入公式栏,然后按 Ctrl-Enter,公式就会自动应用到每个单元格。
要从 RAM 表中根据单个 16 位地址读取,Inkbox 使用了两个 Excel 函数:Address,以数字形式指定所需单元格的行和列;以及 Indirect,它获取指定地址的值。
现在,Inkbox 可以完成取指单元了。从 PC 寄存器中的地址获取两个内存单元,他在时钟旁边添加了两个按钮:一个是重置按钮,它会重置 PC 和 RAM 都恢复为 0;另一个是手动按钮,在手动模式下,指令由用户在取指单元的覆盖槽中指定。Inkbox 发现这在设计和测试 CPU 时非常方便,所以将其作为一个功能包含在内。第一个多路复用器也从内存的两个不同位置读取,从第二个指定寄存器中的地址和 16 位立即值中的地址。
不过,Inkbox 承认他在这里犯了一个错误:“我意识到我没有使用此第 3 个选项的指令,所以我不得不添加第 26 个指令。这是另一个 LOAD 指令,但这对间接寻址程序可能很有用。”
现在唯一缺少的是 4K 屏幕,这里的“4K”实际上指的是使用了 4KB 内存。在内存映射中,它将使用 128KB RAM 的最后 4KB,剩余部分可自由使用,这就是你的 RAM。屏幕由 128x128 个单元格组成,每个单元格代表一个像素,而 Inkbox 已经把这些单元格调整成正方形,而非矩形。屏幕将具有 16 种显示颜色,即每个像素 4 比特,或一个字控制四个像素。
“这在 Excel 公式中增加了另一层复杂性,因为我正在从 256x16 表读取数据到 128x128 表。”Inkbox 提到。
同样,Inkbox 只编写了一个公式并应用于整个表格,因为他发现,花三个小时编写和测试一个复杂的函数,要比机械地将简单的函数应用到每个单元格上花一个小时更有趣。在他解决这个问题之后,添加颜色非常简单,只需做一直以来的事情,应用条件格式。Inkbox 添加了 16 种不同的规则用于 16 种不同的颜色,并且通过将文本颜色设置为与背景相同,这些单元格看起来和行为就像常规像素。它已经不仅仅是一个芯片上的系统,而变成了一个电子表格上的系统。这里有一个非常简单的程序,它将屏幕上的前四个像素变成红色、蓝色、绿色和黄色。
首先,将寄存器 0 设置为 $F000。然后将寄存器 1 设置为 $48C7。现在应该就在这里,将寄存器1的值存储到寄存器 0 中的地址。这是一个在普通 Excel 电子表格中工作的 CPU。但是 Inkbox 还没有完成,因为现在他只是在手动模式下运行它。
设计了一种新的汇编语言
“但我现在想从内存运行更大的程序。为此我需要一个编译器。”为此,Inkbox 设计了一种新的汇编语言,基于其 ISA,我称之为 EXCEL-ASM16,它不仅具有 23 种不同的指令,还能在数据段中定义变量,使用十进制、十六进制或对于某些指令,使用 @ 来表示内存位置来定义数字,它支持标签、注释和额外的 ORG 指令,该指令设置下一条指令的地址,并且能够直接在程序中包含二进制文件。
对于汇编语言而言,这些功能已经相当基础了。虽然我可以增加更多特性,但对于一个 Excel CPU 的自制语言而言,现有功能已经足够。Inkbox 用 EXCEL-ASM16 编写了整个编译器,在 Excel CPU 中运行,并使用 Python 编写,确保了跨平台的兼容性。
但是,如何将编译后的程序加载到内存中呢?因为直接写入单元格会覆盖原有的公式,所以 Inkbox 调整了一些东西。
他要在顶部添加更多按钮,一个独立的重置内存按钮和一个读取 ROM 按钮。但他不能在这个文件中保留 ROM,因为 Excel 不喜欢保存由外部程序保存的具有迭代计算的公式——Inkbox 多次尝试在 RAM 下方保留 ROM 的做法,导致了许多损坏的电子表格。
“切记,永远不要在主文件中进行实验性测试。”Inkbox 建议,当你运行编译器时,首先指定程序文件,然后指定希望编译后的结果保存在一个名为 ROM 的 Excel 电子表格中,然后返回 Excel CPU 文件,切换读取 ROM 开关。调整内存函数后,打开时从 ROM 文件读取,然后在启动程序之前记得关闭:“这太神奇了,我能用它做各种超级酷的程序,最棒的是这仍然只是一个普通的电子表格。”
遗憾的是,它运行速度极慢。Inkbox 补充道,他需要通过按 F9 键手动更新时钟周期,运行每个程序都要花费很长时间,CPU 全速工作也就 2-3Hz ,视频中展示的所有程序都被大幅加速过,不过他“仍认为它是展示处理器内部工作原理的有用工具”。
总体而言,16 位 Excel CPU 项目虽然不可能成为现代计算技术的里程碑,但它展现了 Inkbox 在技术知识和创新方面的深厚功力。由于已经在 Github 上公开了 Excel-ASM16 以及其 CPU 和一些示例程序(https://github.com/InkboxSoftware/excelCPU),你可以在自己的 Excel 里试试看这个 16 位 CPU 是如何运行的。
尽管这样一个嵌入 Microsoft Excel 中的 16 位 CPU,仅支持 128x128 像素、16 色显示并且只有 128KB RAM,在日常使用中可能价值有限,但其存在本身意义重大。如果你曾梦想过“下载一个 CPU”,这可能是你梦寐以求的机会。
推荐阅读:
▶周鸿祎否认360进军直播带货;华为卷轴屏手机专利曝光;谷歌安全团队曝光苹果iOS三个零日漏洞 | 极客头条
▶“删不掉”的 AI 助手!开发者向 JetBrains 发出抗议:公司不让用 AI,代码可能会被泄露