4. 处理器基础:计算机的“大脑”

各位未来的计算机科学家,大家好!本章至关重要,因为我们将深入探索计算机的“大脑”:中央处理器 (CPU)。理解 CPU 的工作原理是计算机科学的基础。我们将探讨它的内部架构、如何执行指令,以及如何使用最底层的编程语言——汇编语言 (Assembly Language) 来与它沟通。

别担心“寄存器 (registers)”或“总线 (buses)”这些听起来像复杂机械结构的术语——我们会用简单、现实生活中的类比来拆解它们。学完本章后,你将彻底明白计算机是如何处理你发出的每一条指令的!

4.1 中央处理器 (CPU) 架构

冯·诺依曼架构与存储程序概念

几乎所有现代计算机都基于冯·诺依曼架构 (Von Neumann Architecture)。这一由约翰·冯·诺依曼提出的概念,定义了计算机系统的结构。

其核心理念是存储程序概念 (Stored Program Concept):

  • 程序指令和程序所使用的数据都存放在同一个存储单元(主存或 RAM)中。
  • 这使得 CPU 能够通过相同的路径(总线)从内存中获取指令和数据。

类比:想象一位厨师(CPU),他把菜谱(指令)和食材(数据)都放在同一个储藏室(内存)里。无论是拿下一步的菜谱还是拿下一个食材,他前往储藏室的路线都是一样的。

CPU 与系统的关键组件

CPU 及其周边环境由几个关键的交互组件组成:

  1. 算术逻辑单元 (ALU): 这是 CPU 的“计算器”。它执行所有的算术运算(如加、减、乘、除)和逻辑运算(如 AND、OR、NOT、比较)。
  2. 控制单元 (CU): 这是“经理”或“交通警察”。它协调 CPU 的所有活动,并指挥 CPU 与其他设备之间的数据流向。它负责解码指令并生成控制信号。
  3. 即时访问存储器 (IAS): 这是计算机主存 (RAM) 的另一个名称。它保存着处理器当前正在使用的指令和数据。
  4. 系统时钟 (System Clock): 生成定时信号(脉冲),同步 CPU 的所有操作。时钟速度决定了 CPU 每秒能执行多少个周期。

寄存器 (CPU 的草稿纸)

寄存器 (Registers) 是 CPU 内部极小且极快的存储位置,用来存放 CPU 当下立即需要处理的临时数据。

寄存器分为两类:

  1. 通用寄存器 (General Purpose Registers): 在算术或逻辑运算期间用于临时存储数据(在本课程大纲中,累加器通常是我们考虑的唯一通用寄存器)。
  2. 专用寄存器 (Special Purpose Registers): 每个在“取指-执行”周期 (Fetch-Execute cycle) 中都有明确且固定的角色。

以下是你必须掌握的关键专用寄存器:

  • 程序计数器 (PC): 保存下一条要获取指令的内存地址。(它就像是指向下一步操作的指针。)
  • 内存地址寄存器 (MAR): 保存当前正在被读取或被写入的内存地址。
  • 内存数据寄存器 (MDR): 保存刚从内存获取,或即将写入内存的数据或指令。
  • 累加器 (ACC): 保存 ALU 运算后的中间结果。
  • 当前指令寄存器 (CIR): 保存当前正在被解码和执行的指令。
  • 变址寄存器 (IX): 用于变址寻址以修改地址,通常在处理列表或数组时使用。
  • 状态寄存器 (Status Register): 包含位(标志位),指示 CPU 的当前状态,例如是否发生了溢出,或上一次计算结果是否为零。

记忆小窍门: MAR 是为了 Address(地址),MDR 是为了 Data(数据)。它们协同工作以访问内存。

快速回顾:寄存器的角色

如果你需要知道在内存中“去哪里”,请使用 MAR。如果你需要持有刚刚拿到的“东西”,请使用 MDR 或 ACC。

系统总线 (数据高速公路)

总线是一组连接计算机系统组件、允许数据传输的平行线路。主要有三种类型:

  1. 地址总线 (Address Bus): 携带正在访问的内存位置或外设的地址。
    • 方向: 单向(CPU 输出地址)。
    • 影响: 其宽度(线路数量)决定了系统能够寻址的最大内存容量。
  2. 数据总线 (Data Bus): 在组件之间传输数据或指令。
    • 方向: 双向(数据双向流动)。
    • 影响: 其宽度决定了同时可以传输多少位。(总线越宽,数据传输越快)。
  3. 控制总线 (Control Bus): 携带管理数据流向与时序的控制信号(如读取、写入、时钟同步)。
    • 方向: 单向与双向(信号在两个方向上传输)。

