功能和结构
本节要和指令系统放在一起理解,主要有两点:一是理解 CPU 的 架构方式,二是理解 CPU 中 各种寄存器的功能细节。
CPU
作为计算机的“大脑”,CPU(中央处理器)是执行程序指令、处理数据的关键部件。从宏观的计算机体系结构来看,CPU 是冯·诺依曼架构中“运算器”与“控制器”两大核心部件的具体实现与集成。因此,剖析 CPU 的内部组成,本质上就是探究现代计算机如何通过精密的硬件设计,将“运算”与“控制”这两大基本功能高效、协调地融为一体,并最终执行复杂的任务。
组成结构
在介绍 CPU 的组成结构之前,首先回顾一下计算机的 冯诺依曼结构,其中 运算器、控制器、存储器、输入、输出 为计算机组成的五大部件,其中 CPU 涵盖的功能就包含 运算器 和 控制器 这两个。
CPU 的核心功能包含 运算和控制 这两大模块,这对应了计算机五大部件中的 运算器 和 控制器。具体而言:运算功能(执行功能)是指 CPU 根据指令对数据进行算术或逻辑运算;控制功能则是指 CPU 通过指令协调计算机中各个部件的工作。
CPU 组成结构简图
CPU 的结构简图如上图所示,CPU 由 运算部件 和 控制部件 组成。但是其实这两者并不能完全涵盖 CPU 的所有结构,因为这种分类方式忽略了 CPU 了内总线,所以一种更完善的 CPU 组件分类方法是将其分为 数据通路 和 控制器 这两部分:
- 数据通路(Datapath)是指令执行过程中,数据所经过的路径,包括路径中的部件。它是指令的 执行部件。
- 控制器(Control Unit)对指令进行解码,生成对应的控制信号,控制 数据通路 的动作。能够执行指令发出控制信号,是指令的 控制部件。
数据通路
CPU 的 数据通路 是指 CPU 在执行指令的过程中内部数据流动的路径,ALU、寄存器组、多路选择器 都属于数据通路的一部分。数据通路 描述了 信息从哪里开始,中间经过哪些部件,最后被传送到哪里。数据通路由 控制部件 控制,控制部件根据每条指令功能的不同,生成对数据通路的控制信号。
数据通路的元件主要分为 组合逻辑元件 和 时序逻辑元件 两类:
组合逻辑元件
组合逻辑元件(操作元件)指那些仅由 组合逻辑电路 组成的元件,其输出仅取决于当前的输入,而不受存储器或时钟信号的影响。输入和输出之间无反馈通路,信号是单向传输的。
数据通路中常用的组合逻辑元件有 算术逻辑单元(ALU)、多路选择器、三态门等;译码器在硬件上同样是组合逻辑,若它负责指令译码,通常归入控制器。如下图所示:
- 译码器:用于操作码或地址码译码, 位输入对应 种不同组合,因此最多有 路互斥输出,每次只有一路被使能。
- 多路选择器:有多个输入,输出与其中一个输入相同,需要用控制信号 Select 选择哪个输入作为输出。
- 三态门:可以被视为一种控制开关,由控制信号 EN 决定信号线的通断,当 EN=1 时,三态门被打开,输入信号等于输出信号;当 EN = 0 时,输出端呈现高阻态,数据通路被断开。
时序逻辑元件
对于 时序逻辑元件(状态元件),其任何时刻的输出不仅与该时刻的输入有关,还与该时刻以前的输入有关,并且 具备状态存储 功能。此外,时序电路必须在 时钟节拍 下工作。
各类 寄存器 和 存储器,如 通用寄存器组、程序计数器、状态/移位/暂存/锁存寄存器等,都属于时序逻辑元件。
控制器
控制器是计算机的指挥中心,它负责协调和控制计算机的所有操作。其核心功能是根据当前正在执行的指令,生成一系列控制信号,精确地指挥数据通路中的各个部件(如 ALU、寄存器、多路选择器)协同工作,从而完成指令所规定的任务。
控制器可以被视为整个 CPU 的“大脑”或“指挥家”。它不直接处理数据,而是决定数据在何时、何地、以何种方式流动和运算。
控制器的 基本工作原理 如下:
- 取指令:控制器指挥程序计数器(PC)送出当前指令地址,从存储器中取出指令,并送入指令寄存器(IR)。
- 分析指令:对指令寄存器中的指令进行译码,识别出指令的操作类型(如加法、跳转)、寻址方式以及所需的操作数。
- 执行指令:根据指令译码的结果,控制器在正确的时序下,生成并发出对应的控制信号序列。这些信号控制数据通路打开或关闭特定的数据路径,选择 ALU 的运算功能,决定是否写入寄存器或内存等。
- 转向下条指令:在完成当前指令后,控制器会更新程序计数器,为取下一条指令做好准备,从而开始新一轮的循环。
控制器的功能和组成详见 控制器。
8086 CPU
上文已经对 CPU 中的组件进行了分类,但是仅有抽象概念是不足够的,该节会提供一个非常简单的 CPU 实现来说明情况,这个 CPU 就是 8086。
8086 是 Intel 早期的 16 位处理器,也是 x86 体系结构的重要起点。本节借它说明寄存器、分段地址与外部引脚等具体实现;做题时若题设使用抽象 CPU,仍应以题设的数据通路和位宽为准。
结构
上文已经提到了 CPU 的组成结构 可以分为 数据通路 和 控制器 这两部分,8086 中的 数据通路 由指令队列、寄存器 和内总线组成。控制器中包含指令译码器、时序控制单元、标志控制逻辑和微指令控制逻辑。
下文会按照这个脉络对 8086 中的组件进行详细说明。
寄存器
从功能的角度进行区分,8086 CPU 的寄存器可以分为 通用寄存器、段寄存器、变址寄存器、指针寄存器、标志寄存器 和内部使用的 特殊寄存器 六类:
- 通用寄存器:用于存储任意的地址或者数据。
AX寄存器:累加器(Accumulator),用于执行算术和逻辑运算。BX寄存器:基址寄存器(Base Register),通常用于存储内存地址。CX寄存器:计数寄存器(Counter Register),用于循环计数和移位操作。DX寄存器:数据寄存器(Data Register),用于输入/输出操作和大整数运算。
- 段寄存器:保存段值;该值左移 4 位后形成段基址。
CS (Code Segment)寄存器:代码段寄存器,存储指向代码段的地址。DS (Data Segment)寄存器:数据段寄存器,存储指向数据段的地址。ES (Extra Segment)寄存器:附加数据段寄存器,通常用于数据访问。SS (Stack Segment)寄存器:堆栈段寄存器,存储指向堆栈段的地址。
- 变址寄存器:用于支持变址寻址模式,和数组和指针操作相关。
SI寄存器:源变址寄存器,通常用于数据传送操作。DI寄存器:目的变址寄存器,也通常用于数据传送操作。
- 指针寄存器:
SP (Stack Pointer)寄存器:堆栈指针寄存器,指向函数栈的顶部。BP (Base Pointer)寄存器:堆栈基址寄存器,指向函数栈的底部。IP (Instruction Pointer)寄存器:指令指针寄存器,存储当前执行指令的偏移地址。
- 标志寄存器:
FLAGS寄存器:标志寄存器,存储有关条件和状态的信息,例如进位、零标志、溢出等。
- 特殊寄存器:
IR (Instruction Register)寄存器:暂存读取的指令。T暂存器:暂存 ALU 一端的输入。
哪些寄存器是汇编程序员可见的?
有在 8086 仿真器上编写过汇编程序的人会知道,可见的寄存器就是你编写汇编程序时可以直接通过指令进行控制的寄存器。
可见的寄存器包括:通用寄存器、段寄存器、标志寄存器(FLAGS)和作为控制流状态的指令指针寄存器(IP)。其中 IP 不能像 AX 一样作为普通 MOV 指令的通用操作数读写,而是由顺序取指、跳转、调用、返回和中断等控制转移隐含改变。
相对地,MAR、MDR、IR 和临时寄存器 T 属于 CPU 内部实现状态,汇编程序不能把它们当作指令操作数直接访问。
段寄存器
段寄存器保存程序内存结构中不同段的段值;在 8086 实模式下,段值左移 4 位形成段基址,再与相应偏移量组合得到物理地址:
- CS 指向代码段(.text)的起始位置
- SS 指向栈段(Stack Stack)的起始位置
- DS 指向数据段(.data)的起始位置
- ES 指向附加段(Extra Segment)的起始位置
对于运行在 8086 上的程序而言,其内存结构相比 现代进程内存空间 更加简单,但其中的逻辑结构是类似的:
从逻辑上来说,程序的执行需要四个段:
- 代码段:存储编译后程序指令的地方
- 数据段:存储有全局数据的地方
- 栈段:函数嵌套调用的发生场所
- 额外段:提供一些灵活性,供程序员发挥
不同的段寄存器与不同的段相关联,指向相关段的起始地址。
指针寄存器
对于有些段来说,仅仅知道其起始地址是不足够的,在程序执行过程中,需要一些额外的寄存器来实现我们需要的操作,指针寄存器主要操作 栈段 和 代码段。
栈指针寄存器
栈指针寄存器 包含 BP、SP 这两个,在进一步了解这两个寄存器之前,请复习一下 函数调用时的内存结构。
函数在执行过程中需要保存的数据与栈类似,具有先进后出的特点。
函数栈从高地址向低地址增长,嵌套调用的函数所对应的函数栈 在栈段上不断堆叠。如果我们在 main() 主函数中嵌套调用 f(g(h(1))),那么该程序对应的栈段对应的逻辑结构如下所示:
在常见栈帧约定中,BP 作为当前函数栈帧的稳定基准,SP 指向当前栈顶;8086 的栈通常从高地址向低地址增长。是否使用 BP 以及具体栈帧布局由调用约定决定,不能把“函数栈的底部”理解为固定硬件边界。
指令指针寄存器
在 8086 中,真正的指令指针寄存器是 IP(Instruction Pointer),它保存当前代码段内下一条待执行指令的 偏移地址。
由于 8086 采用 段式内存管理,仅有 IP 还无法唯一确定一条指令的位置,还需要结合 代码段寄存器 CS 一起使用。因此,CPU 实际取指的位置由 CS:IP 共同确定:
从计算机组成原理的角度来看,教材中常说的 程序计数器(PC,Program Counter) 表示“下一条待执行指令的地址”。在 8086 中,这个概念对应的并不是单独的某个寄存器,而是由 CS:IP 共同实现。因此可以将:
理解为“8086 中程序计数器所表示的位置由 CS 和 IP 两个寄存器共同确定”。
在取指阶段,控制单元根据 CS:IP 定位并读取指令。取指完成后,CPU 会根据当前指令的长度自动更新 IP:
从而使 CS:IP 指向下一条待执行的指令。当发生 跳转、调用、中断 等控制流转移时,CPU 则会直接修改 CS、IP 或两者的值,使程序从新的位置继续执行。
变址寄存器
变址寄存器 主要用于实现变址寻址模式,方便对数组、字符串等数据结构中的 第 i 个元素 进行操作。8086 中的主要变址寄存器是 SI(源变址寄存器)和 DI(目的变址寄存器),下文分别从 数组 和 字符串操作 两个例子说明一下:
数组操作
以下汇编代码段通过一个循环操作实现了对于数组中的前五个元素进行操作。注意在 8086 中,我们是在 CX 中保存 loop 的轮数,每次 LOOP 被调用后 CX 的值自动被减一。
; 假设 DS 指向数据段并且数组从数据段开始
MOV DS, addr ; 将数组的起始地址保存到 DS 中
MOV CX, 5 ; CX 用作循环计数器,假设数组有 5 个元素
MOV SI, 0 ; SI 作为索引寄存器,初始化为 0
NEXT_ELEMENT:
MOV AX, [SI] ; 从数组当前元素读取到 AX
; 对 AX 中的数据进行处理
ADD SI, 2 ; 移动到下一个元素(假设每个元素 2 字节)
LOOP NEXT_ELEMENT ; 循环直到 CX 为 0
字符串操作
以下汇编代码将一个字符串的前 length 个字符复制到另一个字符串中。
; 假设 DS 和 ES 已经分别指向源和目的数据段
MOV SI, OFFSET source ; SI 指向源字符串的起始位置
MOV DI, OFFSET dest ; DI 指向目的字符串的起始位置
CLD ; 清除方向标志位,确保字符串操作从低地址到高地址
MOV CX, length ; CX 初始化为字符串的长度
REP MOVSB ; 复制 CX 个字节从 DS:SI 到 ES:DI
标志寄存器
标志寄存器(Flags)用于存储处理器在 执行指令过程中产生的各种状态和条件,这些状态可以进一步被 控制器 所用,控制后续指令执行的行为。
标志寄存器中的不同位用于标记某个特殊的状态,8086 中的 标志寄存器 是一个 16 位 的寄存器,其中 9 个标志位 被使用,其他 7 个标志位 没有含义。
这些标志位在逻辑上可以被分为 条件标志(conditional flags)和 控制标志(control flags)两种:
条件标志
条件标志用于标记指令执行后的结果状态,用于影响程序的控制流,条件标志 包含以下几种:
- OF (Overflow flag):溢出标志。
- 当 有符号整数 运算的结果太大而无法适应目标寄存器时,OF 标志会设置为 1,表示发生了溢出。
- CF (Carry flag):进位标志。
- 当 无符号整数 运算的结果超出了目标寄存器的位数,CF 标志被设置为 1,表示发生了进位。
- 加法时:CF=1 表示发生了 进位(即结果超过了寄存器能表示的范围)。
- 减法时:CF=1 表示发生了 借位(即被减数小于减数)。
- 当 无符号整数 运算的结果超出了目标寄存器的位数,CF 标志被设置为 1,表示发生了进位。
- SF (Sign flag):符号标志。
- 根据 有符号整数 的计算结果来设置,如果结果为负数,则 SF 被设置为 1,否则为 0。
- ZF (Zero flag):零标志。
- 当操作结果为零时,ZF 标志被设置为 1,否则为 0。
- AF (Auxiliary carry flag):辅助进位标志。
- 通常用于 BCD(二进制编码十进制)算术运算,指示低四位的进位。
- PF (Parity flag):奇偶校验标志。
- 8086 根据结果低 8 位中二进制位 1 的个数设置 PF。若 1 的个数为偶数则 PF=1,为奇数则 PF=0。
需要注意的是,从 CPU 硬件的角度来看,并不存在“有符号整数”和“无符号整数”的区别。CPU 执行加减法时,只是对寄存器中的二进制位进行运算,并根据运算过程中产生的进位、借位以及结果的最高位等信息来设置各个标志位。
例如,对于加法指令,CPU 会同时更新 CF(进位标志)和 OF(溢出标志)。至于这些标志应当被解释为“无符号数发生溢出”还是“有符号数发生溢出”,则取决于程序员或编译器如何解释参与运算的那组二进制位。
换句话说,CF 和 OF 本质上反映的是同一次二进制运算的不同特征:
- CF 描述最高位之外是否产生了进位(或借位),因此通常用于判断无符号数运算是否越界;
- OF 描述结果的符号位是否出现异常变化,因此通常用于判断有符号数运算是否越界。
CPU 只是机械地设置这些标志位,而“有符号溢出”或“无符号溢出”的语义解释,则由后续指令和程序逻辑决定。
例如 8 位加法:
01111111 (+127)
+00000001 (+1)
-----------
10000000
CPU 会得到:
- CF = 0(没有向第 9 位产生进位)
- OF = 1(正数 + 正数得到负数)
如果把这些比特解释为:
- 有符号数:127 + 1 → 溢出
- 无符号数:127 + 1 = 128 → 完全合法
CPU 并不知道你想表达哪一种含义,它只是把 CF=0、OF=1 记录下来,供程序自行解释。这正是 FLAGS 寄存器设计的核心思想。
条件标志通常不需要程序员手动设置。当算术和逻辑指令(如 ADD、AND)以及 比较指令(CMP)被执行时,相关标志位会按该指令的定义被硬件 自动设置;不同指令影响哪些标志位,需要按 ISA 规定判断。
条件标志通常用于控制 条件跳转指令 的执行。条件跳转指令会检查条件寄存器中的标志位,根据标志位的状态决定是否将 程序计数器(PC)修改为目标地址,从而实现程序流程的跳转。
以下我们需要说明几个需要注意的点,这些知识点很容易被混淆:
CF 和 OF 的区别
| 标志位 | 含义 | 通常用于解释 | 置 1 条件 |
|---|---|---|---|
| CF | Carry Flag(进位标志) | 无符号数运算 | 加法产生最高位进位;减法发生借位 |
| OF | Overflow Flag(溢出标志) | 有符号数运算 | 加减法结果超出补码可表示范围,如 8 位的 |
上述的 设置条件 只是 逻辑结果(针对 有/无符号数 的逻辑结果),硬件并不是这样判断的。
对于硬件加法器,它不区分数字是 有符号 还是 无符号,底层电路都是通过 加法器 + 补码机制 完成的。
不过我们通过对一些位进行组合来 实现 上述的逻辑结果。
OF 标志位是如何被设置的?
在处理两个 n 位的有符号整数加法时,OF(Overflow Flag)用于指示结果是否超出了有符号数的可表示范围。对于补码表示的系统,可以使用以下逻辑来判断溢出:
设参与计算的两个 位补码数为 和 ,结果为 ,关注它们的符号位(即最高位,第 位):
| 情况 | 的符号 | 的符号 | 的符号 | 是否溢出 |
|---|---|---|---|---|
| 异号相加 | 0 | 1 | 不影响判断 | 不会溢出 |
| 异号相加 | 1 | 0 | 不影响判断 | 不会溢出 |
| 正数 + 正数 → 正数 | 0 | 0 | 0 | 无溢出 |
| 正数 + 正数 → 负数 | 0 | 0 | 1 | 有溢出 |
| 负数 + 负数 → 负数 | 1 | 1 | 1 | 无溢出 |
| 负数 + 负数 → 正数 | 1 | 1 | 0 | 有溢出 |
因此,OF 的判断规则为:
当两个操作数符号相同,而结果符号与它们不同,就发生了溢出。
用逻辑表达式表示为:
- 其中 分别表示 的最高位(符号位)
- 也可理解为:
- 两数为负,结果为正:溢出
- 两数为正,结果为负:溢出
减法的溢出判断
由于减法 可以转化为加法 ,因此溢出的判断可以同样基于 加法规则 来分析:
- 将减法转化为加法后,使用上述符号位比较法判断 OF。
CF 标志位是如何被设置的?
对于 位加法器,CPU 会保留运算结果的低 位,而最高位产生的进位会被丢弃。
若最高位向更高位产生进位(即加法器的最终进位输出为 1),则 CF = 1,否则 CF = 0。若以 表示最高位的最终进位,则加法时:
对于减法运算,CPU 可通过 实现 。以 x86 的标志语义为例,若发生借位则 CF 被置为 1;此时加法器的最终进位与借位互补:
从硬件角度看,CPU 并不知道操作数是有符号数还是无符号数,它只是记录最高位是否产生了最终进位。而程序通常将 CF 解释为无符号数运算是否发生越界。
所以:
- 加法的 等于最终进位 ;减法是否对最终进位取反,要按具体 ISA 的借位语义判断
- 等于进入符号位的进位与离开符号位的进位之异或。若前者为 ,后者为 ,则:
这其实就是 x86 FLAGS 中最底层、最硬件化的定义。
控制标志
控制标志 并不会被通常的运算指令自动修改,而是通过专门的指令来进行设置或清除。对于以下字段,了解即可:
- IF (Interrupt flag)
- 控制中断处理
- 当 IF 被设置为 1 时,CPU 允许响应可屏蔽外部中断。如果 IF 为 0,CPU 暂不响应 可屏蔽中断;NMI 和由指令触发的软件异常不受 IF 屏蔽。
- TF (Trap flag)
- 控制单步执行。
- 当 TF 被设置为 1 时,CPU 将进入单步执行模式。在单步执行模式下,每执行一条指令后,CPU 将引发一个单步中断,允许程序员逐条调试程序。
- DF (Direction flag)
- 字符串操作的标志位。
- 当 DF=0 时,字符串操作(如
MOVS、LODS、STOS)执行后递增 SI、DI,即从低地址向高地址移动;当 DF=1 时则递减 SI、DI,即从高地址向低地址移动。
特殊寄存器
暂存器
每次 ALU 操作都需要两个操作数,但是 数据总线 是 共享的,同一时刻只能传输一个操作数。所以在 ALU 会按照以下方式进行计算:
- 先读取第一个操作数,暂存在临时寄存器 T 中;
- 然后再读取第二个操作数;
- 最后,ALU 从 T 和第二个操作数一起执行运算。
所以在 只有一个内部数据总线 的设计里,为了配合 ALU 的两个输入,暂存器被设置用于存储前一个时钟周期的数据。
指令寄存器
当 CPU 从内存或指令队列中取出一条指令时,这条指令会被送入 IR(指令寄存器),暂存在这里,供后续的译码和执行阶段使用。
控制单元(CU)可以对 IR 中的指令进行译码,生成一系列控制信号。
引脚
CPU 的 引脚(Pin)是处理器与主板之间进行电气连接的接口,是 CPU 与外部组件(如内存、I/O 设备、电源等)之间通信的桥梁。引脚 的功能包括 数据传输、地址定位、中断控制、时序控制 等,是实现 CPU 与外部世界交互的关键通道。
为便于理解,本节以 Intel 8086 处理器为例进行说明。这些具体引脚用于帮助理解地址、数据、控制和中断信号如何在 CPU 与外部系统之间配合;遇到题目时以题设信号定义为准。
以 8086 为例,8086 为 16 位计算机,其 数据总线 为 16 位,可寻址地址空间为 1 MB,所以其 地址总线 为 20 位。数据总线和地址总线 复用,地址总线的高位与状态线复用:
| 引脚名 | 方向 | 说明 |
|---|---|---|
AD0–AD15 |
双向 | 地址/数据复用线:地址阶段传送 ,数据阶段传送 |
A16/S3–A19/S6 |
输出 | 高位地址线与状态线复用 |
在 数据传输 过程中,低位地址与数据使用同一组引脚(AD0–AD15),通过时序的不同进行区分。为了确保地址被正确识别,8086 使用 ALE(地址锁存使能)信号配合外部锁存器将地址锁存下来。
为了支持外设对 CPU 发起中断请求,以及对处理器进行复位操作,8086 设置了如下相关引脚:
| 引脚名 | 方向 | 说明 |
|---|---|---|
| NMI | 输入 | 不可屏蔽中断请求;不受 IF 控制,在处理器规定的指令边界响应 |
| INTR | 输入 | 可屏蔽中断请求;是否响应受 IF 等条件控制 |
| RESET | 输入 | 复位输入;8086 中为高电平有效,满足规定时序后初始化 CPU 状态 |
| INTA# | 输出 | 低电平有效的中断响应信号,通知外设 CPU 正在响应 INTR |
此外,CPU 还需要通过控制信号对外设进行控制,下面列出了一些常用的控制信号:
| 引脚名 | 方向 | 说明 |
|---|---|---|
| RD# | 输出 | 读信号,低电平有效,表示从内存或 I/O 端口读取 |
| WR# | 输出 | 写信号,低电平有效,表示写入内存或 I/O 端口 |
| ALE | 输出 | 地址锁存使能,表明复用的 AD0–AD15 当前承载地址 |
| DT/R | 输出 | 数据传输方向:接收(读)为 0,发送(写)为 1 |
| READY | 输入 | 外设准备就绪信号;未就绪时 CPU 插入等待状态 |
| HOLD | 输入 | 外部总线主设备请求总线控制权 |
| HLDA | 输出 | 总线控制权应答(Hold Acknowledge) |
其中,READY 信号的作用是支持不同速度的外设。当某些设备处理速度较慢时,CPU 会检测到 READY 为低电平,从而暂停当前操作,等待设备准备就绪,避免数据错误。
而 HOLD 与 HLDA 是总线请求/响应配对信号,用于支持 DMA 等技术,使得外设可以在不经过 CPU 的情况下直接访问内存,从而提升数据传输效率。
数据通路角色与 8086 地址语义
通用 CPU 的取指过程可用一条数据流概括:PC 给出指令地址,地址送入 MAR;主存把该地址处的指令送入 MDR;MDR 再装入 IR 供控制器译码,同时 PC 按顺序地址递增或在控制转移时改写。MAR 保存“本次要访问的主存地址”,MDR 保存“本次从主存读出或将写回主存的数据”,IR 保存“当前正在解释的指令”;它们都是面向数据通路的专用寄存器,不应与通用寄存器或 Cache 中的块混为一谈。
ALU 负责加减、逻辑和比较等组合运算,寄存器在时钟边沿保存结果,控制器则按指令和时序选择数据源、目的寄存器与 ALU 功能。数据通路回答“数据能沿哪些路径走”,控制通路回答“这一拍打开哪些路径”;即使图中有一条连线,也只有相应使能控制信号有效时数据才会写入目标。
段地址不是普通加法地址的省略写法
8086 以段地址和偏移地址共同形成 20 位物理地址:
段寄存器给出段的起始基址粒度,偏移由 IP、SP、BP、SI、DI 或有效地址计算等提供。由于段地址左移 4 位,多个不同的“段:偏移”组合可能指向同一物理地址;改变段寄存器也不意味着把数据复制到新位置,只是改变后续地址计算的基准。代码段、数据段、栈段和附加段的默认选择由指令类型和寄存器组合决定,题目指定段超越时再按显式规则覆盖。
标志寄存器中的状态位记录最近运算的结果特征,例如零、符号、进位和溢出;控制位则影响中断、方向等处理器行为。进位和溢出不是同义词:无符号加法是否超出位宽看进位,有符号补码加法是否超出可表示范围看溢出。读到条件转移时,先确认它按有符号还是无符号条件解释这些标志,再判断跳转结果。
从寄存器视角还原一次访存
执行一条含内存操作数的指令,至少包含“形成有效地址—把地址交给存储器接口—等待并取得数据或送出数据—在 ALU 或目标寄存器中使用结果”几类动作。PC、IR 主要服务于取指,MAR、MDR 服务于主存访问,通用寄存器保存程序可见的操作数和结果;它们可能在同一时钟周期通过多条数据通路并行工作,却不能把某个寄存器中尚未写入的新值当作已稳定可用。
8086 的指令预取与执行单元、段寄存器与偏移寄存器的划分,都是为了在有限引脚和寄存器宽度下组织指令流和数据流。题目问“物理地址”时按段基址左移四位再加偏移;问“逻辑地址”时保留段:偏移对;问“寄存器保存什么”时则不要擅自把它替换为已经计算好的物理地址。把三者区分开,可避免地址题中最常见的重复左移或漏加偏移。
外部总线信号描述 CPU 与主存、I/O 和 DMA 的协作,而不是 CPU 内部每一根数据通路。READY 让慢设备延长当前总线周期,HOLD/HLDA 协调外部总线主设备的临时接管;当总线控制权转交 DMA 时,CPU 的寄存器内容并不会因此自动清空,变化的是谁可以在该时段驱动地址、数据和控制线。