寄存器的介绍
1.通用寄存器
图2.3中除阴影区以外的寄存器是8086/8088和80286所具有的寄存器,它们都是16位寄存器。其中AX、BX、CX、DX 可称为数据寄存器,用来暂时存放计算过程中所用到的操作数、结果或其他信息。它们都可以以字(16位)的形式访问,或者也可以以字节(8位)的形式访问。例如,对AX 可以分别访问高位字节 AH 或低位字节 AL。这4个寄存器都是通用寄存器,但它们又可以用于各自的专用目的。 AX(accumulator)作为累加器用,所以它是算术运算的主要寄存器。在乘、除等指令中指定用来存放操作数。另外,所有的I/O 指令都使用这一寄存器与外部设备传送信息。
BX(base)可以作为通用寄存器使用。此外在计算存储器地址时,它经常用作基址寄存器。
CX(count)可以作为通用寄存器使用。此外常用来保存计数值,如在移位指令、循环(loop)和串处理指令中用作隐含的计数器。
DX(data)可以作为通用寄存器使用。一般在作双字长运算时把 DX 和 AX 组合在一起存放一个双字长数,DX 用来存放高位字。此外,对某些 I/O 操作,DX 可用来存放 I/O的端口地址。
SP、BP、SI、DI四个16位寄存器可以像数据寄存器一样在运算过程中存放操作数,但它们只能以字(16位)为单位使用。此外,它们更经常的用途是在存储器寻址时,提供偏移地址。因此,它们可称为指针或变址寄存器。在这些寄存器中,SP(stack pointer)称为堆栈指针寄存器,BP(base pointer)称为基址指针寄存器,它可以与堆栈段寄存器SS联用来确定堆栈段中的某一存储单元的地址。SP用来指示段顶的偏移地址,BP可作为堆栈区中的一个基地址以便访问堆栈中的信息。SI(source index)源变址寄存器和 DI(destination index)目的变址寄存器一般与数据段寄存器DS联用,用来确定数据段中某一存储单元的地址。这两个变址寄存器有自动增量和自动减量的功能,所以用于变址是很方便的。在串处理指令中,SI和 DI作为隐含的源变址和目的变址寄存器,此时SI和 DS联用,DI和附加段寄存器ES联用,分别达到在数据段和附加段中寻址的目的。
2.专用寄存器 8086/8088和80286的专用寄存器包括IP、SP和FLAGS3个16位寄存器。
IP(instruction pointer)为指令指针寄存器,它用来存放代码段中的偏移地址。在程序运行的过程中,它始终指向下一条指令的首地址,它与段寄存器 CS联用确定下一条指令的物理地址。当这一地址送到存储器后,控制器可以取得下一条要执行的指令,而控制器一旦取得这条指令就马上修改IP的内容,使它指向下一条指令的首地址。可见,计算机就是用IP寄存器来控制指令序列的执行流程的,因此IP寄存器是计算机中很重要的一个控制寄存器。 SP为堆栈指针寄存器,它与堆栈段寄存器联用来确定堆栈段中栈顶的地址,也就是说SP用来存放栈顶的偏移地址。
FLAGS为标志寄存器,又称程序状态寄存器(program status word,PSW)。这是一个存放条件码标志、控制标志和系统标志的寄存器。
80386及其后继机型也有三个32位专用寄存器,它们是 EIP、ESP和 EFLAGS。它们的
作用和相应的16位寄存器相同。
下面介绍标志寄存器。图2.4说明了80x86中标志寄存器的内容,图中未标明的位暂不用。
(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 地址空间的访问。
以上就是EFLAGS中主要标志位的含义。机器提供了设置某些状态信息的指令。必要时,程序员可使用这些指令来建立状态信息。
在调试程序DEBUG 中提供了测试标志位的手段,它用符号表示某些标志位的值。表2.2说明这些标志位的符号表示。
表2.2 标志位的符号表示
标 志 名标志为1 标志为0
OF溢出(是/否) OV NV
DF方向(减量/增量) DN UP
IF中断(允许/关闭) EI DI
SF符号(负/正) NG PL
ZF零(是/否) ZR NZ
AF辅助进位(是/否) AC NA
PF奇偶(偶/奇) PE PO
CF进位(是/否) CY NC
3.段寄存器
段寄存器也是一种专用寄存器,它们专用于存储器寻址,用来直接或间接地存放段地址。段寄存器的长度为16位,在80286以前的处理器中,只有代码段(code segment,CS)、数据段(data segment,DS)、堆栈段(stack segment,SS)和附加段(extra segment,ES)4个寄存器。从80386起,增加了FS和 GS两个段寄存器,它们也属于附加的数据段。
在8086~80286中,有四个专门存放段地址的寄存器,称为段寄存器。它们是代码段CS、数据段DS、堆栈段SS和附加段ES寄存器。每个段寄存器可以确定一个段的起始地址,而这些段则各有各的用途。代码段存放当前正在运行的程序。数据段存放当前运行程序所用的数据,如果程序中使用了串处理指令,则其源操作数也存放在数据段中。堆栈段定义了堆栈的所在区域,堆栈是一种数据结构,它开辟了一个比较特殊的存储区,并以后进先出的方式来访问这一区域,在第3章里还会专门加以说明。附加段是附加的数据段,它是一个辅助的数据区,也是串处理指令的目的操作数存放区。程序员在编制程序时, 应该按照上述规定把程序的各部分放在规定的段区之内。
在80386及其后继的80x86中,除上述4个段寄存器外,又增加了2个段寄存器 FS和GS,它们也是附加的数据段寄存器,所以8086~80286的程序允许4个存储段,而其他
80x86程序可允许6个存储段。
除非专门指定,一般情况下,各段在存储器中的分配是由操作系统负责的。每个段可以独立地占用64KB存储区,如图2.9所示。各段也可以允许重叠,下面的例子就可以说明这种情况。
例2.1 如果代码段中的程序占有8KB(2000H)存储区,数据段占有2KB(800H)存储区,堆栈段只占有256个字节的存储区。此时段区的分配如图2.10所示。从图中可以看出,代码段的区域可以是02000~11FFFH,但由于程序区只需要8KB,所以程序区结束后的第一个小段的首地址就作为数据段的起始地址。也就是说,在这里,代码段和数据段可以重叠在一起。当然每个存储单元的内容是不允许发生冲突的,所谓的重叠只是指每个段区的大小允许根据实际需要来分配,而不一定要占有64KB的最大段空间。实际上,段区的分配工作是由操作系统完成的。但是,系统允许程序员在必要时可指定所需占用的内存区,指定方法将
在第4章中说明。
如果程序中的四个段都在64KB的范围之内,而且程序运行时所需要的信息都在本程序所定义的区段之内,那么程序员只要在程序的首部设定各段寄存器的值就可以了。如果程序的某一段(例如数据段)在程序运行过程中会超过64KB空间,或者程序中可能访问除本身四个段以外的其他段区的信息,那么在程序中必须动态地修改段寄存器的内容,以保证所获得的信息的正确性,并不会因段区的划分而限制了程序空间。
表2.3 8086/8088,80286的段寄存器和相应存放偏移地址的寄存器之间的默认组合 段 偏移
CS IP
SS SP或BP
DS BX、DI、SI或一个16位数
ES DI(用于串指令)
表2.4 80386及其后继机型的段寄存器和相应存放偏移地址的寄存器之间的默认组合 段 偏移
CS EIP
SS ESP或EBP
DS EAX、EBX、ECX、EDX、EDI、ESI、一个8位数或一个32位数
ES EDI(用于串指令)
FS 无默认
GS 无默认
在这种默认组合下,程序中不必专门指定其组合关系,但程序如用到非默认的组合关系,则必须用段跨越前缀加以说明。