类比:想象一个铁路系统。地址总线是铁轨(单向,决定地点)。数据总线是火车车厢(运送货物)。控制总线是调度中心,负责指挥哪列火车去往何处。

取指-执行周期 (Fetch-Execute Cycle)

这是 CPU 执行程序指令的不间断过程。它包含三个主要阶段:取指 (Fetch)、解码 (Decode) 和执行 (Execute)。

周期步骤(使用寄存器传输符号 - RTN)

1. 取指阶段: 从内存获取下一条指令。

  • MAR ← [PC]:下一条指令的地址从程序计数器 (PC) 复制到内存地址寄存器 (MAR)。
  • PC ← [PC] + 1:PC 加 1,指向下一条指令(为下一个周期做准备)。
  • MDR ← [MAR]:存储在 MAR 所指地址的指令从内存中获取,并加载到内存数据寄存器 (MDR)。
  • CIR ← [MDR]:指令从 MDR 复制到当前指令寄存器 (CIR)。

2. 解码阶段: 控制单元 (CU) 解读 CIR 中的指令。

  • CU 判断该指令的意义(例如:ADD、JUMP、LOAD)。
  • 它为执行准备所需的任何数据,可能还会从内存中获取操作数。

3. 执行阶段: 执行该指令。

  • 如果是算术或逻辑指令,ALU 执行运算(例如将数值加到 ACC 中)。
  • 如果是跳转 (jump/branch) 指令,PC 可能会更新为新的地址。
  • 控制信号会发送给其他组件。

关键总结: 取指-执行周期是一个无止境的循环。它每秒运行数百万次,负责移动地址、获取指令并执行计算。

影响 CPU 性能的因素

计算机系统的速度和效率受多种硬件因素影响:

  • 处理器类型与内核数量: 更多的内核允许 CPU 同时运行多个 F-E 周期(并行处理)。
  • 时钟速度: 以吉赫兹 (GHz) 为单位。较高的时钟速度意味着每秒能执行更多的取指-执行周期。
  • 总线宽度: 较宽的数据总线允许同时传输更多位(例如,64 位总线比 32 位传输数据更快)。
  • 高速缓存 (Cache): 位于 CPU 芯片上或附近、极快速的小型存储器 (SRAM)。它存储了频繁使用的指令和数据,与访问主 RAM 相比,大幅加速了访问过程。缓存越大,性能通常越好。

外设连接 (接口)

不同的接口用于将外设连接到计算机:

  • 通用串行总线 (USB): 用于连接各种外设(键盘、鼠标、U 盘)的通用标准。它使用串行数据传输。
  • 高清多媒体接口 (HDMI): 主要用于传输高质量数字音视频信号(例如将计算机连接到显示器或电视)。
  • 视频图形阵列 (VGA): 一种较旧的标准,用于连接模拟显示器。它只传输视频信号,不传输音频。

中断 (处理紧急事件)

中断 (Interrupt) 是由设备或软件发送给 CPU 的信号,促使它暂停当前的任务以处理紧急事件。

  • 目的: 确保关键任务(如按键动作或磁盘读取完成)能被快速处理,防止 CPU 浪费时间不断检查(轮询)设备。
  • 可能原因: 硬件故障(如断电)、I/O 完成(打印机完成工作)、定时器超时,或非法指令(除以零)。
  • 检测: CPU 在每个取指-执行周期的末尾检查中断。
  • 处理过程:
    1. CPU 检测到中断信号。
    2. 所有寄存器的内容(特别是 PC)被保存到一个特殊位置(堆栈/Stack),以便 CPU 稍后能返回之前的任务。
    3. PC 被加载对应的中断服务程序 (ISR) 的起始地址。
    4. 执行 ISR(处理紧急请求的程序)。
    5. ISR 完成后,从堆栈中恢复原始的寄存器内容,CPU 从中断处恢复之前的任务。
关键总结:4.1 概要

