通过改变各种寄存器中的内容来实现对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 | ;以下为正确指令 |
物理地址
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将
在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 | jmp 2AE3:3 |
- 仅修改IP的内容,可用
jmp 某一合法寄存器
指令完成- 用寄存器中的值修改IP
1 | ;指令执行前:ax=1000H,CS=2000H,IP=0003H |
代码段
对于8086PC机,在编程时,可以根据需要,将一组内存单元定义为一个段。
假设将长度为N(N<=64KB)的一步代码,存在一组地址连续、起始地址为16的倍数的内存单元中,可以认为这段内存时用来存放代码,从而定义了一个代码段。
这仅仅是在编程时的一种安排,CPU并不会由于这种安排,就自动地将定义的代码段中的指令当做指令来执行。
所以,要让CPU还行放在代码段中的指令,必须要将CS:IP指向所定义的代码段中的第一条指令的首地址。