寄存器
一个典型的CPU(此处讨论的不是某一具体的CPU)由运算器、控制器、寄存器(CPU工作原理)等器件构成,这些器件靠内部总线相连。总线,相对于CPU内部来说是外部总线。内部总线实现CPU内部各个器件之间的联系,外部总线实现CPU和主板上其他器件的联系。简单地说,在CPU中:
运算器进行信息处理;
寄存器进行信息存储;
控制器控制各种器件进行工作;
内部总线连接各种器件,在它们之间进行数据的传送。
CPU中的主要部件是寄存器。寄存器是CPU中程序员可以用指令读写的部件。程序员通过改变各种寄存器中的内容来实现对CPU的控制。
不同的CPU,寄存器的个数、结构是不相同的。8086CPU 有14个寄存器,每个寄存器有一个名称。这些寄存器是: AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。
通用寄存器
8086CPU的所有寄存器都是16 位的,可以存放两个字节。AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据, 被称为通用寄存器。
以AX为例,寄存器的逻辑结构如图所示。
一个16位寄存器可以存储一个 16位的数据,数据在寄存器中的存放情况如图所示。
8086CPU的上一代CPU中的寄存器都是8位的,为了保证兼容,使原来基于上代CPU编写的程序稍加修改就可以运行在8086之上,8086CPU 的AX、BX、CX、DX这4个寄存器都可分为两个可独立使用的8位寄存器来用:
AX可分为AH和AL;
BX可分为BH和BL;
CX可分为CH和CL;
DX可分为DH和DL;
以AX为例,8086CPU的16位寄存器分为两个8位寄存器的情况如图所示。
AX的低8位(0位~7位)构成了AL寄存器,高8位(8位~15位)构成了AH寄存器。AH和AL寄存器是可以独立使用的8位寄存器。图展示了16位寄存器及它所分成的两个8位寄存器的数据存储的情况。
字在寄存器的存储
出于对兼容性的考虑,8086CPU 可以一次性处理以下两种尺寸的数据。
字节:记为byte, 一个字节由8个bit组成,可以存在8位寄存器中。
字:记为word, 一个字由两个字节组成,这两个字节分别称为这个字的高位字节和低位字节,如图所示。
一个字可以存在一个16位寄存器中,这个字的高位字节和低位字节自然就存在这个寄存器的高8位寄存器和低8位寄存器中。一个字型数据 20000存在AX寄存器中,在AH中存储了它的高8位,在AL中存储了它的低8位。AH和AL中的数据,既可以看成是一个字型数据的高8位和低8位,这个字型数据的大小是20000;又可以看成是两个独立的字节型数据,它们的大小分别是78和32。
关于数制的讨论
任何数据,到了计算机中都是以二进制的形式存放的。为了描述不同的问题,又经常将它们用其他的进制来表示。比如寄存器AX中的数据是0100111000100000,这就是AX中的信息本身,可以用不同的逻辑意义来看待它。可以将它看作一个数值, 大小是20000。
当然,二进制数0100111000100000本身也可表示一个数值的大小,但人类习惯的是十进制,用十进制20000表示可以使我们直观地感受到这个数值的大小。
十六进制数的一位相当于二进制数的四位,如0100111000100000可表示成: 4(0100)、 E(1110)、2(0010)、0(0000)四位十六进制数。
由于一个内存单元可存放8位数据,CPU中的寄存器又可存放n个8位的数据。也就是说,计算机中的数据大多是由1~N个8位数据构成的。很多时候,需要直观地看出组成数据的各个字节数据的值,用十六进制来表示数据可以直观地看出这个数据是由哪些8位数据构成的。比如20000写成4E20就可以直观地看出,这个数据是由4E和20两个8位数据构成的,如果AX中存放4E20,则AH里是4E,AL里是20。这种表示方法便于许多问题的直观分析。
为了区分不同的进制,在十六进制表示的数据的后面加H,在二进制表示的数据后面加B,十进制表示的数据后面什么也不加。如:可用3种不同的进制表示图中AX里的数据,十进制: 20000, 十六进制: 4E20H, 二进制: 0100111000100000B。
几条汇编指令
通过汇编指令控制CPU进行工作
为了使具有高级语言基础的读者更好地理解指令的含义,有时会用文字描述和高级语言描述这两种方式来描述一条汇编指令的含义。在写一条汇编指令或一 个寄存器的名称时不区分大小写。如: mov ax,18和MOV AX,18的含义相同; bx和BX的含义相同。
CPU执行表 中所列的程序段中的每条指令后,对寄存器中的数据进行的改变。
程序段中的最后一条指令 add ax,bx,在执行前ax和bx中的数据都为8226H,相加后所得的值为: 1044CH, 但是ax为16位寄存器,只能存放4位十六进制的数据,所以最高位的1不能在ax中保存,ax中的数据为:044CH。
程序段中的最后一条指令 add al,93H, 在执行前,al中的数据为C5H,相加后所得的值为: 158H, 但是al为8位寄存器,只能存放两位十六进制的数据,所以最高位的1丢失,ax中的数据为: 0058H。(这里的丢失,指的是进位值不能在8位寄存器中保存,但是CPU并不真的丢弃这个进位值)
注意,此时al是作为一个独立的8位寄存器来使用的,和ah没有关系,CPU在执行这条指令时认为ah和al是两个不相关的寄存器。不要错误地认为,诸如add al,93H 的指令产生的进位会存储在ah中,add al,93H进行的是8位运算。
如果执行add ax,93H, 低8位的进位会存储在ah中,CPU在执行这条指令时认为只有一个16位寄存器ax, 进行的是16位运算。指令add ax,93H执行后,ax 中的值为:0158H。此时,使用的寄存器是16位寄存器ax, add ax,93H相当于将ax中的16位数据00c5H和另一个16位数据0093H相加,结果是16位的0158H。
在进行数据传送或运算时,要注意指令的两个操作对象的位数应当是一致的
mov ax, bx
mov bx, cx
mov ax, 18H
mov al, 18H
add ax, bx
add ax, 20000
等都是正确的指令,而:
mov ax, bl (在8位寄存器和16位寄存器之间传送数据)
mov bh, ax (在16位寄存器和8位寄存器之间传送数据)
mov al, 20000 (8位寄存器最大可存放值为255的数据)
add al, 100H (将一个高于8位的数据加到一个8位寄存器中)
等都是错误的指令,错误的原因都是指令的两个操作对象的位数不一致。
物理地址
CPU访问内存单元时,要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性 空间,每一个内存单元在这个空间中都有唯一的地址,我们将这个唯的地址称为物理地址。
CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址。在CPU向地址总线上发出物理地址之前,必须要在内部先形成这个物理地址。不同的CPU可以有不同的形成物理地址的方式。8086CPU是如何在内部形成内存单元的物理地址的。
16位结构的CPU
我们说8086CPU的上一代CPU(8080、8085)等是 8位机,而8086是16位机,也可以说8086是16位结构的CPU。那么什么是16位结构的CPU呢?
16位结构(16位机、字长为16 位等常见说法,与16 位结构的含义相同)描述了一个CPU具有下面几方面的结构特性。
运算器一次最多可以处理16位的数据:
寄存器的最大宽度为16 位:
寄存器和运算器之间的通路为16位。
8086是16位结构的CPU,这也就是说,在8086内部,能够一次性处理、 传输、暂时存储的信息的最大长度是16位的。内存单元的地址在送上地址总线之前,必须在CPU中处理、传输、暂时存放,对于16位CPU,能一次性处理、传输、暂时存储16位的地址。
当8086CPU要读写内存时:
CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;
段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;
地址加法器将两个16位地址合成为一个20位的物理地址;
地址加法器通过内部总线将20位物理地址送入输入输出控制电路;
输入输出控制电路将20位物理地址送上地址总线;
20位物理地址被地址总线传送到存储器。
地址加法器采用物理地址=段地址x16+偏移地址的方法用段地址和偏移地址合成物理地址。例如,8086CPU 要访问地址为123C8H 的内存单元,此时,地址加法器的工作过程如图所示(图中数据皆为十六进制表示)。