冯·诺依曼架构定义了存储程序概念。CPU 使用专用寄存器(PC、MAR、MDR、CIR、ACC)运行 F-E 周期。总线传输数据与地址,而中断允许 CPU 高效管理紧急的外部请求。

4.2 汇编语言

汇编语言与机器码的关系

机器码 (Machine Code) 是编程的最底层——它是 CPU 直接执行的原始二进制指令(0 与 1)。对人类而言,阅读或编写起来既繁琐又几乎不可能。

汇编语言 (Assembly Language) 是一种低级语言,使用助记符(如 ADD、JMP、LDM 等简短易记的缩写)来代表机器码指令。

  • 关键关系: 汇编语言与机器码之间存在一一对应的关系。一条汇编语言指令直接翻译成一条机器码指令。
  • 汇编器 (Assembler): 一种称为汇编器的软件,负责将汇编语言程序翻译成可执行的机器码。

指令格式:操作码与操作数

每个低级指令(在汇编语言和机器码中)都分为两个主要部分:

  • 操作码 (Opcode / Operation Code): 指定 CPU 需要执行的操作或任务(例如 ADD、LDM 或 JMP)。在机器码中,操作码还标识所使用的寻址模式。
  • 操作数 (Operand): 保存数据本身、寄存器引用,或是要对其执行操作的数据之内存地址。

两遍汇编器 (Two-Pass Assembler)

由于汇编语言程序经常使用标号 (labels)(地址的符号名称,如 LOOP 或 START),汇编器需要两遍扫描才能完整翻译代码。

第一遍:建立符号表 (Symbol Table)

  1. 汇编器逐行读取源代码。
  2. 它识别程序中使用的所有标号。
  3. 它计算每个标号定义的内存地址。
  4. 它建立一个符号表,映射每个标号及其对应的地址。
  5. 关键在于,此阶段尚未生成机器码。

第二遍:翻译

  1. 汇编器第二次读取源代码。
  2. 它将每条助记指令翻译成对应的二进制机器码。
  3. 当遇到作为操作数的标号(例如 JMP START)时,它会从符号表(第一遍建立的)中查出该标号的实际内存地址,并将该地址插入机器码指令中。
  4. 生成最终的可执行机器码程序。

为什么需要两遍?如果程序前半部分的指令(第一遍)引用了程序后半部分定义的标号(第二遍),汇编器必须依靠符号表来获取该地址。

指令分组

汇编语言指令通常按其功能分组:

  • 数据传输: 在寄存器和内存之间移动数据(如 LDM、STO、MOV)。
  • 输入与输出 (I/O): 处理 CPU 与外设之间的数据传输(如 IN、OUT)。
  • 算术运算: 数学计算(如 ADD、SUB、INC、DEC)。
  • 无条件跳转: 总是改变执行流程的指令(如 JMP – Jump)。
  • 条件跳转: 仅在状态寄存器满足特定条件时才改变流程,通常跟在比较 (COMPARE) 指令之后(如 JPE - Jump if True, JPN - Jump if False)。
  • 比较指令: 用于根据比较结果设置状态寄存器中的标志位(如 CMP – 比较 ACC 的内容)。

寻址模式 (Modes of Addressing)

