8086处理器
处理器是计算机系统的硬件核心部件,决定着计算机的关键性能,常被称为*处理单元,简称CPU。
功能结构
处理器由多个功能部件组成。Intel公司按两个功能模块描绘了Intel 8086处理器的内部结构:
总线接口单元和执行单元
总线接口单元BIU(Bus Interface Unit)
由6字节的指令队列(指令寄存器)、指令指针IP、段寄存器(CS、DS、SS和ES)、地址加法器和总线控制逻辑等构成。
总线接口单元BIU管理着 8086 与系统总线的接口,负责处理器对存储器和外设进行访问。
8086 所有对外操作必须通过 BIU 和这些总线进行,例如从主存中读取指令、从主存或外设读取数据、向主存或外设写出数据等操作。
执行单元EU(Execution Unit)
由算术逻辑单元ALU(Arithmetic Logic Unit)、标志寄存器、通用寄存器和进行指令译码的EU控制电路等构成,负责执行指令的功能。
源程序由一条条语句组成,运行程序将执行一条条的指令。一条指令的执行可以分为两个主要阶段:取指和执行。
取指阶段:处理器将指令代码从主存储器中取出并进入处理器内部的过程。(队列形式)
执行阶段:处理器将指令代码翻译成它代表的功能(被称为译码)、并发出有关控制信号实现这个功能的过程。
总线接口单元BIU负责从存储器取出这个指令代码,送入指令队列。执行单元EU从指令队列中获得预先取出的指令代码进行运算和传递等操作。具体如下图所示:
指令预取
8086处理器维护着长度为6字节的指令队列,该队列按照“先进先出”FIFO(First In First Out)的方式进行工作。
指令的读取操作在BIU单元实现,而指令的执行阶段在EU单元完成。它们互相独立且可并行操作。
其中指令队列如果空缺,BIU会自动填补空缺,当程序不按顺序执行,BIU会废除已取出的指令而重新取指形成新的指令队列。
由于要译码执行的指令已经预取到了处理器内部的指令队列,所以 8086 不需要等待取指操作就可以从指令队列获得指令进行译码执行。
寄存器
处理器内部需要高速存储单元,用于暂时存放程序执行过程中的代码和数据,这些存储单元被称为寄存器(Register)。处理器内部设计有多种寄存器,每种寄存器还可能有多个,从应用的角度可以分成两类:透明寄存器和可编程寄存器。
透明寄存器:有些寄存器对应用人员来说不能通过指令直接编程控制,所以称之为透明寄存器。
可编程寄存器:底层语言程序员需要掌握可编程(Programmable)寄存器。它们具有引用名称、供编程使用。
其中可编程寄存器又可以划分为两种:
通用寄存器:在处理器中数量较多、使用频度较高,具有多种用途。比如存放指令需要的数据等。
专用寄存器:各自只用于特定目的。比如记录将要执行指令的主存地址、标志寄存器保存指令执行的辅助信息。
8086的寄存器有8个16位通用寄存器、4个16位段寄存器、1个16位标志寄存器和1个16位指令指针寄存器:
通用寄存器
通用寄存器(General-Purpose Register)一般是指处理器最常使用的整数通用寄存器,可用于保存整数数据、地址等。
8086 处理器的 8 个 16 位通用寄存器,分别被命名为:AX、BX、CX、DX、SI、DI、BP和SP。
其中前4个通用寄存器AX、BX、CX和DX还可以进一步分成高字节H(High)和低字节L(Low)两部分。
所以前4个寄存器又有8个8位通用寄存器:AH和AL、BH和BL、CH和CL、DH和DL。
通用寄存器的用途很多,可以保存数据、暂存运算结果,也可以存放存储器地址、作为变量的指针。
名称 | 中英文含义 | 作用 |
---|---|---|
AX | 累加器(Accumulator) | 使用频率最高,用于算术、逻辑运算以及与外设传送信息等 |
BX | 基址寄存器(Base) | 常用作存放存储器地址,以方便指向变量或数组中的元素 |
CX | 计数器(Counter) | 常用作为循环操作等指令中的计数器 |
DX | 数据寄存器(Data) | 可用来存放数据,中输入输出指令存放外设端口地址 |
SI | 源变址寄存器(Source Index) | 用于指向字符串或数组的源操作数 |
DI | 目的变址寄存器(Destination Index) | 用于指向字符串或数组的目的操作数 |
BP | 基址指针寄存器(Base Pointer) | 默认情况下指向程序堆栈区域的数据,主要用于中子程序中访问通过堆栈传递的参数和局部变量 |
SP | 堆栈指针寄存器(Stack Pointer) | 专用于指向程序堆栈区域顶部的数据,中涉及堆栈操作的指令中会自动增加或减少 |
许多指令需要表达两个操作数(操作对象,例如加法指令的被加数以及加法结果):
源操作数是指被传送或参与运算的操作数(例如:加法的被加数)。
目的操作数是指保存传送结果或运算结果的操作数(例如:加法的和值结果)。
SI和DI是变址寄存器,常通过改变寄存器表达的地址指向数组元素。SI常用于指向源操作数,而DI常用于指向目的操作数。
堆栈(Stack)是一个特殊的存储区域,它采用先进后出FILO的操作方式存取数据。
BP和SP是指针寄存器,用于指向堆栈中的数据。它会随着处理器执行有关指令而自动增大或减小。
标志寄存器
标志(Flag)用于反映指令执行结果或控制指令执行形式。处理器中用一个或多个二进制位表示一种标志,其0或1的不同组合表达标志的不同状态。
Intel 8086支持的9个标志,分为状态标志和控制标志两类,采用一个16位的标志寄存器FLAGS保存:
状态标志是最基本的标志,用于记录指令执行结果的辅助信息。主要包括加减运算和逻辑运算指令。
状态标志有6个,处理器主要使用其中5个构成,它们从低位到高位分别是:
进位标志CF(Carry Flag)
奇偶标志PF(Parity Flag)
调整标志AF(Adjust Flag)
零标志ZF(ZeroFlag)
符号标志SF(Sign Flag)
溢出标志OF(Overflow Flag)
控制标志用于控制处理器执行指令的方式,可由程序根据需要用相关指令设置。
8086的控制标志有3个,它们分别是:
方向标志DF(Direction Flag),仅用于串操作指令中,控制地址的变化方向;
中断允许标志IF(Interrupt-enable Flag),或简称中断标志,用于控制外部可屏蔽中断是否可以被处理器响应;
陷阱标志TF(Trap Flag),也常称为单步标志,用于控制处理器是否进入单步操作方式。
指令指针寄存器
程序的指令存放最主存储器中,处理器用专用寄存器表示将要执行的指令最主存的位置,这个位置用存储器地址表示。
最8086处理器中,这个存储器地址保存最16位指令指针寄存器IP(Instruction Pointer)中。
指令指针寄存器IP是一个专用寄存器,具有自动增量的能力。处理器执行完一条指令, IP就加上该指令的字节数,指向下一条指令,实现程序的顺序执行。需要实现分支、调用等操作时需要修改 IP,它的改变将引起程序转移到指定的指令执行。
IP寄存器不能像通用寄存器一样直接赋值修改,需要执行控制转移指令(如跳转、分支、调用和返回指令)、出现中断或异常时被处理器赋值而相应改变。
段寄存器
段寄存器是因为对内存的分段管理而设置的。计算机需要对内存分段,以分配给不同的程序使用。
对应用程序来说,主要涉及3类基本段:
存放程序中指令代码的代码段(CodeSegment)
存放当前运行程序所用数据的数据段(Data Segment)
指明程序使用的堆栈区域的堆栈段(Stack Segment)
段其实是主存的一个连续区域,为了表面段最主存中的位置,8086处理器设计有4个16位段寄存器:
代码段寄存器CS,堆栈段寄存器SS,数据段寄存器DS和附加段寄存器ES (Extra Segment)
注意:附加段也是用于存放数据的数据段,专为处理数据串设计的串操作指令必须使用附加段作为其目的操作数的存放区域。
存储器组织
个人计算机主板上的主存条和一个ROM芯片构成主存储器,保存正在运行使用的指令和数据。
存储单元和存储单位
主存储器被划分成许多存储单元,每个存储单元都有一个顺序号码,称为存储单元地址或存储器地址(Memory Address)。
主存储器的每个存储单元具有一个地址,保存一个字节(8个二进制位)的信息,这称为字节编址(Byte Addressable),也直译为字节可寻址,因为通过一个存储器地址可以访问到一个字节信息。
计算机由二进制机器码组成,其中8个二进制位组成一个字节(Byte),常用大写字母B表示。
位编号由右向左(由低位向高位)从0开始递增计数为D0~D7,如下图所示:
其中,二进制数据的右边为最低位,左边为最高位:
右边最低位称为最低有效位LSB(Least Significant Bit)
左边最高位称为最高有效位MSB(Most Significant Bit),对应字节、字、双字长度的数据。
主存储器使用字节作为基本存储单位,也就是\(2^{10}=1024\)的二进制倍数关系,而硬盘或U盘厂商则使用\(10^3\)倍数关系。
物理地址和逻辑地址
主存条和ROM芯片构成的主存储器需要处理器通过总线进行访问,被称为物理存储器。
物理存储器的每个存储单元有一个唯一的地址,就是物理地址(Physical Address)。物理地址空间从0开始顺序编排,直到处理器支持的最大存储单元。
二进制位有0和1两种状态,即2(=\(2^1\))个编码;那么,2位有00、01、10和11共4(\(2^2\))个编码,以此类推可以得到N位有\(2^N\)个编码。
8086处理器具有20位地址总线,那么它支持\(2^{20}\),即1M个存储单元。而每个存储单元保存一个字节,所以8086可以支持1MB存储器容量,其物理地址空间是0 ~ \(2^{20} - 1\)。
地址(编号)习惯用十六进制数表达,20位数字信号对应二进制20位,可以用5位十六进制数表达为:00000H~FFFFFH,如下图所示:
由于8086处理器只有16位寄存器,不能完整保存20位物理地址,而使用16位表示存储器地址,可以表达的存储器容量是64KB(\(2^{16}\)字节),范围是:0000H~FFFFH。
8086处理器将1MB物理存储器空间分成许多不超过64KB的区域管理,这种区域称为段(Segment)。段用于8086内部和程序设计中,所以常被称为逻辑段。
8086处理器规定每个段低4位只能是全为0的物理地址,也就是能被16整除的地址,表示为:XXXX0H
,此时低4为都是0的情况可以省略,那么20位物理地址就可以只表达高16位。
所以,编程中使用的逻辑地址(Logical Address),它包括段基地址和偏移地址,都可以使用 16 位表示。
段基地址确定该段在主存中的起始地址。以段基地址为起点,段内的位置可以用距离该起点的位移量表示,称为偏移地址(Offset)。
逻辑地址使用英文冒号":"来分割段基地址和偏移地址:段基地址:偏移地址.
所以最8086处理器中逻辑地址转换为物理地址的方式如下:
段基地址左移4位(十六进制一位) + 偏移地址 = 20位物理地址
注意:同一个物理地址可以有多个逻辑地址,但是存储单元只能有一个物理地址。
应用程序的基本段
8086有四种类型的逻辑段来实现存储器的分段管理,有4个段寄存器保存对应的段基地址(保存高16位)。
分段管理存储空间属于模块化思想,英语程序通常需要使用三种类型的段:
代码段、堆栈段和数据段,8086还设计有一个属于数据段类型的附加段。
程序指令代码必须安排最代码段,否则无法正常执行。
解析:程序利用代码段寄存器CS获得当前代码段的段基地址,指令指针寄存器IP保存代码段中指令的偏移地址。处理器利用CS:IP的方式取得下一条需要执行的指令。
程序使用的堆栈(临时存放数据的区域)一定在堆栈段。
解析:程序利用SS获得当前堆栈段的段基地址,堆栈指针寄存器SP保存堆栈栈顶的偏移地址。处理器利用SS:SP操作堆栈数据。
存储器的分段管理
8086 规定段基地址低 4 位均为 0,每段最大不超过 64KB。但是每段可以不是64KB,它们可以完全分开、部分重叠、或完全重叠。各段的内容是不允许发生冲突的。
图中a是各段独立分配的示例,各段均占64KB字节范围,互相独立。
图中b是互相重叠段的分配示例。各段大小应根据实际需要来分配,可以重叠。