今天来回顾一下8086/8088 CPU寄存器组的知识。其实8086汇编还是很久以前学过的,Win32汇编也接触过一些,但是由于长时间不碰,生疏了不少。今后可以花点时间总结总结,梳理一下以前学习过的知识,尽管暂时还用不上,但这样就便于以后需要用到的时候很容易捡起来。我知道博客园里大多数人都是搞Web或者手机开发的,相信用汇编的人也不多,不过工作之余学一学汇编,了解一些计算机底层的知识,对自己的“身心”是有帮助的。希望自己能坚持把8086汇编完整地写完,如果有精力还可以写一写win32汇编。
这一节先从8086/8088 CPU寄存器组开始说起。
说到8086/8088 CPU寄存器组,它们的特点就是都是16位的,不论是通用寄存器、段寄存器还是标志寄存器。
8086/8088包括四个16位数据寄存器,两个16位指针寄存器,两个16位变址寄存器,一个16位指令指针寄存器,四个16位段寄存器,一个16位标志寄存器。总共有14个寄存器,这14个寄存器分成四组。我从《80x86汇编语言程序设计教程》电子版上截了一张图,它描绘了这14个寄存器的名称和分组情况。
通用寄存器
何谓通用寄存器,简单来说就是经常用到的寄存器。按照上图我们不难发现,数据寄存器、指针寄存器和变址寄存器统称为通用寄存器。这些寄存器除了各自规定的专门用途外,它们均可用于传送和暂存数据,可以保存算术逻辑运算中的操作数和运算结果。
数据寄存器
数据寄存器主要用来保存操作数或运算结果等信息,它们的存在节省了为存取操作数所需占用总线和访问存储器的时间。
四个16位的数据寄存器均可分解成八个独立的8位寄存器,这八个8位的寄存器有各自的名称,均可独立存取。比如:AX寄存器可以分解为AH寄存器和AL寄存器,其中AH寄存器就是AX寄存器的高8位,AL寄存器就是AX寄存器的低8位。其他寄存器类推。
这四个数据寄存器除了它们通用的功能以外,还有其他专门的用途。
- AX和AL寄存器又称为累加器(Accumulator),使用得比较普遍。
- BX寄存器称为基(Base)地址存储器,它是四个数据存储器中唯一可以作为存储器指针使用的存储器。
- CX寄存器称为计数(Count)寄存器。在字符串操作和循环操作时,用它来控制重复循环操作次数。在移位操作时,CL寄存器用于保存移位的位数。
- DX寄存器称为数据(Data)寄存器。在进行32位的乘除法操作时,用它存放被除数的高16位或余数。它也用于存放I/O端口地址。
变址和指针寄存器
变址和指针寄存器主要用于存放某个存储单元地址的偏移,或某组存储单元开始地址的偏移,即作为存储器指针使用。
作为通用寄存器,它们也可以保存16位算术逻辑运算中的操作数和运算结果,有时运算结果就是需要的存储单元地址的偏移。注意,16位的变址寄存器和指针寄存器不能分解成8位寄存器使用。
SI和DI寄存器称为变址寄存器。在字符串操作中,规定由SI(Source Index)给出源指针,由DI(Destination Index)给出目的指针。当然,SI和DI也可作为一般存储器指针使用。
BP和SP寄存器称为指针寄存器。BP(Base Pointer)主要用于给出堆栈中数据区基址的偏移,SP(Stack Pointer)通常只作为堆栈指针使用,即保存堆栈栈顶地址的偏移。
段寄存器
8086/8088 CPU依赖其内部的四个段寄存器实现寻址1M字节物理地址空间(20条地址线)。8086/8088把1M字节地址空间分成若干逻辑段,当前使用段的段值存放在段寄存器中。
8086/8088 CPU的4个段寄存器分别称为代码段(Code Segment)寄存器CS、数据段(Data Segment)寄存器DS、堆栈段(Stack Segment)寄存器SS、附加段(Extra Segment)寄存器ES。那么就有四个当前使用段可直接存取,这四个当前段分别称为代码段、数据段、堆栈段和附加段。
控制寄存器
指令指针寄存器
8086/8088 CPU中的指令指针IP(Instruction Pointer)给出接着要执行的指令在代码段中的偏移,通过CS:IP即可访问CPU要执行的下一条指令。
标志寄存器
虽然标志寄存器是16位,但实际包含了9个标志,主要用于反映处理器的状态和运算结果的某些特征。各标志在标志寄存器中的位置如下所示。
标识寄存器又称程序状态寄存器(Program Status Word)。它是一个存放条件码标志位、控制标志和系统标志的寄存器。
1)条件码标志用来记录程序中运行结果的状态信息,它们是根据有关指令的运行结果由CPU自动设置的。由于这些状态信息往往作为后续条件转移指令的转移控制条件,所以为条件码。它包括以下6位:
- 溢出标志(overflow flag, OF),在运算过程中,如操作数超过了机器能表示的范围称为成为溢出。此时OF置为1,否则置0。
- 符号标志(sign flag, SF),记录运算结果的符号,结果为负时置1,否则置0。
- 零标志(zero flag, ZF),运算结果为0时ZF位置1,否则置0。
- 进位标志(carry flag, CF),记录运算时从最高有效位产生的进位值。例如,执行加法指令时,最高有效位有进位时置1,否则置0。
- 辅助进位标志(auxiliary carry flag, AF),记录运算时第3位(半个字节)产生的进位值。例如,执行加法指令第3位有进位时置1,否则置0。
- 奇偶标志位(parity flag,PF),用来为机器中传送信息时可能产生的代码出错情况提供检验条件。当结果操作数中1的个数为偶数时置1,否则置0。
2)控制标志位为方向标志(direction flag, DF),在串指令中控制处理信息的方向用。当DF位为1时,每次操作后使变址寄存器SI和DI减小,这样就使串处理从高地址向低地址方向处理。当DF位为0时,则使SI和DI增大,使串处理从低地址向高地址方向处理。
3)系统标志位可以用于I/O、可屏蔽中断、程序调试、任务切换和系统工作方式等的控制。一般应用程序不必关心或修改这些位的状态,只有系统程序员或需要编制底层I/O设备控制等程序时才需要访问其中的有关位。
- 陷阱标志(trap flag, TF),用于调试时的单步方式操作。当TF位为1时,每条指令执行完后产生陷阱,由系统控制计算机;当TF位为0时,CPU正常工作,不产生陷阱。
- 中断标志(interrupt flag, IF),当IF位为1时,允许CPU响应可屏蔽中断请求,否则关闭中断。
- I/O特权级(I/O privilege level, IOPL),在保护模式下,用于控制对I/O地址空间的访问。