8086CPU的结构与功能

CPU结构与功能

不管什么型号的CPU,其内部均有这四大部件

  1. ALU:算术逻辑单元
  2. 工作寄存器:分为数据寄存器和地址寄存器

工作寄存器的目的是为了提高运算速度,希望参与运算的数据不从外部存储器去取数据,而是在CPU内部取,所以要有能暂存少量数据的寄存器。

数据寄存器是专门存放数据的,地址寄存器是专门存放地址,进行间接寻址方式,但当地址寄存器不提供地址时,也可以用来暂存数据。

  1. 控制器:中央指挥机关
  2. I/O控制逻辑电路

8086架构图 8086结构详解_堆栈

一般CPU执行存储器(按字节组织)里面指令过程如下:

  1. CPU通过控制器部件里面的程序计数器(PC)给外部存储器的地址引脚输出地址(通过地址总线AB),同时CPU给存储器发送读操作命令;
  2. 在读操作下,就把这个地址单元的指令代码通过数据总线(DB),取回来放在指令寄存器里面(IR),注意此时因为指令没有执行完,所以PC还不能去往下一条指令,IR没有地方放数据。
  3. 指令译码器(ID)不断检测指令寄存器有没有数据,有的话就把指令取走放在ID里面,取来的指令就被ID译码分析,就知道这个指令希望CPU做什么,怎么做;
  4. ID通知控制逻辑部件,在相应的控制引脚发出相应的有效命令(读,写等);
  5. 此条指令执行完,IR为空,PC自动增加到下一条指令的地址,执行下一条指令流程。如果指令为n字节,PC自动增n。

    因为在取指令时候,不能执行指令,在执行指令时候,不能取指令,因此这种架构CPU是取指令->执行指令->取指令...这样循环下去。CPU执行效率不高。

堆栈

由先进后出原则组织的存储器区域,称为堆栈。

单片机应用中,堆栈是个特殊存储区,堆栈属于RAM空间的一部分,堆栈用于函数调用、中断切换时保存和恢复现场数据(临时数据)。

对于8006 CPU而言,堆栈操作是按字操作。

堆栈单元的地址指针由堆栈指针寄存器SP的内容提供。

堆栈操作中两个最重要的是PUSH(入栈)和POP(出栈)。

入栈举例:

执行指令

PUSH AX
PUSH BX

AX是8086里面一个16位寄存器,

初始化后,SP指向栈底加1的地址。

PUSH AX这条指令完成的功能分为2部分:

  1. 先把SP的内容减2,再放回SP,SP=SP-2,此时SP指向栈底减1地址。空出了一个字单元。
  2. 将AX的低8位放在低地址单元,高8位放在高地址单元

    需要注意的是:栈顶是活动的。执行完PUSH AX后,AL所在单元就是栈顶。再执行 PUSH BX,BL所在单元就是栈顶,而栈底是固定的。
    可以看出,栈底在高地址,栈顶在低地址。
    当SP指针超出堆栈区时,称为堆栈操作溢出。溢出的话,会造成死机。堆栈区大小需要根据实际程序定义,工程设计应该留出30%的富余量。

出栈举例:

因为遵循先进后出原则,出栈先执行POP BX

  1. 把SP的16位内容做栈顶地址,从该地址单元读出一个字给BX
  2. SP指针自动增加2

然后再执行 POP AX

8086 CPU的内部结构

前面提到一般微处理器的内部结构,因为她存在效率低的问题,所以intel才研发出8086。

8086的内部结构:

8086架构图 8086结构详解_数据_02


指令队列寄存器类似前面的指令寄存器IR,不同的是,在8086中,指令队列寄存器相当于6个IR(6个字节)。

只要指令队列寄存器没放满,就可以继续取。

BIU主要负责,从外部存储器中取指令,并将取回的指令放在指令队列中。

EU主要负责从指令队列中获取指令,遵循先进先出原则,并对该指令译码分析,加以执行。

