2.2 8086微处理器的功能结构
2.2.1 总线接口单元(BIU)
总线接口部件BIU(如图2-7所示)主要由地址加法器、专用寄存器组、指令队列缓冲器以及总线控制电路等四个部件组成。其主要功能是负责完成CPU与存储器或I/O设备之间的数据传输。BIU中地址加法器将来自于段寄存器的16位地址(段首地址)左移4位后与来自于IP寄存器或EU提供的16位偏移地址相加(通常将“段首地址:偏移地址”称为逻辑地址),形成一个20位的实际地址(又称为物理地址),以对1M字节的存储空间进行寻址。具体讲:当CPU执行指令时,BIU根据指令的寻址方式通过地址加法器形成指令在存储器中的物理地址,然后访问该物理地址所对应的存储单元,从中取出指令代码送到指令队列缓冲器中等待执行。指令队列一共6个字节,一旦指令队列中空出2个字节,BIU将自动进入读指令操作以填满指令队列。遇到转移类指令时,BIU将指令队列中的尚存指令作废,重新从新的目标地址中取指令送到指令队列中。当EU需要读写数据时,BIU将根据EU送来的操作数地址形成操作数的物理地址,从中读取操作数或者将指令的执行结果传输到该物理地址所指定的内存单元或外设端口中。
BIU的总线控制电路将CPU的内部总线与外部总线相连,是CPU与外部交换数据的通路。BIU的总线控制电路包括16条数据总线、20条地址总线和若干控制总线。
图2-7 8086 CPU结构框图
2.2.2 执行单元(EU)
指令执行部件EU主要由算术逻辑运算单元ALU、标志寄存器FR、通用寄存器组和EU控制器等四个部件组成。其主要功能是执行指令。一般情况下指令顺序执行,EU可不断地从BIU指令队列缓冲器中取得执行的指令,连续执行指令,而省去了访问存储器取指令所需的时间。如果指令执行过程中需要访问存储器存取数据时,只需将要访问的地址送给BIU,等待操作数到来后再继续执行。遇到转移类指令时则将指令队列中的后续指令作废,等待BIU重新从存储器中取出新的指令代码进入指令队列缓冲器后,EU才能继续执行指令。这种情况下,EU和BIU的并行操作会受到一定的影响,但只要转移类指令出现的频率不是很高,两者的并行操作仍然能取得较好的效果。
EU中的算术逻辑运算部件ALU可完成16位或8位二进制数的运算,运算结果一方面通过内部总线送到通用寄存器组或BIU的内部寄存器中以等待写到存储器;另一方面影响状态标志寄存器FR的状态标志位。16位暂存器用于暂时存放参加运算的操作数。
EU控制器则负责从BIU的指令队列缓冲器中取指令、分析指令(即对指令译码),然后根据译码结果向EU内部各部件发出控制命令以完成各条指令的功能。
2.2.3 8086 CPU的引脚功能
8086 CPU采用标准DIP 40线封装,根据它的基本性能至少包含16条数据线,20条地址线,再加上其他一些必要的控制信号,这样芯片引脚数量太多,因此对部分引脚采用分时复用方式,构成40个引脚的双列直插式封装。8086 CPU引脚如图2-8所示。
下面对各引脚功能作简要说明:
1.地址/数据总线AD15~AD0
分时复用的寻址存储器或端口的地址总线和数据总线。传输地址时三态输出,传输数据时双向三态输入/输出。
2.地址/状态总线A19/S6~A16/S3
分时复用地址/状态总线为输出、三态总线。
作为地址线使用时,A19~A16与AD15~AD0一起构成访问存储器的20位物理地址,当CPU访问I/O端口时,A19~A16保持为“0”。
作状态线用时,S6~S3用来输出状态信号,其中:S6总是低电平,以表示8086 CPU当前连在总线上;S5表明中断允许状态位IF的当前设置;S4和S3表示当前访问存储器所使用的段寄存器,S4和S3编码与段寄存器对应关系如表2-1所示。在DMA方式时,这些引脚成浮空状态。
图2-8 8086 CPU引脚
表2-1 S4、S3编码表示的段寄存器
3.控制总线
(1)(Bus High Enable/Status)
高8位数据总线允许/状态复用引脚,三态、输出,低电平有效。
可以看做一根附加的地址总线,用来访问存储器的高字节,而A0用来访问存储器的低字节,所以通常作为接在高8位数据总线上设备的片选信号,而A0作为接在低8位数据总线上设备的片选信号,其关系如表2-2所示。
表2-2 和A0编码与数据总线数据传输间关系
非数据传输期间,S7输出状态信号。在DMA方式时,它为浮空状态(高阻状态)。
(2)(Read)
读信号,三态、输出,低电平有效。当时,表示当前CPU正在读存储器或I/O端口,到底是访问存储单元还是I/O端口则取决于信号线的电平。在系统总线进入“保持响应”期间,被浮空。
(3)READY
准备就绪信号,是被访问的存储器或I/O端口发给CPU的响应信号,高电平有效。当READY=1时,表示CPU访问的存储器或I/O端口已准备就绪,马上可以进行一次数据传输。CPU在每个总线周期的T3状态上升沿开始对READY信号采样,若检测到READY为低电平,表示所访问的存储器或I/O端口尚未准备就绪,此时,CPU在T3状态之后自动插入一个等待周期TW,在TW状态的上升沿继续测试READY信号电平,为低电平时继续插入TW状态,直到READY变为高电平,进入T4状态,完成数据传输过程,从而结束当前总线周期。
(4)
测试信号,输入,低电平有效。当执行WAIT指令时,每隔5个时钟周期,CPU就对信号进行一次测试。若为高电平,则CPU重复执行WAIT指令而处于等待状态,直到为低电平,CPU才脱离等待状态,继续执行后续指令。
(5)INTR(Interrupt Request)
可屏蔽中断请求信号,输入,高电平有效。当INTR=1时表示外设向CPU发出了中断请求,CPU在每条指令的最后一个时钟周期对INTR进行测试。一旦测试到INTR=1,并且当前中断允许标志IF=1,CPU就响应中断请求,停止执行指令序列,转去执行中断服务程序。
(6)NMI(Non-Maskable Interrupt Request)
非屏蔽中断请求信号,输入,边沿触发,上升沿有效。此请求不受IF状态的限制,CPU一旦检测到NMI有效,待当前指令执行完毕就响应。显然,这是一种比INTR优先级高的中断请求。
(7)RESET
复位信号,输入,高电平有效。RESET信号至少要保持4个时钟周期,CPU收到RESET信号后,停止进行操作,并将标志寄存器、段寄存器、指令指针等复位到初始状态(CS为全1,其他寄存器清零),指令队列清空。
(8)CLK(Clock)
系统时钟,通常由8284A时钟发生器输入,该时钟信号的低/高之比常采用2:1(占空度为1/3)。CPU可使用的时钟频率随芯片型号不同而异,如8086为5MHz,8086-1为10MHz,8086-2为8MHz。
4.电源线VCC和地线GND
电源线VCC接入单一的+5V电源。两条地线GND应有效接地。
5.其他控制线(24~31引脚)
这些控制线的性能将根据方式控制线所处的状态而确定。当=1时,8086 CPU工作于最小方式,在此方式下,对存储器或I/O端口的读写控制信号以及总线请求/响应信号直接由CPU这8根引脚提供,当=0时,8086 CPU工作于最大方式,这8根引脚被重新定义,上述控制信号由总线控制器8288根据总线周期状态提供,而不是由8086 CPU提供。下面分别讲述最小方式和最大方式。
(1)最小方式
①(Interrupt Acknowledge)
中断响应信号,它用于对外设的中断请求作出响应。8086CPU的信号实际上是两个连续的负脉冲,第1个负脉冲通知外设接口,它发出的中断请求已获得允许;外设接口收到第2个负脉冲后,往数据总线上放中断类型码,使CPU得到有关此中断源的服务程序入口地址信息,从而转入相应的中断处理程序。
② ALE(Address Latch Enable)
地址锁存信号,是8086 CPU提供给地址锁存器8282/8283的控制信号,高电平有效。在任何一个总线周期的T1状态,ALE输出有效电平,以表示当前在地址/数据复用总线上输出的是地址信号,地址锁存器在ALE下降沿对地址信息进行锁存。也可将ALE看做是8282/8283的片选信号。在DMA方式下,ALE不能浮空。
③(Data Enable)
数据允许信号,三态、输出,低电平有效,通常用作为数据总线收发器的选通信号。在每个存储器或I/O访问周期以及中断响应周期,变为低电平。在DMA方式下,处于浮空状态。
④ (Data Transmit /Receive)
数据发送/接收控制信号,三态、输出。在使用8286/8287作为数据总线收发器系统中,控制8286/8287的数据传输方向。时,CPU发送数据;=0时,CPU接收数据。在DMA方式下,它处于浮空状态。
⑤ (Memory/Input and Output)
存储器或I/O端口访问控制信号,三态、输出。时,表示CPU正在访问存储器;时,则表示CPU正在访问I/O端口。
⑥(Write)
写信号,三态输出,低电平有效。时,表示CPU正在进行存储器或I/O写操作,由决定数据是写入存储器还是写入I/O端口。在DMA方式下,该引脚浮空。
⑦ HOLD(Hold Request)
总线请求信号,输入,高电平有效。当DMA操作或其他处理器要求占用总线时,HOLD信号为高电平,表示外界请求CPU让出对总线的控制权。
⑧ HLDA(Hold Acknowledge)
总线响应信号,输出,高电平有效。当CPU同意让出总线控制权时,输出HLDA高电平信号,通知外界可以使用总线。同时主CPU所有具有“三态”的信号线都进入浮空状态,当HOLD变为低电平时,主CPU将HLDA变为低电平,重获总线控制权。
(2)最大方式
①(Bus Cycles Status)
总线周期状态标志,三态、输出。这些信号由CPU送入8288总线控制器对应输入端,8288利用这些信号的不同组合,产生访问存储器或I/O的控制信号或中断响应信号。和编码与具体操作类型之间的对应关系如表2-3所示。
由表2-3可见只要有一根为低电平,即开始一个总线周期。
表2-3的编码与操作类型之间的对应关系
② QS1、QS0(Instruction Queue Status)
指令队列状态信号,输出。QS1和QS0不同编码状态,反映了CPU内部当前的指令队列状态,以便外部主控设备对8086内部指令队列的动作进行跟踪。QS1、QS0的不同编码状态和指令队列的状态如表2-4所示。
表2-4 QS1、QS0的编码和指令队列的状态表
③
封锁信号,三态、输出,低电平有效。有效时表示CPU不允许其他总线主控设备占用总线。这个信号电平可用指令在程序中设置。如在一条指令前加上LOCK前缀,则在执行这条指令期间保持有效,即在此指令执行期间,封锁其他主控设备使用总线。CPU响应中断执行两个中断响应周期,在第一个中断响应周期自动封锁总线。在DMA方式下,线处于浮空状态。
④
总线请求信号输入/总线请求允许信号输出,双向、三态,低电平有效。输入时表示其他主控设备向CPU请求使用总线,输出时表示CPU对总线请求的响应信号。两条线可同时与两个主控设备相连,内部保证有较高优先级。
2.2.4 寄存器组
1.通用寄存器组
8086的通用寄存器可分为两组。
数据寄存器:包括4个16位的寄存器AX、BX、CX和DX,可用来存放16位的数据或地址。同时每个数据寄存器又可分成两个8位寄存器:AH、AL、BH、BL、CH、CL、DH和DL,用来存放8位数据。
数据寄存器用于存放指令操作数。在一些指令中,某些寄存器具有特定的用途:如AX作累加器;BX作基址寄存器;CX在串操作指令中用做计数器;DX在字乘法、除法指令中存放乘积高位、被除数高位或余数,在某些I/O操作期间用来保存I/O端口地址等。
指针寄存器和变址寄存器:它们是4个16位寄存器。堆栈指针SP(Stack Point)和基址指针BP(Basic Point)称为指针寄存器,用来指示当前堆栈段中的数据所在的偏移地址。源变址寄存器SI(Source Index)和目的变址寄存器DI(Destination Index)称为变址寄存器,用来表示当前数据段中操作数的索引地址(偏移地址的一部分)。
2.段寄存器和存储器分段
8086 CPU共有20根地址线,具有对1MB存储空间的寻址能力。直接寻址需要20位地址码,而所有的内部寄存器只有16位,16位寄存器的直接寻址能力为64K字节。因此,在8086系统中采用分段技术把1M字节的存储空间分成若干个逻辑段,每段最长为64K字节,这些逻辑段可在整个存储空间中浮动,用段寄存器给定各个逻辑段的首地址的高16位,这个地址被称做段基址。其中,代码段寄存器CS用来存放当前程序所在的代码段的段基址,代码段中通常存放可执行的指令代码;数据段寄存器DS用来存放程序当前使用的数据段的段基址,附加段寄存器ES用来存放程序当前使用的附加段的段基址,数据段和附加段通常存放参加运算的操作数或运算结果;堆栈段寄存器SS则用来存放当前使用的堆栈段的段基址,一些临时性的数据被保存在堆栈中。
3.标志寄存器
8086CPU中设置了一个16位标志寄存器FR,用来存放运算结果的特征,具体格式如图2-9所示。
图2-9 标志寄存器Flag
16位标志寄存器FR中只用其中9位作标志位,其余位为无效位。9个标志位可分成两类:一类叫状态标志位,用来表示算术逻辑运算结果的特征,包括CF、PF、AF、ZF、SF和OF;另一类叫控制标志位,用来控制CPU的操作,由程序设置或清除,它们是IF、DF、TF。
(1)CF(Carry Flag)进位标志位。当进行16位或8位数加法或减法运算时,若最高位产生进位或借位时,CF=1;否则CF=0。逻辑运算的结果总使CF=0。
(2)PF(Parity Flag)奇偶校验标志位。若运算结果低8位中含有偶数个“1”时,PF=1,否则PF=0。
(3)AF(Auxiliary Carry Flag)辅助进位标志位。当进行8位数运算时,低4位向高4位产生进位或借位时,AF=1;否则AF=0。
(4)ZF(Zero Flag)零标志位。若运算结果为0,ZF=1;否则ZF=0。
(5)SF(Sign Flag)符号标志位。对于带符号的数,用最高位表示数的符号。若运算结果的最高位为1,表示结果为负数,SF=1;否则SF=0。
(6)OF(Overflow Flag)溢出标志位。当进行带符号数补码运算时,运算结果超出了机器所能表示的数值范围(即字节运算时结果大于+127或小于−128,而字运算中的结果大于+32767或小于−32768),就产生溢出。此时,OF=1;否则OF=0。在8086指令系统中,有一条中断指令INTO能够在发生溢出时产生内部中断,使程序自动跳转到溢出中断服务子程序。
(7)IF(Interrupt Enable Flag)中断允许标志位。用于允许或禁止CPU响应可屏蔽中断,由程序控制。若IF=1,则CPU可以响应引脚INTR来的外部中断请求;若IF=0,则禁止CPU响应引脚上的中断请求。IF位可通过STI指令或CLI指令进行置位或复位。
(8)DF(Direction Flag)方向标志位。用于控制字符串指令操作的步进方向,由程序控制。当DF=1,表示串运算指令地址指针自动减量(字节操作减1,字操作减2),即串操作由高地址向低地址进行;反之地址指针自动增量,串操作由低地址向高地址进行。DF可通过STD指令或CLD指令进行置位或复位。
(9)TF(Trap Flag)单步标志位。也称陷阱标志,该标志是为了调试程序而设置的。当TF=1时,表示CPU以单步方式执行程序,即CPU每执行完一条指令就自动产生一次内部中断,用户可用此来进行程序调试、跟踪指令执行结果;当TF=0,表示CPU正常执行程序。
4.指令指针
IP(Instruction Pointer)指令指针是一个16位寄存器,用来存放将要执行的下一条指令在当前代码段中的偏移地址。在程序运行过程中,BIU可修改IP中内容,使IP总是指向下一条待取的指令。IP和CS一起指定下一条指令的物理地址,物理地址=CS × 16+IP。
2.2.5 8086基本时序
8086基本时序有时钟周期、指令周期和总线周期。
(1)时钟周期。CPU的任何操作都是在时钟脉冲信号CLK的统一控制下,一个节拍一个节拍地工作。时钟脉冲信号的间隔时间称为时钟周期,通常表示为T周期。时钟周期可通过微处理器的时钟主频计算得到,即T=1/主频。例如,主频为5MHz,其时钟周期T=200ns。8086的时钟信号如图2-10所示。
图2-10 8086时钟周期
(2)指令周期。任何指令的执行过程都是由取指令、指令译码和指令执行等操作组成的。完成一条指令所有操作需要的时间称为指令周期。指令周期的长度,以时钟周期T为单位计量。不同指令的执行时间不等,即指令周期长度不等,例如8086的最短指令周期为2T,而最长的指令周期则达到200T左右。
(3)总线周期。CPU与外部系统的信息交换都是通过总线来进行的。完成一次总线操作所需的时间称为总线周期。每当CPU要从存储器或I/O端口存取一个单元(字或字节)均需要一个总线周期。8086的一个典型总线周期由4个时钟周期所组成,分别以T1、T2、T3、T4来表示,如图2-11所示。在第一个时钟周期T1期间,CPU送出地址A15~A0,由地址锁存器将其锁存;在T2~T4期间,CPU与存储器单元或I/O端口交换数据;在总线周期的T4时钟周期结束后,又开始新的总线周期。
若所使用的存储器或外设的工作速度较慢,不能满足上述的基本时序的要求,则可用一个产生外部准备好READY信号的电路,使CPU在T3时钟与T4时钟之间插入TW等待时钟,来解决CPU与存储器或外设之间的时间配合,如图2-11所示的延长总线周期。CPU在T3时钟周期的前沿将测试READY输入引脚信号,若READY为低电平(未准备好),则在T3、T4之间插入等待时钟TW以延长总线周期。插入TW的个数,与READY输入引脚信号低电平持续时间长短有关。在每个TW时钟的上升沿,也将检测READY信号,若READY信号为高电平(已准备好)时,则总线操作进入T4时钟状态。
图2-11 总线周期
2.2.6 8086存储器组织
1.存储器的分段
8086微处理器有20根地址线,因此,具有220=1M字节的存储器地址空间。这1M字节的内存单元按照00000H~FFFFFH来编址。
由于8086微处理器的内部寄存器,包括指令指针和堆栈指针都是16位的,显然不能用寄存器直接对1M的内存空间进行寻址(16位寄存器只能寻址216=64K字节),因此,8086系统中引入了分段的概念。它把1M存储空间分成若干个逻辑段,每个逻辑段容量为64K字节,段内任一单元的地址可用一个16位的整数表示,称为偏移地址或偏移量,如图2-12所示。这样一来,要访问某一个存储器单元(包含在某逻辑段中),就要先找到其所在段的起始处(称为段基址或段址,存放段址的寄存器称为段地址寄存器或段址寄存器)。因此,在8086系统中一个存储器单元的地址可由段地址和偏移地址两部分组成,即段地址:段内偏移地址。
图2-12 各逻辑段的排列
为实现这种分段组织,8086微处理器中提供了专门的寄存器存放这两部分地址,段内偏移地址使用IP、SP、BX、BP、SI或DI,段地址使用CS、DS、SS或ES。
存储器的分段,犹如学生宿舍楼的房间分层划分一样,给定了楼层号和房间在该层的顺序号,就可以找到指定的房间。楼层号相当于段地址,各层房间的顺序号相当于偏移量。一个内存单元的地址可用“段址:偏移量”表示。
20位的段地址怎么能放在16位的寄存器中呢?8086微处理器解决这个问题的方法很简单,即只存20位地址的高16位,低4位默认为0,也就是规定段必须从地址为16的整数倍的存储单元开始。
另外,8086微处理器允许逻辑段在整个存储空间浮动,即段与段之间可以部分重叠、完全重叠、连续排列或断续排列,如图2-12所示。这样,整个1M存储空间中可设置16~64K个逻辑段。
存储器采用分段方法进行组织,带来了诸多好处。首先,它解决了用16位寄存器寻址1MB内存的问题,扩大了存储空间;其次,可以使指令系统中的大部分指令只涉及16位地址,这减少了指令长度,提高了执行程序的速度;再者,内存分段也为程序的浮动装配创造了条件。
段与段之间可以重叠的优点是,对于小程序可以大大节省内存空间。实际上,操作系统在对程序进行装配时,一般总让数据段和代码段相邻,当代码段小于64K时,就将数据段往代码部分靠拢。尽管从表面上看CS、DS赋为不同的值,概念上代码和数据是在两个段中,但实际上程序代码后面就紧跟着数据。当数据所占区域也比较小时,两者或许在同一个64K范围或者在一个更小的范围内,还可能连同堆栈段都在这个范围内。这样,可以同时将更多的程序装入内存。
段与段之间可以断续的优点是可以充分利用分散的剩余内存空间。
2.物理地址与逻辑地址的转换
按照存储单元在存储器中的实际顺序依次进行编号,此编号就是存储单元的物理地址,按照物理地址可直接在存储器中找到指定的存储单元。物理地址从0编起,通常用十六进制数表示。
存储器采用分段组织后,任意一个存储单元的位置由段基址和段内偏移量两部分共同给出,称为存储单元的逻辑地址,表示为逻辑地址=段基址:偏移量。但是在编写程序时,事先无法确定存储器中存放指令或数据的具体位置,即它的物理地址。那么计算机是如何根据该逻辑地址去找到具体的存储单元呢?8086微处理中引入了一个叫做地址加法器的部件。寻址时,它先设定一个参考位置,依此为基础,确定其他存储单元的位置。参考位置用段址表示,相对参考位置的偏移用偏移量表示,即用“段基址:偏移量”表示指定单元的地址。具体操作是将段基址送入地址加法器并左移4位,再将段内偏移地址送入相加,得到一个20位的实际地址,该地址又称为物理地址或绝对地址,是指CPU和存储器进行数据交换时实际寻址所使用的地址,即CPU送到地址总线上的地址。
程序中不能使用20位的实际地址,而使用16位的逻辑地址,任何一个存储单元对应的20位物理地址,都是由逻辑地址经上述变换得来的。
地址计算公式为:物理地址=段基址×16+偏移地址。
物理地址的形成过程如图2-13所示。
图2-13 CPU物理地址的形成
例如,代码段寄存器CS=2000H,指令指针寄存器存放的是偏移地址IP=2200H,则存储器的物理地址为20000H+2200H=22200H。
一个单元的物理地址是唯一的,而逻辑地址可由不同的段地址或偏移量组成。例如3243:0014H和3241: 0034H表示的是同一个物理地址。
16位段地址左移四位变成20位,故由“段地址:偏移量”确定的物理地址是20位。20位地址的寻址空间是220=210K=1M。这就是为什么8086是16位机,却可以获得20位的地址的原因。
对于逻辑地址有下述说明。4个段寄存器分别指向4个现行可寻址的分段的起始字节单元。一般指令程序存放在代码段中,段地址来源于代码段寄存器,偏移地址来源于指令指针IP。当涉及一个堆栈操作时,段地址寄存器为SS,偏移地址来源于栈指针寄存器SP。当涉及一个操作数时,则由数据段寄存器DS或附加段寄存器ES作为段寄存器,而偏移地址是由16位偏移量得到。16位偏移量可以由指令中的偏移量加上16位地址寄存器的值组成,取决于指令的寻址方式。寻址时到底使用哪个寄存器,BIU根据执行操作的种类和要取得的数据类型确定,如表2-5所示。
表2-5 逻辑地址源