技术

ICS 与 8086 复习 05:8086 寄存器与分段寻址

ICS 与 8086 汇编复习 · 第 05 篇 系列目录 · 上一篇 · 下一篇

看到 1234:0010,先不要把它当成一个普通的十六进制数。冒号左边是段值,右边是偏移量,两者共同定位内存。8086 地址题的关键,是把寄存器、逻辑地址、物理地址和内存内容分开计算。

本篇复习目标:会认寄存器,会算段地址,会按小端顺序读写字数据,并能解释为什么不同逻辑地址可以指向同一字节。

先画清寄存器的分工

8086 的主要程序可见寄存器都是 16 位。按用途记,比逐个背英文缩写更有效。

类别 寄存器 做题时首先想到的用途
数据寄存器 AX、BX、CX、DX 保存数据;部分指令有隐含操作数
指针与变址寄存器 SP、BP、SI、DI 栈顶、栈中数据、源与目标地址
段寄存器 CS、DS、SS、ES 提供代码、数据、栈、附加段的段值
指令指针 IP 与 CS 配合确定指令位置
标志寄存器 FLAGS 记录运算状态并控制部分执行行为

AX 可拆成 AH 和 AL,BX、CX、DX 同理。若 AX=1234H,则 AH=12H、AL=34H。随后执行 MOV AL,56H,AX 成为 1256H,AH 没有改变。SI、DI、BP、SP 在 8086 中不能这样拆成高低字节寄存器。

还要记住三组常见的隐含关系:LOOP 使用 CX;串指令常使用 SI、DI、CX;字乘除常涉及 AX 或 DX:AX。CX 与 CL 是同一个寄存器的整体和低字节,不能把二者当作互不影响的两个计数器。

16 位寄存器如何找到 1 MiB 内存

8086 有 20 根地址线,物理地址范围为 00000H 到 FFFFFH,共 2^20 个字节,即 1 MiB。单个 16 位值只有 0000H 到 FFFFH,因此采用段值与偏移量共同形成地址:

段基址 = 段值 × 10H
物理地址 = 段基址 + 偏移量

这里的 10H 等于十进制 16。段寄存器存放的是段值,左移四位后才得到段基址。例如 DS 为 1234H,对应段基址是 12340H,不能直接把 1234H 加到偏移量上。

16 位偏移量使一个段能够表示的偏移范围为 0000H 到 FFFFH,覆盖最多 64 KiB。段基址按 16 字节对齐;这不代表段的长度只有 16 字节,也不代表各段必须互不重叠。

以下例子都不跨越 1 MiB 边界。对原始 8086,若加法产生第 21 位,地址总线上只留下低 20 位,不能把这种边界行为直接推广到所有后续 x86 环境。

一道地址题,分四步计算

已知:

DS = 1234H    SS = 2000H
BX = 0010H    SI = 0004H    BP = 0010H

求 MOV AX,[BX+SI+6] 所访问的地址,并求执行结果。这里未带后缀的 6 按通常 MASM 默认十进制理解,恰好与 6H 相同。

  1. 先算有效地址:0010H+0004H+0006H=001AH。
  2. 该地址表达式不含 BP,默认使用 DS。
  3. 算物理地址:1234H×10H+001AH=1235AH。
  4. MOV 的目标是 AX,因此读取连续两个字节,而不是只读一个字节。

若物理地址 1235AH 的内容为 78H,1235BH 的内容为 56H,则 AX=5678H。低地址保存低字节,这是 x86 的小端存储顺序。

换成 MOV AX,[BP+6],有效地址为 0016H,但默认段改为 SS,所以物理地址是 20016H。同样的偏移量,搭配不同段寄存器,就可能访问完全不同的位置。

默认段和合法寻址组合

常见的默认配对如下。

场景 默认地址关系
取指令 CS:IP
普通数据访问,地址表达式不含 BP 通常使用 DS
普通数据访问,地址表达式含 BP 通常使用 SS
PUSH、POP 等栈操作 SS:SP
MOVSB 等串传送的源与目标 DS:SI 与 ES:DI

8086 中,普通内存操作数可用 BX、BP、SI、DI 构造地址。常见合法双寄存器组合是 [BX+SI]、[BX+DI]、[BP+SI]、[BP+DI],并可再加位移量。[AX]、[SP]、[BX+BP]、[SI+DI] 不能直接套用为 8086 的普通有效地址形式。

