对于汇编程序员来说,CPU 中的主要部件是寄存器。寄存器是 CPU 中程序员可以用指令读写的部件。通过更改各种寄存器中的内容来实现对 CPU 的控制。
在计算机的中央处理单元(CPU)中,寄存器是一小块高速缓存内存,用来临时存储数据和指令。寄存器通常非常小,但访问速度极快,因为它们直接与CPU相连。
不同的 CPU,寄存器的个数、结构是不相同的。
2.1 通用寄存器
8086 CPU 的所有寄存器都是 16 位的,可以存放两个字节。
AX、BX、CX、DX 这 4 个寄存器通常用来存放一般性的数据,被称为通用寄存器。
通用寄存器(General-Purpose Registers)是可以用于多种用途的寄存器。它们不像专用寄存器那样只能做特定的任务,而是可以灵活地用于各种不同的操作。
8086 CPU 的上一代 CPU 中的寄存器都是 8 位的,为了保证兼容,使原来基于上代 CPU 编写的程序稍加修改就可以运行在 8086 之上,8086 CPU 的 AX、BX、CX、DX 这 4 个寄存器都可分为两个可独立使用的 8 位寄存器来用:
- AX 可分为 AH 和 AL;
- BX 可分为 BH 和 BL;
- CX 可分为 CH 和 CL;
- DX 可分为 DH 和 DL。
以 AX 为例,寄存器的逻辑结构如图 2.1 所示
一个 16 位寄存器可以存储一个 16 位的数据,数据在寄存器中的存放情况如图 2.2 所示
以 AX 为例,8086 CPU 的 16 位寄存器分为两个 8 位寄存器的情况如图 2.3 所示
AX 的低 8 位(0 位~7 位)构成了 AL 寄存器,高 8 位(8 位~15 位)构成了 AH 寄存器。AH 和 AL 寄存器是可以独立使用的 8 位寄存器。
图 2.4 展示了 16 位寄存器及它所分成的两个 8 位寄存器的数据存储的情况。
2.2 字在寄存器中的存储
出于对兼容性的考虑,8086 CPU 可以一次性处理以下两种尺寸的数据。
- 字节:记为 byte,一个字节由 8 个 bit 组成,可以存在 8 位寄存器中。
- 字:记为 word,一个字由两个字节组成,这两个字节分别称为这个字的高位字节和低位字节,如图 2.5 所示。
关于数制的讨论 任何数据,到了计算机中都是以二进制的形式存放的。为了描述不同的问题,又经常将它们用其他的进制来表示。比如图 2.4 中寄存器 AX中的数据是 0100111000100000,这就是 AX中的信息本身,可以用不同的逻辑意义来看待它。可以将它看作一人数值,大小是 20000。
2.3 几条汇编指令
通过汇编指令控制 CPU 进行工作
为了更方便理解,有时会用文字描述和高级语言描述这两种方式来描述一条指令的含义。在写一条汇编指令或一个寄存器的名称时不区分大小写。
2.4 物理地址
CPU 访问内存单元时,要给出内存单元的地址。所有内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,我们将这个唯一的地址称为物理地址。
一维的线性空间:所有内存单元构成的存储空间可以想象成一条长长的线,这条线上的每一个点都代表一个内存单元。这条线是“一维的”,意味着所有的内存单元是按顺序排列的,没有分支或交错。
假设你有一个非常大的数组,数组的每个元素(内存单元)都可以存储一些数据。这个数组可以看作是内存的一部分,每个元素都有一个索引(Index),这个索引就是该元素的地址。
CPU 通过地址总线送入存储器的,必须是一个内存单元的物理地址。在 CPU 地址总线上发出物理地址之前,必须要在内部先形成这个物理地址。不同的 CPU 可以有不同的形成物理地址的方式。
2.5 16 位结构的 CPU
8086 是 16 位机,也可以说是 16 位结构的 CPU,具有以下结构特性:
- 运算器一次最多可以处理 16 位的数据
- 寄存器的最大宽度为 16 位
- 寄存器和运算器之间的通路为 16 位
2.6 8086 CPU 给出物理地址的方法
8086 CPU 有 20 位地址总线,可以传送 20 位地址,送到 1 MB 寻址能力。8086 CPU 又是 16 位结构,在内部一次性处理、传输、暂时存储的地址为 16 位。从 8086 CPU 的内部结构来看,如果将地址从内部简单地发出,那么它只能送出 16 位的地址,表现出的寻址能力只有 64 KB。
8086 CPU 采用一种在内部用两个 16 位地址合成的方法来形成一个 20 位的物理地址。
地址加法器采用物理地址=段地址×16+偏移地址的方法用段地址和偏移地址合成物理地址。例如,8086 CPU 要访问地址为 123 C8H 的内存单元,此时,地址加法器的工作过程如图 2.7 所示 (图中数据皆为十六进制表示)。
2.7 “段地址×16+偏移地址=物理地址”的本质含义
本质含义是:CPU 在访问内存时,用一个基研地址(段地址×16 和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。
2.8 段的概念
内存没有分段,段的划分来自于 CPU,由 2.7 可使用分段的方式来管理内存:将物理内存划分为不同的区域,每个区域被称为一段。每一段都有自己的起始地址(基址)和长度(段长)。
- 地址
10000H
至10FFFH
的内存单元组成一个段,该段的起始地址(基址)为10000H
,段地址为1000H
,大小为100H
。 -
地址
10000H
至1007FH
、10080H
至100FFH
的内存单元也可以组成两个段,它们的起始地址(基址)分别为10000H
和10080H
,段地址分别为1000H
和1008H
,大小都为80H
。 -
段:内存的一部分,具有固定的起始地址(基址)和长度。
- 段地址:段的相对起始地址,用于计算物理地址。
- 偏移地址:相对于段首地址的偏移量,用于确定段内位置。
- 物理地址:由段地址和偏移地址相加得到的实际内存地址。
- 段地址 × 16 必须是 16 的倍数。
- 偏移地址为 16 位,寻址能力为 64KB。
- 段的最大长度为 64KB。
2.9 段寄存器
8086 CPU 有 4 个段寄存器:CS、DS、SS、ES
2.10 CS 和 IP
CS:代码段寄存器 IP:指令指针寄存器
2.11 修改 CS、IP 的指令
在 CPU 中,程序员能够用指令读写的部件只有寄存器,通过改变寄存器中的内容实现对 CPU 的控制。
2.12 代码段
汇编语言(第4版) (王爽) (Z-Library).pdf
使用 DosBox 来 debug
下载 DosBox 和 debug.exe,两个放在同一目录下。
在 dosbox. conf配置 DosBox 的挂载目录,如果没有则用在 dosbox 运行 config -writeconf dosbox.conf
来生成,接着添加 debug. exe 所在目录