认识寄存器
寄存器的官方叫法有很多,Wiki 上面的叫法是 Processing Register
, 也可以称为 CPU Register
,计算机中经常有一个东西多种叫法的情况,反正你知道都说的是寄存器就可以了。
认识寄存器之前,我们首先先来看一下 CPU 内部的构造。
CPU 从逻辑上可以分为 3 个模块,分别是控制单元、运算单元和存储单元,这三部分由 CPU 内部总线连接起来。
几乎所有的冯·诺伊曼型计算机的 CPU,其工作都可以分为5个阶段:「取指令、指令译码、执行指令、访存取数、结果写回」。
取指令
阶段是将内存中的指令读取到 CPU 中寄存器的过程,程序寄存器用于存储下一条指令所在的地址指令译码
阶段,在取指令完成后,立马进入指令译码阶段,在指令译码阶段,指令译码器按照预定的指令格式,对取回的指令进行拆分和解释,识别区分出不同的指令类别以及各种获取操作数的方法。执行指令
阶段,译码完成后,就需要执行这一条指令了,此阶段的任务是完成指令所规定的各种操作,具体实现指令的功能。访问取数
阶段,根据指令的需要,有可能需要从内存中提取数据,此阶段的任务是:根据指令地址码,得到操作数在主存中的地址,并从主存中读取该操作数用于运算。结果写回
阶段,作为最后一个阶段,结果写回(Write Back,WB)阶段把执行指令阶段的运行结果数据写回到 CPU 的内部寄存器中,以便被后续的指令快速地存取;
计算机架构中的寄存器
寄存器是一块速度非常快的计算机内存,下面是现代计算机中具有存储功能的部件比对,可以看到,寄存器的速度是最快的,同时也是造价最高昂的。
我们以 intel 8086 处理器为例来进行探讨,8086 处理器是 x86 架构的前身。在 8086 后面又衍生出来了 8088 。
在 8086 CPU 中,地址总线达到 20 根,因此最大寻址能力是 2^20 次幂也就是 1MB 的寻址能力,8088 也是如此。
在 8086 架构中,所有的内部寄存器、内部以及外部总线都是 16 位宽,可以存储两个字节,因为是完全的 16 位微处理器。8086 处理器有 14 个寄存器,每个寄存器都有一个特有的名称,即
「AX,BX,CX,DX,SP,BP,SI,DI,IP,FLAG,CS,DS,SS,ES」
这 14 个寄存器有可能进行具体的划分,按照功能可以分为三种
- 通用寄存器
- 控制寄存器
- 段寄存器
下面我们分别介绍一下这几种寄存器
通用寄存器
通用寄存器主要有四种 ,即 「AX、BX、CX、DX」 同样的,这四个寄存器也是 16 位的,能存放两个字节。AX、BX、CX、DX 这四个寄存器一般用来存放数据,也被称为 数据寄存器
。它们的结构如下
8086 CPU 的上一代寄存器是 8080 ,它是一类 8 位的 CPU,为了保证兼容性,8086 在 8080 上做了很小的修改,8086 中的通用寄存器 AX、BX、CX、DX 都可以独立使用两个 8 位寄存器来使用。
在细节方面,AX、BX、CX、DX 可以再向下进行划分
AX(Accumulator Register)
:累加寄存器,它主要用于输入/输出和大规模的指令运算。BX(Base Register)
:基址寄存器,用来存储基础访问地址CX(Count Register)
:计数寄存器,CX 寄存器在迭代的操作中会循环计数DX(data Register)
:数据寄存器,它也用于输入/输出操作。它还与 AX 寄存器以及 DX 一起使用,用于涉及大数值的乘法和除法运算。
这四种寄存器可以分为上半部分和下半部分,用作八个 8 位数据寄存器
- 「AX 寄存器可以分为两个独立的 8 位的 AH 和 AL 寄存器;」
- 「BX 寄存器可以分为两个独立的 8 位的 BH 和 BL 寄存器;」
- 「CX 寄存器可以分为两个独立的 8 位的 CH 和 CL 寄存器;」
- 「DX 寄存器可以分为两个独立的 8 位的 DH 和 DL 寄存器;」
除了上面 AX、BX、CX、DX 寄存器以外,其他寄存器均不可以分为两个独立的 8 位寄存器
如下图所示。
AX 的低位(0 - 7)位构成了 AL 寄存器,高 8 位(8 - 15)位构成了 AH 寄存器。AH 和 AL 寄存器是可以使用的 8 位寄存器,其他同理。
在认识了寄存器之后,我们通过一个示例来看一下数据的具体存储方式。
比如数据 19 ,它在 16 位存储器中所存储的表示如下
寄存器的存储方式是先存储低位,如果低位满足不了就存储高位,如果低位能够满足,高位用 0 补全,在其他低位能满足的情况下,其余位也用 0 补全。
8086 CPU 可以一次存储两种类型的数据
字节(byte)
:一个字节由 8 bit 组成,这是一种恒定不变的存储方式字(word)
:字是由指令集或处理器硬件作为单元处理的固定大小的数据,对于 intel 来说,一个字长就是两个字节,字是计算机一个非常重要的特征,针对不同的指令集架构来说,计算机一次处理的数据也是不同的。也就是说,针对不同指令集的机器,一次能处理不用的字长,有字、双字(32位)、四字(64位)等。
AX 寄存器
我们上面探讨过,AX 的另外一个名字叫做累加寄存器或者简称为累加器,其可以分为 2 个独立的 8 位寄存器 AH 和 AL;在编写汇编程序中,AX 寄存器可以说是使用频率最高的寄存器。
下面是几段汇编代码
mov ax,20 /* 将 20 送入寄存器 AX*/ mov ah,80 /* 将 80 送入寄存器 AH*/ add ax,10 /* 将寄存器 AX 中的数值加上 8 */
❝这里注意下:上面代码中出现的是 ax、ah ,而注释中确是 AX、AH ,其实含义是一样的,不区分大小写。
❞
AX 相比于其他通用寄存器来说,有一点比较特殊,AX 具有一种特殊功能的使用,那就是使用 DIV 和 MUL 指令式使用。
❝DIV 是 8086 CPU 中的
除法
指令。MUL 是 8086 CPU 中的
❞乘法
指令。
BX 寄存器
BX 被称为数据寄存器,即表明其能够暂存一般数据。同样为了适应以前的 8 位 CPU ,而可以将 BX 当做两个独立的 8 位寄存器使用,即有 BH 和 BL。BX 除了具有暂存数据的功能外,还用于 寻址
,即寻找物理内存地址。BX 寄存器中存放的数据一般是用来作为偏移地址
使用的,因为偏移地址当然是在基址地址上的偏移了。偏移地址是在段寄存器中存储的,关于段寄存器的介绍,我们后面再说。
CX 寄存器
CX 也是数据寄存器,能够暂存一般性数据。同样为了适应以前的 8 位 CPU ,而可以将 CX 当做两个独立的 8 位寄存器使用,即有 CH 和 CL。除此之外,CX 也是有其专门的用途的,CX 中的 C 被翻译为 Counting 也就是计数器的功能。当在汇编指令中使用循环 LOOP 指令时,可以通过 CX 来指定需要循环的次数,每次执行循环 LOOP 时候,CPU 会做两件事
- 一件事是计数器自动减 1
- 还有一件就是判断 CX 中的值,如果 CX 中的值为 0 则会跳出循环,而继续执行循环下面的指令,
当然如果 CX 中的值不为 0 ,则会继续执行循环中所指定的指令 。
DX 寄存器
DX 也是数据寄存器,能够暂存一般性数据。同样为了适应以前的 8 位 CPU ,DX 的用途其实在前面介绍 AX 寄存器时便已经有所介绍了,那就是支持 MUL 和 DIV 指令。同时也支持数值溢出等。
段寄存器
CPU 包含四个段寄存器,用作程序指令,数据或栈的基础位置。实际上,对 IBM PC 上所有内存的引用都包含一个段寄存器作为基本位置。
段寄存器主要包含
CS(Code Segment)
:代码寄存器,程序代码的基础位置DS(Data Segment)
:数据寄存器,变量的基本位置SS(Stack Segment)
:栈寄存器,栈的基础位置ES(Extra Segment)
:其他寄存器,内存中变量的其他基本位置。
索引寄存器
索引寄存器主要包含段地址的偏移量,索引寄存器主要分为
BP(Base Pointer)
:基础指针,它是栈寄存器上的偏移量,用来定位栈上变量SP(Stack Pointer)
: 栈指针,它是栈寄存器上的偏移量,用来定位栈顶SI(Source Index)
: 变址寄存器,用来拷贝源字符串DI(Destination Index)
: 目标变址寄存器,用来复制到目标字符串
状态和控制寄存器
就剩下两种寄存器还没聊了,这两种寄存器是指令指针寄存器和标志寄存器:
IP(Instruction Pointer)
:指令指针寄存器,它是从 Code Segment 代码寄存器处的偏移来存储执行的下一条指令FLAG
: Flag 寄存器用于存储当前进程的状态,这些状态有
- 位置 (Direction):用于数据块的传输方向,是向上传输还是向下传输
- 中断标志位 (Interrupt) :1 - 允许;0 - 禁止
- 陷入位 (Trap) :确定每条指令执行完成后,CPU 是否应该停止。1 - 开启,0 - 关闭
- 进位 (Carry) : 设置最后一个无符号算术运算是否带有进位
- 溢出 (Overflow) : 设置最后一个有符号运算是否溢出
- 符号 (Sign) : 如果最后一次算术运算为负,则设置 1 =负,0 =正
- 零位 (Zero) : 如果最后一次算术运算结果为零,1 = 零
- 辅助进位 (Aux Carry) :用于第三位到第四位的进位
- 奇偶校验 (Parity) : 用于奇偶校验