段超越前缀可以改变许多普通数据访问的默认段,但不能因此认为每一种隐含访问都能任意换段。尤其要单独记住串指令的目的地址 ES:DI。

地址不唯一,内存字节却是同一个

比较以下两个逻辑地址:

1234:0010 → 12340H + 0010H = 12350H
1235:0000 → 12350H + 0000H = 12350H

它们对应同一物理地址。因此,“段地址不同”不能推出“物理地址不同”。判断是否重合必须代入公式,不能只比较冒号左边。

栈题也遵循相同规则。若 SS=2000H、SP=0100H、AX=1234H,执行 PUSH AX 后,SP 先减 2,成为 00FEH,随后把 34H 写到 200FEH、12H 写到 200FFH。栈向低地址增长与字内的小端顺序,是两个需要同时应用的规则。

读寄存器值与读内存值是两次不同的动作

比较 MOV AX,BX 与 MOV AX,[BX]。前者复制 BX 中的数值,后者把 BX 当作偏移量,使用默认数据段访问内存,再把读到的字放入 AX。假如 BX 为 0010H,前者的结果已经确定;后者的结果还依赖 DS,以及相应两个字节的内存内容。

因此,求程序运行结果时不能停在“算出了物理地址”。地址只是找到了门牌,最后还要根据访问宽度、字节顺序和内存初值求出实际操作数。反过来,若题目只给寄存器而没有给内存内容,就可能只能算出地址,不能凭空写出 AX 的最终值。

检查题目条件也能减少无效计算:读 AL 只需一个字节,读 AX 要两个字节;立即数操作不需要访问该数值所对应的内存地址;寄存器间复制也不需要拿段值参与运算。

标志判断必须带着位宽与数值解释

FLAGS 并不把每个结果简单归类为“对”或“错”。例如 8 位加法 7FH+01H 得到 80H:按无符号数解释,127 加 1 仍在范围内,CF=0;按带符号数解释,两个正数得到负数编码,OF=1。SF=1 只说明结果最高位为 1,不能单独证明有符号计算没有溢出。

做标志题时,先标出操作数是字节还是字,再按该位宽计算保留结果。不要因为纸面上写了四位十六进制,就把字节指令擅自当成字指令。具体判定方法见第07篇。

易错点

  • 段值、段基址、偏移量和存储内容是四种不同的量,答题时最好分别写出。
  • DS=1234H 表示段值,不表示内存 1234H 地址中的内容。
  • 同一逻辑地址在给定环境中确定一个物理地址;同一物理地址通常可用多个逻辑地址表示。
  • FLAGS 中 ZF=1 表示结果为零;PF 只统计结果最低字节中 1 的个数;CF 与 OF 分别服务于不同的数值解释。
  • 原课件第2章第22页把 BX 与 AX、CX、DX 一并排除在地址寄存器之外,这是笔误;BX 是 8086 合法的基址寄存器。课件后面出现的 FS、GS 属于后续处理器,8086 只有 CS、DS、SS、ES 四个段寄存器。

三道自测

题 1。 DS=1000H,BX=0020H,执行 MOV AL,[BX+3],物理地址是多少?

答: 默认使用 DS,有效地址为 0023H,物理地址为 10023H;因为目标是 AL,所以读一个字节。

题 2。 2000:0010 与 2001:0000 是否相同?

答: 二者的物理地址都是 20010H,对应同一字节。

题 3。 地址 30000H、30001H 依次存放 CDH、ABH,读取该处的字得到什么?

答: 得到 ABCDH。若仅读取第一个字节,则得到 CDH。

对应课件

《汇编语言 第2章.ppt》第5—18页:字节、字、小端存储与逻辑地址;第19—26页:寄存器分类;第27—35页:标志;第37—40页:段寄存器与默认配对。寄存器代际对照见第44—46页。《汇编语言 第3章.pptx》第18—28页:合法有效地址组合、默认段和段超越。本文计算题为据上述原理重新编写的复习例题。

系列导航

CONTINUE / PATH

从这里继续

顺着当前内容继续,或者换到另一个板块。

讨论这篇文章

关于《ICS 与 8086 复习 05:8086 寄存器与分段寻址》的补充、不同意见或延伸话题,都可以留在这里。

滚动到这里时自动载入留言。