语雀原文链接
文章目录
- 1、CPU组成
- 2、通用寄存器
- 16位寄存器的存储
- 16位寄存器兼容8位
- word 和 byte
- 进位问题
- 3、地址加法器
- 不同的段地址和偏移地址表示同一个物理地址
- 偏移地址的范围
- 一个段的起始地址一定是16的倍数
- 4、CS:IP
- CS IP工作过程
- jmp修改CS:IP
- 5、DS和[address]
- DS和[address]
- mov add sub
1、CPU组成
- 一个CPU由运算器、控制器、寄存器等器件构成,这些器件靠内部总线相连。
- 运算器进行信息处理
- 寄存器进行信息储存
- 控制器控制各种器件进行工作
- 内部总线连接各种器件,在它们之间进行数据的传递
- 内部总线实现CPU内部各个器件之间的联系,外部总线实现CPU和主板上其他器件的联系。
- 不同CPU,寄存器的个数、结构是不相同的。
- 8086CPU有14个寄存器,AX BX CX DX SI DI SP BP IP CS SS DS ES PSW,这些寄存器都是16位二进制。
- 其中4个段寄存器:CS、DS、SS、ES
2、通用寄存器
- AX BX CX DX这四个寄存器通常用来存放一般性的数据,被称为通用寄存器
- 不同CPU的通用寄存器的大小不一样,有8位,16位等等。8086CPU的所有寄存器都是16位,可以存放两个字节
16位寄存器的存储
16位寄存器兼容8位
- 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的低8位(0位7位)构成了AL寄存器,高8位(8位15位构成了AH寄存器。AH和AL寄存器是可以独立使用的8位寄存器。下图展示了16位寄存器及它所分成的两个8位寄存器的数据存储的情况。
word 和 byte
- 字节:byte,一个字节由8个bit组成,可以存放在8位寄存器中
- 字:word,一个字由两个字节组成,分别称为这个字的高位字节和低位字节
- CPU中,用16位寄存器来存储一个字(一个字占据两个内存单元,2字节)。高8位存放高位字节,低8位存放低位字节。
- 上图中,我们从0地址开始存放4E20H,低8位存放20,高8位存放4E。地址0、1可以看成一个字单元。
- 有两个概念可以普及下:
- 0地址单元中存放的字节型数据是20H
- 0地址字单元中存放的字型数据是4E20H
- 上述概念总结如下:任何两个地址连续的内存单单元,N号单元和N+1号单元,可以将它们看成两个内存单元,也可看成一个地址为N的字单元中的高位字节单元和低位字节单元。
进位问题
- 例子1:高位进位
MOV AX,8226H
MOV BX,8226H
ADD AX,BX
AX BX都是16位寄存器,此时AX的值是多少?
答案:8226H + 8226H = 1044CH,但是寄存器只能放16位,AX的值是044CH
- 例子2:低位进位
MOV AX,00C5H
ADD AL,93H
此时AX的值是多少?
答案:AL原始是C5H,加上93H,等于158H,但是AL只是低8位寄存器(作为一个独立的8位寄存器),最高位1会丢失,丢失1也不会给AH,类似最终结果AX=0158(CPU并没有真的丢弃这个值),所以最终的AX=0058
- 例子3:
MOV AX,00C5H
ADD AX,93H
此时AX的值是多少
AX=00C5H + 0093H = 0158H,AX是16位寄存器,能正常进位
- 例子4:指令的操作对象位数不一致,以下都是错误的指令
mov ax,bl 在8位寄存器和16位寄存器之间传送数据
mov bh,ax 在16位寄存器和8位寄存器之间传送数据
mov al, 20000 8位寄存器最大可存放值为255的数据
add al,100H 将一个高于8位的数据加到一个8位寄存器中
3、地址加法器
- 8086CPU有20位地址总线,似乎多余了,内部只能送出16位地址,寻址能力只有64KB,但是实际有1M的寻址能力。
- 8086CPU在内部用两个16位地址合成形成一个20位物理地址
- 两个16位寄存器,一个段地址、另一个偏移地址
- 段地址和偏移地址通过内部总线送入一个地址加法器的部件,合成一个20位的物理地址
- 地址加法器采用物理地址=段地址x16+偏移地址
- 8086CPU要访问地址123C8H(20位长度)的内存单元
- 对于一个16位的CPU,偏移地址范围0000H~FFFFH,如果段地址1000H,则该内存空间的地址范围
1000H * 16 + 0000H ~ 1000H * 16 + FFFFH
10000H ~ 1FFFFH
总共2^16=65536=64KB个内存单元
不同的段地址和偏移地址表示同一个物理地址
- 下面的几个段地址:偏移地址,最终表示的物理地址都是21F60H
偏移地址的范围
- 偏移地址16位,变化范围0FFFFH,最多是216=64KB个内存单元。如果给定一个段地址1000H,则这段寻址范围:10000H1FFFFH
- 一个段的长度最大为64KB
一个段的起始地址一定是16的倍数
- 物理地址=段地址x16+偏移地址
- 16位偏移地址的范围:0~FFFFH
- 所以一个段的起始地址一定是16的倍数
4、CS:IP
CS IP工作过程
- CS和IP是8086CPU中最为关键的寄存器,它指出了当前要读取指令的地址。
- CS寄存器存储段地址,IP寄存器存储偏移地址,CS:IP组成真真的程序入口的物理地址。
- 每读取一次指令,IP=IP+所读取指令的长度,从而指向下一条指令
- 8086CPU工作过程,初始化状态:CS=2000 IP=0000
- 地址加法器
- 输入输出控制电路
- 20位地址总线
- 读取内存中的数据
- 指令缓冲器
- IP增加
- 执行控制器
- AX=0123H
- 读取2000:0003处的指令
- 执行mov bx,0003H,最终BX=0003H
- 读取2000:0006处的指令
- 执行mov ax,bx,最终AX=0003 BX=0003
- 读取2000:0008处的指令,add ax,bx ,01D8
- 执行指令add ax,bx = 01D8,最终结果AX=0003,BX=0003
- 8086CPU工作过程简要概述
(1)从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器:
(2)IP=IP+所读取指令的长度,从而指向下一条指令;
(3)执行指令。转到步骤(1),重复这个过程。
jmp修改CS:IP
- MOV CS,AAAAH 这种写法是错误的,8086CPU不支持将数据直接送入段寄存器,CPU提供了jmp指令用于修改段寄存器的值
- 例子1:mov不能修改段寄存器的值
- 例子2:jmp修改IP寄存器,直接写入数据
- 073F:0100 写入指令 jmp 1234
- 执行后IP=1234
- 例子3:jmp修改IP寄存器,用其他寄存器的值
- 073F:0100 写入指令 mov ax,1111
- 执行后AX=1111
- 073F:0103 写入指令 jmp ax
- 执行后,最终IP的值等于AX的值,IP=1111
- 例子4:jmp同时修改CS:IP寄存器的值
- 073F:0100 写入指令 jmp 0700:2222
- 执行后 CS=0700 IP=2222
5、DS和[address]
DS和[address]
- [address]表示内存单元的偏移地址,8086CPU自动取DS寄存器中的数据为段地址
- 例子1
- 073F:0100 写入指令 mov ax,[011E]
- 执行后mov ax,[011E],就是将DS作为段地址 011E作为偏移地址,073F:011E的值放到AX寄存器中
- 此时073F:011E(低8位)存储2E,073F:011F(高8位)存储07
- 最终结果AX=072E
- 例子2
- 例子3
mov add sub
- mov指令访问内存单元时,mov指令只给出单元的偏移地址,段地址默认在DS寄存器中
- mov指令可以有以下几种形式
mov 寄存器,数据 比如:mov ax,8
mov 寄存器,寄存器 比如:mov ax,bx
mov 寄存器,内存单元 比如:mov ax,[0]
mov 内存单元,寄存器 比如:mov [0],ax
mov 寄存器,内存单元 比如:mov ds,[0]
mov 段寄存器,寄存器 比如:mov ds,ax
mov 寄存器,段寄存器 比如:mov ax,ds