通过改变各种寄存器中的内容来实现对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这四个寄存器通常用来存放一般性的数据,称为通用寄存器
  • 8086CPU的上一代CPU中的寄存器都是8位的,为了保证兼容,8086CPU的四个通用寄存器都可分为两个可独立使用的8位寄存器来用
    • AX:AH(高8位,8~15位)、AL(低8位,0~7位)
    • BX:BH、BL
    • CX:CH、CL
    • DX:DH、DL

数据:18

二进制:10010

在寄存器AX中的存储

1(4位)0(3位)0(2位)1(1位)0(0位)

字在寄存中的存储

出于对兼容性的考虑,8086CPU可以一次性处理遗下两种尺寸的数字

  • 字节
    • byte
    • 一个字节由8个bit组成
    • 可以存在8位寄存器中
    • word
    • 一个字由两个字节组成
    • 这两个字节分别称为这个字的高位字节和低位字节

一个字可以存在一个16位寄存器中,高位字节和地位字节就存在这个寄存器的高8位寄存器和低8位寄存器中。

十进制:20000

二进制:100111000100000

AX:100111000100000

AH:1001110(高位字节)

AL:00100000(低位字节)

书写习惯:

十六进制:Hexadecimal,前缀0x,后缀H

十进制:decimal,前缀\,后缀D

八进制:Octal,前缀0,后缀O

二进制:Binary,前缀0b,后缀B

汇编指令

书写汇编指令不区分大小写。

练习

程序段中的指令 执行后AX中的数据 执行后BX中的数据
mov ax,001AH 001AH 0000H
mov bx,0026H 001AH 0026H
add al,bl 0040H 0026H
add ah,bl 2640H 0026H
add bh,al 2640H 4026H
mov ah,0 0040H 4026H
add al,85H 00C5H 4026H
add al,93H ? 4026H

指令执行后AX中的数据为多少?

指令 AH AL BH BL
mov ax,001AH 00000000 00011010 00000000 00000000
mov bx,0026H 00000000 00011010 00000000 00100110
add al,bl 00000000 01000000 00000000 00100110
add ah,bl 00100110 01000000 01000000 00100110
add bh,al 00100110 01000000 01000000 00100110
mov ah,0 00000000 01000000 01000000 00100110
add al,85H 00000000 11000101 01000000 00100110
add al,93H 00000000 01011000 01000000 00100110

解答:AX=AH+AL=00000000+01011000=0058H

分析:程序段中最后一条指令add al,93H,执行前,al中的数据为C5H(11000101),相加后所得的值为158H(101011000),但是al为8位寄存器,只能存放两位十六进制的数据,所以最高位的1丢失(8位寄存器中不能保存),ax中的数据为:0058H。

执行add al,93H时,al是作为一个独立的8位寄存器来使用的,和ah没有关系,CPU在执行这条指令时认为ah和al是两个不相关的寄存器,进行的是8位运算。

如果执行add ax,93H,低八位的进位会存储在ah中,CPU在执行这条指令时认为只有一个16位寄存器ax,进行的是16位运算。


在进行数据传送或运算时,要注意指令的两个操作对象的位数应当是一致的。

1
2
3
4
5
6
7
8
9
10
11
12
;以下为正确指令
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可以有不同的形成物理地址的方式,接下来讨论的是8086CPU如何内部形成内存单元的物理地址。

16位结构的CPU

16位结构(16位机、字长为16位)描述了一个CPU具有下面几方面的结构特性

  • 运算器一次最多可以处理16位的数据
  • 寄存器的最大宽度为16位
  • 寄存器和运算器之间的通路位16位

8086CPU给出物理地址的方法

8086有20位地址总线,能达到1MB寻址能力,但又是16位结构,从内部一次性处理、传输、暂时存储的地址位16位。从它的内部结构看,如果将地址从内部简单的发出,那么只能送出16位的地址,表现出的寻址能力只有64KB。

8086采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。