8086做到了取指令和执行指令的并行操作,大大提高了效率。这种并行操作到现在依旧存在。

8086 CPU的寄存器组织

8086 CPU共有14个16位的寄存器。

按功能分,可以分为3类。

一.通用寄存器

即EU部分的8个寄存器。

  1. 数据寄存器:AX、BX、CX、DX。

    在有数据运算时,目的操作数尽量选AX,这样运算比其他寄存器快。

BX常用来提供段内地址,来进行间接寻址。

DX在IO指令中,用来做IO地址寄存器。

  1. 地址指针

地址指针寄存器有2个:

  • SP-堆栈指针寄存器:用来指示堆栈区的段内偏移地址。
  • BP-地址指针寄存器:BP和BX的作用类似,但她默认的是堆栈段内的段内偏移地址,BX是数据段内的偏移地址。

举例

8086架构图 8086结构详解_8086架构图_03


执行指令

mov BX,0002H
mov BP,0002H
mov AL,34H
mov [BX],AL

指令将AL的内容写到数据段的地址0002H单元中。

而如果执行

mov [BP],AL

则是将AL的内容写到堆栈段的地址0002H单元中。

如果我们希望将BP提供的地址是给数据段写,则需要在前面加上段超越前缀 “DS:”,指明地址指向数据段,简称段前缀。即:

mov DS:[BP],AL
  1. 变址寄存器
    变址寄存器也有两个:
  • SI-源变址寄存器
  • DI-目标变址寄存器

这两个寄存器都可以当作地址寄存器,默认指向数据段。“变”来源于8086 CPU对字符串的操作。

举例:

8086架构图 8086结构详解_数据_04


我们想将字符串从源串搬到目的串。我们可以用MOV这种数据传送的方式,但8086为了提高效率,专门为字符串开辟了一种指令-字符串操作指令。除了传送外,还有其他的操作。在3.13小节。

源串必须定义在DS段,字符串的偏移首地址,必须由SI提供。

目的串必须定义在ES段,偏移首地址,必须由DI提供。

为了将源串搬到目的串,我们可以执行

MOVSB

“B”表示字节,一次搬一个字节。她没有源操作数和目标操作数。但是CPU知道源串和目的串的地址在哪里。如果从首地址开始搬,CPU搬完一个字节后,会将地址自动"变",即加1。如果原来的指针是末地址,则会自动地减1。自动加减地址,就是“变址”的含义。

需要注意:变址只有在SI和DI当作字符串操作时候才变。

二.段寄存器

段寄存器有4个:

  1. CS-代码段寄存器,指明程序代码所在的逻辑段地址。
  2. DS-数据段寄存器
  3. ES-附加数据段寄存器
  4. SS-堆栈段寄存器

初始化时候,必须对DS、ES、SS初始化,指明我们定义的段地址。而CS用户不能初始化,由操作系统(编译器)完成。CS不能做目的操作数,只可以读,做源操作数。

三.控制寄存器

控制寄存器有2个

  1. IP-指令指针寄存器,用于提供程序代码区的偏移地址,等效于一般CPU的程序计数器PC。不能用作目标操作数。
  2. PSW-处理器状态字寄存器,一共设定了9个标志位,分为2类:1)状态标志,反映的是ALU运算后,结果的状态。2)控制表示,用来控制CPU的运行状态。

需要注意的是,对于CPU而言,外部的中断是可以屏蔽的,内部不可以屏蔽。

8086 CPU的存储器和I/O组织

一.存储器地址空间与数据存放格式

1.地址空间

8086 CPU有20根地址总线,\(A_{19}-A_{16},A_{15}-A_{10},A_{9}-A_{0}\),8086利用这20根地址线全部用来为存储器编址,所以8086能寻址的存储器地址空间为 \(2^{20}B=1MB\)

