# 5. 计算模型与机器语言

在前面章节中我们深入底层，详细讨论了计算机的计算单元与存储单元的构造方式，这一节我们将视野提升一个抽象层次，来看一下通过这些组件构建起来的最基础的计算机模型，并简单讨论一下为该模型设计指令集所需要考虑的因素。

到目前为止，我们讨论的内容局限于两个芯片：

* CPU: 计算芯片，前文提到的ALU、寄存器都是CPU的组成部分，除此之外CPU还至少需要一个控制组件（Control Unit），用来“指挥”CPU的工作
* 内存: 存储芯片，CPU 所执行的指令以及操作的数据都存储在内存中

CPU 与内存通过总线（Bus）进行通信，总线上包含三种信号：地址信号、数据信号、控制信号。如下图所示：

![](/files/-MdWT_NInQ1npcJjz_Yu)

虽然该图很简单，但已经呈现出了一个最基本的计算模型：在 CU(Control Unit) 的控制下，CPU 反复地执行存放在内存中的指令，指令的执行效果就是将内存或寄存器中的数据扔进 ALU 做运算，再将结果写回内存或寄存器。至于CPU来回倒腾这些数据到底是为了什么，这是宏观的层面上所具备的意义，可能是在完成一个交易、可能是在模拟一个电子游戏、也可能是在播放一部电影。但不管是什么事情，在微观层面的体现都是这样。

> 如果读者熟悉图灵机模型，会发现上文所说的计算模型就是图灵机的一种映射。事实上如果我们再加上输入与输出设备，就是一个冯诺伊曼架构的计算机模型。

CPU 执行指令通常划分成多个阶段：取指、解码、执行、存储，一个完整的循环被称为 CPU 的一个执行周期。整个流程由 CU 主导，CPU 的各个组件会在一起密切配合，例如寄存器 PC(Program Counter) 总是保存着下一条指令的内存地址，PC 的内容由当前执行的指令决定；如果需要 ALU 参与运算，CU 在解码后需要将各种输入信号传给 ALU。这些逻辑需要非常复杂的硬件电路来支撑，但这里我们不再深入讨论硬件实现，而是将其看着是一个功能完善的整体。

在该模型下，我们需要如下几类指令：

1. 算术、逻辑运算。该工作通过 ALU 来完成，输入、输出来自寄存器或者内存
2. 数据传输。将数据在寄存器与内存之间传输
3. 流程控制。如何获取并执行下一条指令，程序默认是顺序执行的，我们还要考虑如何完成条件判断以及完成程序跳转等

设计指令集时需要考虑如下因素：

1. 内存模型 \
   既然 CPU 的毕生精力都在倒腾内存中的数据，那么如何对内存进行寻址是指令集的重点。内存模型决定了寻址方式，以及能够寻址的内存空间大小。例如上文中提到的 Intel 8086 芯片，其为了在16位寄存器中支持20位的地址空间，采用的是分段寻址（Segmented Addressing）模式。
2. 指令格式
3. 寄存器种类 \
   哪些寄存器是专用寄存器，哪些是通用寄存器。例如 Intel 8086 芯片中，为了支持分段寻址，专门设计了段寄存器（Segment Registers）与索引寄存器（Index Registers）。

其中最重要的是内存模型，内存模型会显著影响上层程序的设计，例如操作系统的实现。事实上内存地址的用途是多样化的，不仅仅局限在对内存芯片的寻址上，如果我们重新审视 CPU 与内存的关系，会发现 CPU 根本不知道存储芯片的存在，CPU 面对的只是一个个具备存储能力的地址而已，如果使用高级程序设计的词汇来描述，内存地址就是一个接口，而内存芯片是其中的一种实现；其它的实现例如 [Memory-mapped IO](https://en.wikipedia.org/wiki/Memory-mapped_I/O) 将内存地址映射成 I/O 设备，而 [Memory-mapped File](https://en.wikipedia.org/wiki/Memory-mapped_file) 将一段内存地址空间映射成磁盘上的文件的某一段内容，这样 CPU 就能够像操作内存一样操作 I/O 设备以及文件了。

指令集是 CPU 全部功能的描述，是面向 CPU 进行编程的唯一媒介，所以也叫着机器语言，机器语言是抽象层次最低的编程语言，用二进制表示，其中每个0与1都可以想象成某个精灵在拨动逻辑门中的电路开关，以便让电子信号以预设的轨迹流过整个电路。机器语言是硬件到软件的过渡，从更深刻的意义上看，机器语言刻画的是一个计算模型，而如何合理、高效地使用该计算模型来解决现实之中的问题，我们还需要专门的系统来进行管理与协调，并提供更高层次的抽象模型，这个系统就是操作系统。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://s2.shizhz.me/s2e5.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