8086CPU要读写内存时:

  • 16位段地址+16位偏移地址
  • 通过内部总线送入地址加法器(段地址左移4位+偏移地址)
  • 合成20位物理地址
  • 通过内部总线送入输入输出控制电路
  • 通过内部总线送入地址总线
  • 传入内存

关于进制:

一个数据的二进制形式左移1位,相当于该数乘以2

一个数据的二进制形式左移N位,相当于该数乘以2的N次方

一个数据的十六进制形式左移1位,相当于该数乘以16;

一个数据的十进制形式左移1位,相当于该数乘以10

一个X进制的数据左移1位,相当于该数乘以X

段的概念

内存并没有分段,段的划分来自于CPU。8086CPU物理地址计算方式使得可以用分段的方式来管理内存。

假设10000H~100FFH的内存单元组成一个段,该段的起始地址(基础地址)位 10000H,段地址位1000H,大小为100H;也可以认为10000H~1007FH、10080H~100FFH的内存单元组成两个段,它们的起始地址(基础地址)为:10000H和10080H,段地址为1000H和1008H,大小都为80H。

可以根据需要,将地址连续、起始地址为16的倍数的一组内存单元定义为一个段。

段寄存器

  • 段地址在8086CPU的段寄存器中存放。
  • 8086CPU由4个段寄存器:CS、DS、SS、ES。
  • 当8086CPU要访问内存时由这4个段寄存器提供内存单元的段地址。

CS和IP

  • CS和IP时8086CPU中两个最关键的寄存器,它们只是了CPU当前要读取指令的地址。

  • CS:代码段寄存器

  • IP:指令指针寄存器
  • 8086CPU的工作过程

    • 在8086CPU中,任何时刻,CPU将CS:IP指向的内容当做指令执行,读取的指令进入指令缓冲器
    • IP=IP+所读取指令的长度,从而指向下一条指令
    • 执行指令
  • 在8086CPU加电启动或复位后(CPU刚开始工作时),CS=FFFFH,IP=0000H,也就是说,8086CPU刚启动时,CPU从内存FFFF0H单元中读取指令执行

CPU根据什么将内存中的信息看作指令?

CPU将CS:IP指向的内存单元中的内容看作指令,用它们合成指令的物理地址,到内存中读取指令码,执行。

如果内存中的一段信息曾被CPU执行过的话,那么,它所在的内存单元必然被CS:IP指向过

修改CS、IP的指令

  • 程序员可以通过改变CS、IP中的内容来控制CPU执行目标指令

  • 能够改变CS、IP的内容的指令被统称为转移指令

  • 最简单的可以修改CS、IP的指令:jmp指令

  • 若想同时修改CS、IP的内容,可用jmp 段地址:偏移地址指令完成。

    • 用指令中给出的段地址修改CS,偏移地址修改IP
1
2
3
4
jmp 2AE3:3
;执行后:CS=2AE3H,IP=0003H,CPU将从2AE33H处读取指令
jmp 3:0B16
;执行后:CS=0003H,IP=0B16H,CPU将从00B46H处读取指令
  • 仅修改IP的内容,可用jmp 某一合法寄存器指令完成
    • 用寄存器中的值修改IP
1
2
3
4
5
6
7
;指令执行前:ax=1000H,CS=2000H,IP=0003H
jmp ax
;指令执行后:ax=1000H,CS=2000H,IP=1000H

;指令执行前:bx=0B16H,CS=2000H,IP=0003H
jmp bx
;指令执行后:bx=0B16H,CS=2000H,IP=0B16H

代码段

  • 对于8086PC机,在编程时,可以根据需要,将一组内存单元定义为一个段。

  • 假设将长度为N(N<=64KB)的一步代码,存在一组地址连续、起始地址为16的倍数的内存单元中,可以认为这段内存时用来存放代码,从而定义了一个代码段。

  • 这仅仅是在编程时的一种安排,CPU并不会由于这种安排,就自动地将定义的代码段中的指令当做指令来执行。

  • 所以,要让CPU还行放在代码段中的指令,必须要将CS:IP指向所定义的代码段中的第一条指令的首地址。