同时用低16条给外部I/O端口编址,所以8086能寻址的外部I/O地址空间为 \(2^{16}B=64KB\)

2.数据存放格式

数据存放在存储器中,一般数据格式为:

  • 字节型数据:一个字节数据占用一个地址单元。

我们可以用“伪指令”定义字节型数据,“伪指令”不是告诉CPU做什么的,这是“指令”的工作。

伪指令是告诉汇编器(将汇编语言编译成机器语言)做什么,伪指令由汇编器解释。

DB-字节型数据伪指令 ,告诉汇编器定义一个字节数据。

假设我们在DS段一开始就定义了3个字节数据

DB 12H,12,-12

8086架构图 8086结构详解_寄存器_05

  • 字型数据

DW-字型数据定义伪指令,需要注意的是,存储器中一个字单元,低字节地址称为该字单元的地址。高字节地址不用说明。

如果字单元的地址是偶地址,则称该单元为“对准的字单元”,如果是奇地址,则称为“未对准的字单元”。CPU对对准的字单元操作,要快一倍。

这是因为,在8086 CPU中,有16根数据线,定义:对偶地址操作,走低8位数据线(D0 ~ D7);对奇地址操作,走高8位数据线(D8 ~ D15)。所以假设执行对对准的字单元写,因为字单元地址是偶地址,并且要遵循高8位字节数据存放在高地址单元,低8位数据存放在低地址单元,所以16位数据在一个周期就可以一次传送完。而对未对准的字单元,则需要两个周期,第一个周期传送高8位数据,第二个周期传送低8位。

  • 双字型数据

DD-双字型数据定义伪指令

二.存储器的分段与物理地址的形成

1.为什么要分段?

因为在8086 CPU有20根地址线,能寻址 1MB 空间,但是CPU里面提供地址的寄存器只有16位,只能寻址 64KB地址空间,所以为了让1MB空间寻址完,必须把 1MB 分为许多的逻辑段来管理。

2.怎么分段?

因为地址寄存器都是16位的,所以一个逻辑段最大就是64KB,实际当中可以根据需求定义大小。

规定:逻辑段的起始地址必须能被16整除,所以1MB最多有64K个逻辑段。

定义:

存储器原来实际存在的地址称为物理地址。用“PA”表示。

一个逻辑段的起始地址称为“段基址”。

在一个逻辑段中,地址被分为两部分描述:一个16位段地址和一个16位段内的偏移地址。这样的描述方式我们称为“逻辑地址”。在实际应用当中我们用到的都是逻辑地址。

8086架构图 8086结构详解_堆栈_06


3.物理地址的形成

已知某物理单元的逻辑地址,我们可以通过换算得到物理地址:

PA=段地址*16H+段内偏移地址

将一个16进制数乘以16,相当于朝左移动一位。段内偏移地址又被称为段内有效地址。

由于段与段之间存在重叠的部分,因此同一个物理存储单元可以表示成不同的段地址和段内偏移地址。但是换算后的物理地址是唯一的。

举例

取指令的操作:

BIU把CS的内容送给加法器,加法器对该内容乘以16,BIU再把IP的内容送给加法器相加,得到取指令所在存储单元的20位物理地址,这20位物理地址通过地址产生与总线控制电路,送到外部的 A0~A20引脚。CS和IP的内容的产生和改变是由操作系统决定的,用户无法更改。

数据传送操作:

执行 MOV [BX],AX

EU通知BIU要进行写操作,BIU停止读指令操作,BIU把DS内容送给加法器乘以16,EU把BX的值沿内部数据总线送给BIU,BIU收到后再送给加法器相加,得到20位物理地址,然后EU再把AX的内容送到数据线,把20位物理地址送到地址线,同时给外部存储器发一个写命令,就把AX的内容写到该单元中。如果该存储单元是对准的,就花一个周期写完,未对准就花两个周期写完。

4.各类指令的地址信息

8086架构图 8086结构详解_数据_07