思路:造一个最简单的能执行程序的计算机
故事起源
- 先驱想创造一个能执行程序的计算机,让我们来帮助他
开始构思 !
- 我们知道,程序是由(代码 & 数据)组成的
- 比如:假设我们想要计算
1+2+3+...+100
,那么我们不费吹灰之力就能写一个程序来完成这件事 - 不难理解:
- 数据是程序处理的对象
- 代码描述了程序是如何对数据进行处理的
ok,既然我们想让计算机执行程序,那应该将程序放在哪儿呢 ?
- 程序有几十行代码的“小程序”,也有上万行代码的“大程序”(比如大型游戏程序)
- 显然,我们应该将程序放到一个拥有较大存储空间的“容器”中,这个容器叫:存储器
- 于是,存储器诞生了,程序可被放入存储器中,等待着被 CPU 执行
等等,啥是 CPU ?
- CPU,中文名叫中央处理器,听起来牛逼吧 ?!
- 嗯,它确实牛逼,它是负责处理数据的核心电路单元,程序执行全靠它
- 还不懂 ?
- 你想啊,一个计算机它如果只有存储器,那还是不能计算嘛
- 所以就得 CPU 扛起计算的重任喽
- 咋扛呢 ?傻瓜,给 CPU 造运算器啊,然后就能对数据进行各种处理了
- 啥 ?你觉得运算器太复杂 ?
- 确实有点复杂哈,那就先只思考加法器吧~
- 仍然以计算
1+2+3+...+100
为例 - 对于本例,程序的编写方式是(将“部分”累加到“sum”上)
这就说明:有时候程序是需要对同一个数据进行连续的处理的
那么现在硬件视角的执行是下面这样的
- 从存储器读出 sum 和 1,传入 CPU,1 被加到 sum 上,将 sum 写回存储器
- 从存储器读出 sum 和 2,传入 CPU,2 被加到 sum 上,将 sum 写回存储器
- 从存储器读出 sum 和 3,传入 CPU,3 被加到 sum 上,将 sum 写回存储器
- …
啊西巴 !
- 上面这样我们每完成一次累加都得将 sum 写回存储器,然后立刻就又将 sum 读出来继续加,这样太傻了啊
为什么说上面这种方式很傻呢 ?你可以想像这样的场景:
- 考试的时候你做一道题就向你同桌借一次橡皮,上道题做完你立马就还回去,下道题还借…
- 懂了吧 ?!
另外,大容量的存储器的读写速度是相对较慢的,这是谁都无法违背的材料特性规律
于是先驱创造了小容量但高速的寄存器,CPU 正在处理中的数据可被暂放其中
至此,我们就有了(存储器、CPU、寄存器)
- riscv-volume-1、riscv-volume-2 ==> See 阿里云盘/Books
- https://github.com/riscv-non-isa/riscv-elf-psabi-doc
为了让强大的 CPU 成为我们忠实的奴仆,指令诞生了
我们可以用指令来控制 CPU,让 CPU 做我们想做的事
但(发一条指令,CPU 就动一动)的方式还是不尽人意,于是先驱就和 CPU 做了一个简单的约定
- 给你一段程序,你执行完一条指令之后,就继续执行下一条指令
- 可 CPU 怎么知道现在执行到哪一条指令呢 ?
- 为此,先驱为 CPU 创造了程序计数器(Program Counter,PC)
- 在 x86 中,它有一个特殊的名字,叫(Extended Instruction Pointer,EIP)
- 从此,计算机就只需做一件事
1
2
3
4
5while (1) {
从 PC 指示的存储器位置取出指令;
执行指令;
更新 PC;
}
至此,我们就设计出了一个足够简单的计算机
只需将一段指令序列放入存储器,然后让 PC 指向第一条指令,这段指令序列就会被计算机自动执行~
例如,下面的指令序列可以计算1+2+...+100
其中r1
和r2
是两个寄存器,还有一个隐含的程序计数器PC
,初值为0
为了帮助大家理解, 我们把指令的语义翻译成 C 代码放在右侧,其中每一行 C 代码前都添加了一个语句标号
1 | 0: mov r1, 0 | pc0: r1 = 0; |
计算机执行以上的指令序列,最后会在 PC = 5 的指令处陷入死循环,此时计算已经结束,1+2+...+100
的结果会被存放在寄存器r1
中
- 事实上,开拓者图灵早在 1936 年就已经提出了类似的核心思想,「计算机科学之父」果然名不虚传
- 而这个流传至今的核心思想,就是“存储程序” !
- 为了表达对图灵的敬仰,我们将上面这个最简单的计算机称为「图灵机,Turing Machine,TRM」
- 或许你已经听说过图灵机这个作为计算模型时的概念
- 但这里我们只强调一个最简单的真实计算机需要满足哪些条件:
- 结构上:TRM 有(存储器、PC、加法器、寄存器)
- 工作方式上:TRM 不断重复以下过程
- 从 PC 指示的存储器位置取出指令 => 执行指令 => 更新 PC
- 咦 ?(存储器、PC、加法器、寄存器)这些不都是数字逻辑电路课上学习过的部件吗 ?
- 也许你会觉得难以置信,但你正面对着的这台无所不能的计算机,就是由只懂 0 和 1 的数字逻辑电路组成的 !
blame my 数字逻辑电路 teacher, blame myself.
- 可我们写的是 C 代码啊,这个冷冰冰的电路是如何理解凝结了人类智慧结晶的 C 代码的呢 ?
- 先驱说:“计算机诞生的那些年还没有 C 语言,大家当时都是直接编写对人类来说晦涩难懂的机器指令,这也是最早的对电子计算机的编程方式了”
- 后来人们发明了(高级语言 & 编译器),我们能直接编写高级语言代码,经由编译器处理,生成功能等价的,且 CPU 能理解的指令
- CPU 执行这些指令,就相当于执行了我们写的代码
如今的计算机本质上仍然是”存储程序”这种工作方式
经过了无数计算机科学家们的努力,才使得我们今天可以轻松地使用计算机
(完)