一文看懂8086CPU寄存器的特点和作用
8086数据寄存器介绍
通用寄存器
在8086CPU中,通用寄存器有8个,分别是AX,BX,CX,DX,SP,BP,SI,DI
下面介绍这几个通用寄存器:
数据寄存器(AX,BX,CX,DX):
数据寄存器有AX,BX,CX,DX四个组成,
由于在8086之前的CPU为8位CPU,所以为了兼容以前的8位程序,在8086CPU中,每一个数据寄存器都可以当做两个单独的寄存器来使用,由此,每一个16位寄存器就可以当做2个独立的8位寄存器来使用了。
AX寄存器可以分为两个独立的8位的AH和AL寄存器;
BX寄存器可以分为两个独立的8位的BH和BL寄存器;
CX寄存器可以分为两个独立的8位的CH和CL寄存器;
DX寄存器可以分为两个独立的8位的DH和DL寄存器;
除了上面4个数据寄存器以外,其他寄存器均不可以分为两个独立的8位寄存器;
注意在上面标志中的“独立”二字,这两个字表明AH和AL作为8位寄存器使用时,可以看做它们是互不相关的,也就是看做两个完全没有联系的寄存器X和Y即可,比如指令MOVAH,12H,CPU在执行时根本就不会知道AL中是什么鬼东西,因为它只认识AH。
下面给出一幅16位数据寄存器的结构图:
表示16位寄存器AX可以表示成两个8位寄存器,
其中AH表示高位的8位寄存器,AL表示低位的8位寄存器。
AX寄存器:
如上所说,AX的另外一个名字叫做累加寄存器或者简称为累加器,其可以分为2个独立的8位寄存器AH和AL;
在写汇编程序时,AX寄存器可以说是使用率最高的寄存器(不过,总共才那么14个寄存器,哪一个不经常使用咯?),既然AX是数据寄存器的话,那么理所当然,其可以用来存放普通的数据,由于其是16位寄存器,自然也就可以存放16位数据,但是因为其又可以分为2个独立的8位寄存器AH和AL,所以,在AH和AL中又可以独立的存放2个8位的数据,可以有以下代码(即将AX当做普通的寄存器使用,即可以用来暂存数据):
MOVAX,1234H;向寄存器AX传入数据1234H
MOVAH,56H;向寄存器AX的高8位寄存器AH中传入数据56H
MOVAL,78H;向寄存器AX的低8位寄存器AL中传入数据78H
3条语句的执行过程如下:
而既然AX又被称作为累加器,自然其还有一点点特殊的地方的:
AX寄存器还具有的特殊用途是在使用DIV和MUL指令时使用,DIV在8086CPU中是除法指令,而在使用除法的时候有两种情况,即除数可以是8位或者是16位的,而且除数可以存放在寄存器中或者是内存单元中,而至于被除数的话,自然,应该由AX来代替了,当除数是8位时,被除数一定会是16位的,并且默认是放在AX寄存器中,而当除数是16位时,被除数一定是32位的,因为AX是16位寄存器,自然,放不下32位的被除数,所以,在这里还需要使用另一个16位寄存器DX,其中DX存放32位的被除数的高16位,而AX则存放32位的被除数的低16位,同时,AX的作用还不仅仅是用来保存被除数的,当除法指令执行完成以后,如果除数是8位的,则在AL中会保存此次除法操作的商,而在AH中则会保存此次除法操作的余数,当然,如果除数是16位的话,则AX中会保存本次除法操作的商,而DX则保存本次除法操作的余数。
上面介绍的是AX寄存器在除法操作中的应用,下面还需要介绍一下AX在乘法操作中的应用,
当使用MUL做乘法运算时,两个相乘的数要么都是8位,要么都是16位,如果两个相乘的数都是8位的话,则一个默认是放在AL中,而另一个8位的乘数则位于其他的寄存器或者说是内存字节单元中,而如果两个相乘的数都是16位的话,则一个默认存放在AX中,另一个16位的则是位于16的寄存器中或者是某个内存字单元中。
同时,当MUL指令执行完毕后,如果是8位的乘法运算,则默认乘法运算的结果是保存在AX中,而如果是16位的乘法运算的话,则默认乘法运算的结果有32位,其中,高位默认保存在DX中,而低位则默认保存在AX中。
AX寄存器在DIV指令中的使用:
MOVDX,0H;设置32位被除数的高16位为0H
MOVAX,8H;设置32位被除数的低16位为8H
MOVBX,2H;设置16位除数为2H
DIVBX;执行计算
4条语句的执行过程如下:
AX寄存器在MUL指令中的使用:
MOVAX,800H;设置16位乘数为800H
MOVBX,100H;设置16位乘数为100H
MOVDX,0H;清空用来保存乘法结果的高16位
MULBX;执行计算
BX寄存器:
首先可以明确的是,BX作为数据寄存器,表明其是可以暂存一般的数据的,即在某种程度上,它和AX可以暂存一般性数据的功能是一样的,其同样为了适应以前的8位CPU,而可以将BX当做两个独立的8位寄存器使用,即有BH和BL,除了暂存一般性数据的功能外,BX作为通用寄存器的一种,BX主要还是用于其专属功能–寻址(寻址物理内存地址)上,BX寄存器中存放的数据一般是用来作为偏移地址使用的。
在8086CPU中,CPU是根据《段地址:偏移地址》来进行寻址操作的,而BX中存放的数据表示的是偏移地址的话,自然,便可以通过《段地址:[BX]》的方式来完成寻址操作了。
为了介绍BX在寻址当中的作用,下面我给出一副示意图:
上面的示意图表示:可以令BX=2,然后通过DS:[BX]来访问到内存中段地址为DS,且偏移量为2的内存单元了。
上面介绍的这种寻址方式是BX在寻址中最最简单的应用了,而对于稍微复杂的寻址方式,
还可以依赖于SI,DI,BP等寄存器来一起完成。
BX寄存器在寻址中的使用:
MOVBX,5H
MOVAH,11H
MOVAH,[BX];设置AX的值为偏移地址为BX中的值时所代表的内存单元
3条语句的执行过程如下:
从上图可以看出,在偏移地址为5时的内存单元中的数据位BBH,
而从这幅图上面就可以看出,确实通过[BX]找到了偏移地址为5处的内存单元,并且将内存单元移入了AH中。
CX寄存器:
CX寄存器作为数据寄存器的一种呢,其同样具有和AX,BX一样的特点,即可以暂存一般性的数据,同时还可以将其当做两个独立的8位寄存器使用,即有CH和CL两个8位寄存器,当然,CX也是有其专门的用途的,CX中的C被翻译为CounTIng也就是计数器的功能,当在汇编指令中使用循环LOOP指令时,可以通过CX来指定需要循环的次数,而CPU在每一次执行LOOP指令的时候,都会做两件事:
一件就是令CX=CX–1,即令CX计数器自动减去1;
还有一件就是判断CX中的值,如果CX中的值为0则会跳出循环,而继续执行循环下面的指令,当然如果CX中的值不为0,则会继续执行循环中所指定的指令。
CX寄存器在循环中的使用(输出5个白底蓝字的A):
MOVAX,0B800H
MOVDS,AX;使用80x25彩色字符模式,内存地址0xB8000-0xBFFFFF
MOVBX,0;从0xB8000开始
MOVCX,5H;循环5次
MOVDX,41H;A的16进制为41H
MOVAX,01110001B;显示白底蓝字
s:MOV[BX],DX;显示ASCII字符
ADDBX,1
MOV[BX],AX;设置字符显示属性
ADDBX,1
LOOPs
语句的执行过程如下:
DX寄存器:
DX寄存器作为数据寄存器的一种,同样具有和AX,BX,CX一样的特点,即可以暂存一般性的数据,同时还可以将其当做两个独立的8位寄存器使用,极有DH和DL,同时,DX作为一个通用寄存器的话,关于DX在其他方面的用途,当在使用DIV指令进行除法运算时,如果除数为16位时,被除数将会是32位,而被除数的高16位就是存放在DX中,而且执行完DIV指令后,本次除法运算所产生的余数将会保存在DX中,同时,在执行MUL指令时,如果两个相乘的数都是16位的话,那么相乘后产生的结果显然需要32位来保存,而这32位的结果的高16位就是存放在DX寄存器中。
DX寄存器在DIV指令中的使用(即2293812/256=8960余数为52):
MOVDX,0023H;32位被除数的高16位
MOVAX,0034H;32位被除数的低16位
MOVBX,100H;16的除数
DIVBX
语句的执行过程如下:
可以看到在语句结束以后,AX=2300H即十进制的8960,而DX=34H即十进制的52和我们的结果是一致的。
8086CPU各类寄存器特点及用途
8086有14个16位寄存器,这14个寄存器按其用途可分为通用寄存器、指令指针、标志寄存器和段寄存器等4类。
1、通用寄存器
通用寄存器有8个,又可以分成2组,一组是数据寄存器(4个),另一组是指针寄存器及变址寄存器(4个)。
数据寄存器分为:
AH&AL=AX(accumulator):累加寄存器,常用于运算;在乘除等指令中指定用来存放操作数,另外,所有的I/O指令都使用这一寄存器与外界设备传送数据。
BH&BL=BX(base):基址寄存器,常用于地址索引;
CH&CL=CX(count):计数寄存器,常用于计数;常用于保存计算值,如在移位指令,循环(loop)和串处理指令中用作隐含的计数器。
DH&DL=DX(data):数据寄存器,常用于数据传递。他们的特点是,这4个16位的寄存器可以分为高8位:AH,BH,CH,DH.以及低八位:AL,BL,CL,DL。这2组8位寄存器可以分别寻址,并单独使用。
另一组是指针寄存器和变址寄存器,包括:
SP(StackPointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置;
BP(BasePointer):基址指针寄存器,可用作SS的一个相对基址位置;
SI(SourceIndex):源变址寄存器可用来存放相对于DS段之源变址指针;
DI(DesTInaTIonIndex):目的变址寄存器,可用来存放相对于ES段之目的变址指针。
这4个16位寄存器只能按16位进行存取操作,主要用来形成操作数的地址,用于堆栈操作和变址运算中计算操作数的有效地址。
2、指令指针IP(InstrucTIonPointer)
指令指针IP是一个16位专用寄存器,它指向当前需要取出的指令字节,当BIU从内存中取出一个指令字节后,IP就自动加1,指向下一个指令字节。注意,IP指向的是指令地址的段内地址偏移量,又称偏移地址(OffsetAddress)或有效地址(EA,EffectiveAddress)。
3、标志寄存器FR(FlagRegister)
8086有一个18位的标志寄存器FR,在FR中有意义的有9位,其中6位是状态位,3位是控制位。
OF:溢出标志位OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。
DF:方向标志DF位用来决定在串操作指令执行时有关指针寄存器发生调整的方向。
IF:中断允许标志IF位用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求。但不管该标志为何值,CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求,以及CPU内部产生的中断请求。具体规定如下:
(1)、当IF=1时,CPU可以响应CPU外部的可屏蔽中断发出的中断请求;
(2)、当IF=0时,CPU不响应CPU外部的可屏蔽中断发出的中断请求。
TF:跟踪标志TF。该标志可用于程序调试。TF标志没有专门的指令来设置或清楚。
(1)如果TF=1,则CPU处于单步执行指令的工作方式,此时每执行完一条指令,就显示CPU内各个寄存器的当前值及CPU将要执行的下一条指令。
(2)如果TF=0,则处于连续工作模式。
SF:符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。在微机系统中,有符号数采用补码表示法,所以,SF也就反映运算结果的正负号。运算结果为正数时,SF的值为0,否则其值为1。
ZF:零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。
AF:下列情况下,辅助进位标志AF的值被置为1,否则其值为0:
(1)、在字操作时,发生低字节向高字节进位或借位时;
(2)、在字节操作时,发生低4位向高4位进位或借位时。
PF:奇偶标志PF用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。
CF:进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。)
4、段寄存器(SegmentRegister)
为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:
CS(CodeSegment):代码段寄存器;
DS(DataSegment):数据段寄存器;
SS(StackSegment):堆栈段寄存器;
ES(ExtraSegment):附加段寄存器。
当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS所指的64K内,这就是COM文件不得大于64K的原因。8086以内存做为战场,用寄存器做为军事基地,以加速工作。