寻址模式定义了指令中的操作数部分如何引用所需的数据。这对于编写高效的汇编语言程序至关重要。

  1. 立即寻址 (Immediate Addressing, Opcode #n):
    • 操作数本身即为要使用的实际数据。
    • 示例:LDM #10(将数字 10 加载到累加器)。
    • 优点:最快的模式,因为获取数据不需要访问内存。
  2. 直接寻址 (Direct Addressing, Opcode <address>):
    • 操作数是数据所存放的内存地址。
    • 示例:LDD 500(将内存位置 500 的内容加载到 ACC)。
    • 优点:访问固定内存位置的简单方法。
  3. 间接寻址 (Indirect Addressing, Opcode I <address>):
    • 操作数是一个地址,该地址存放着另一个地址。CPU 先从第一个位置取得地址,再用该第二个地址去抓取实际数据。
    • 示例:LDI 500(到位置 500。读取那里找到的地址,假设是 800。然后将位置 800 的内容加载到 ACC)。
    • 优点:对于指针或需要动态改变数据指向时非常有用。
  4. 变址寻址 (Indexed Addressing, Opcode X <address>):
    • 有效地址是通过将操作数中的地址加上变址寄存器 (IX) 的内容计算得出。
    • 示例:LDX 500(有效地址 = 500 + [IX])。
    • 优点:只需增加变址寄存器,即可依序访问数组或列表中的元素,极为重要。
  5. 相对寻址 (Relative Addressing):
    • 主要用于跳转指令。跳转到的地址相对于程序计数器 (PC) 的当前值。
    • 优点:允许跳转指令具有可重定位性(如果程序在内存中移动,跳转仍相对于指令正确运作)。
关键总结:4.2 概要

汇编语言使用助记符来代表机器码。指令由操作码和操作数组成。两遍汇编器通过先建立符号表然后进行翻译来处理标号。寻址模式定义了指令如何找到数据,从立即寻址(数据在指令中)到变址寻址(数据地址经由计算得出)。

4.3 位操作 (Bit Manipulation)

位操作是指使用逻辑运算或移位来改变寄存器或内存中单个位。这是低级编程中设置标志位、缩放数值和控制设备的基础。

二进制移位 (Binary Shifts)

二进制移位会将寄存器(如 ACC)中的所有位向左或向右移动指定数量 (n) 的位置。

1. 逻辑移位 (LSL 与 LSR)
  • 逻辑左移 (LSL #n): 位向左移动 'n' 位。右端补 0。
    • 效果: 将数值乘以 \(2^n\)。
  • 逻辑右移 (LSR #n): 位向右移动 'n' 位。左端补 0。
    • 效果: 将数值除以 \(2^n\)。
2. 算术移位 (Arithmetic Shifts)

这些移位专为带符号(补码)的数字设计。

  • 算术左移: 与逻辑左移相同。
  • 算术右移: 位向右移动,但保留/复制最左边的位(符号位/Sign Bit)以维持数字原本的正负号。如果数字为负(符号位为 1),则左边不会补 0。

常见错误:逻辑移位“只”应应用于无符号数,因为它们不会保留符号位。

3. 循环移位 (Cyclic/Rotational Shifts)

从寄存器一端移出的位会重新插入到另一端。不会丢失任何位,也不会补 0。

示例:如果 10110010 循环左移 1 位,会变成 01100101。

用于监控与控制的位操作 (位掩码)

位操作,通常称为位掩码 (Bit Masking),用于直接与硬件控制寄存器交互。通过将“掩码”(特定的二进制模式)与逻辑运算符 (AND, OR, XOR) 结合,我们可以隔离、设置或清除特定的位。

1. 设置位 (使用 OR)

要确保特定位为 1 (SET),我们使用位 OR 运算,配合仅在目标位置为 1 的掩码。

OR 规则:X OR 1 = 1 且 X OR 0 = X

示例:要将 ACC (01010000) 的第 3 个位(由右算起,位位置 2)设为 1:

ACC: 0101 0000
MASK: 0000 0100
OR 结果: 0101 0100 (第 3 个位现在确保为 1。)

2. 清除位 (使用 AND)

要确保特定位为 0 (CLEAR),我们使用位 AND 运算,配合仅在目标位置为 0(其他皆为 1)的掩码。

AND 规则:X AND 0 = 0 且 X AND 1 = X

示例:要清除 ACC (11011100) 的第 8 个位(由右算起,位位置 7):

ACC: 1101 1100
MASK: 0111 1111 (我们使用欲清除位的反向掩码)
AND 结果: 0101 1100 (第 8 个位现在确保为 0。)

3. 测试/检查位 (使用 AND)

要查看某个位当前是否已设置 (1),我们使用位 AND 运算,配合仅在测试位置为 1 的掩码。

如果结果为 0,则该位为 0。如果结果不为 0,则该位为 1。

示例:测试 ACC (10100000) 的第 5 个位(位置 4):

ACC: 1010 0000
MASK: 0001 0000
AND 结果: 0000 0000 (第 5 个位为 0。)

关键总结:4.3 概要

二进制移位可用于快速乘除。位掩码利用 AND 来清除位,用 OR 来设置位,并常用 AND 来测试硬件寄存器中特定位的状态。

恭喜!你现在已经掌握了处理器运作的核心原则。这些知识是你理解所有软件如何与硬件交互的基石。请持续练习 F-E 周期步骤和寻址模式——它们是考试中的核心考题!