02.寄存器
寄存器
前言
一个典型的CPU由运算器,控制器,寄存器等器件构成,这些器件靠内部总线连接。简单来说:
- 运算器进行信息处理
- 寄存器进行信息存储
- 控制器控制各种器件进行工作
- 内部总线连接各种器件,在它们之间进行数据的传送
对于汇编程序而言,CPU中的主要部件是寄存器,寄存器是CPU中程序员可以进行指令读写的器件,可以通过改写各种寄存器中内容来实现对CPU的控制
不同的CPU,寄存器的个数,结构是不同的。8086CPU有14个寄存器,每个寄存器有一个名称,这些寄存器是:AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW
通用寄存器
8086的寄存器都是16位的,可以存放2个字节。AX,BX,CX,DX这4个寄存器通常用来存放一般性数据,被称为通用寄存器
为了兼容性考虑,这四个寄存器又可以拆分成两个独立的寄存器:
- AX分为AH和AL
- BX分为BH和BL
- CX分为CH和CL
- DX分为DH和DL
分别表示高8位和低8位
字在寄存器中的存储
出于兼容性的考虑,8086CPU可以处理两种尺寸的数据
- 字节:byte,由8个bit组成,可以存放8位寄存器中
- 字:word,由两个byte组成,分别成为高位字节和低位字节
几条汇编指令
汇编语言的书写不区分大小写
在进行数据传送和运算时,要注意指令的两个操作对象的位数应该是一致的
| 汇编指令 | 控制CPU完成的操作 |
|---|---|
| mov ax, 18 | 将18送入寄存器ax中 |
| mov ah, 78 | 将78送入寄存器ah中 |
| add ax, 8 | 将寄存器ax中值加上8 |
| mov ax, bx | 将寄存器bx中的值送入寄存器ax中 |
| add ax, bx | 将ax和bx中值相加,结果存入ax中 |
以下这些指令是错误的
| 汇编指令 |
|---|
| mov ax, bl |
| mov bh, ax |
| mov al, 2000 |
| add al, 100H |
物理地址
CPU访问内存时,要给出内存单元的地址,所有的内存单元构成一个一维的线性空间,每一个内存单元都有唯一的地址,我们将这个唯一个地址称之为物理地址
CPU通过地址总线送入存储器的地址必须是一个内存单元的物理地址。在CPU向存储器发送物理地址之前,必须现在内部形成这个地址,不同的CPU可以有不同的地址形成方式
16位结构的CPU
什么是16位结构的CPU
概括来讲,16位的CPU具有以下几方面的结构特性
- 运算器一次最多处理16位的数据
- 寄存器的最大宽度为16位
- 寄存器和存储器之间的通路为16位
能够一次性处理,传输,暂时存储的信息的最大长度为16位
8086CPU给出物理地址的方法
8086CPU有20位地址总线,可以传送20位地址,寻址能力是 2^20 ;另一方面,它又是16位的CPU结构,按理里说寻址能力为 2^16,它的内部是如何实现的呢?
8086CPU采用了两个16位地址合成一个20位地址的方法:
- CPU提供两个16位的地址,一个称为段地址,一个称为偏移地址
- 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件
- 地址加法器将两个16位地址合成一个20位物理地址
- 地址加法器通过内部总线将20位物理地址送入输入输出控制电路
- 输入输出电路将20位物理地址送上地址总线
- 20位物理地址被地址总线送入存储器
地址加法器采用 段地址*16+偏移地址的方式生成20位物理地址
段的概念
段的概念不是来自内存,并不是将内存分成一个一个段。段的概念来自于CPU,采用段基址+偏移地址的方式来计算物理地址,使得我们可以通过 段 的形式来管理我们的内存。
段寄存器
CPU采用段基址+偏移地址的方式来计算物理地址,那么是通过什么器件来存储段地址呢?段地址在8086CPU中通过段寄存器存放。8086CPU中有4个段寄存器:CS,DS,SS,ES
CS 和 IP
CS 和 IP 是8086CPU中最为关键的连个寄存器,它们指示了CPU 当前要读取指令的地址。CS 是段寄存器,IP 为指令指针寄存器。
在 8086 PC机上,任何时刻,CPU将读取 CS*16+IP 处的一条指令执行。也可以这样说,8086机中,任意时刻,CPU将CS:IP指向的内容当作指令执行
8086 的 CPU 工作流程简述:
- 从 CS:IP 指向的内存中读取指令,读取的指令进入指令缓冲器
- IP = IP + 所读取的指令的长度,从而指向下一条指令
- 执行指令,转回 步骤1,重复这个过程
第一节中我们说过,指令和数据没有区别,都是二进制数据,CPU在工作时将有的数据看作指令,有的数据看作数据。那么在什么时候看作指令呢?现在我们明白了,CPU将CS:IP指向的数据看作指令
修改CS,IP的指令
前面提到的通用寄存器,我们可以通过 mov 指令修改其内部的值,mov 指令被称之为 传送指令。
那我们是否可以通过 mov 指令来修改 CS 和 IP 寄存器的值呢?
不能,因为没有提供这样的功能。它提供了另一种类型的指令,能够修改 CS,IP 寄存器值的指令,称之为 转移指令。
先介绍一种最简单的转移指令 jmp
jump 2:0a03 -->同时修改cs和ip的值
单独修改 IP 的值
jump 某一个合法寄存器
jump ax -->将 ax 寄存器中值存入 IP 中
代码段
在编写程序时,可以根据需要,将一组内存单元定义为一个段,我们可以将长度为 N(N <= 64kb)的一段代码,存在一组连续的,起始地址为16倍数的内存单元中,我们可以这样认为,这一段内存就是用来存放代码的,从而定义了一个代码段
运行时,我们只需要指定这段代码段的地址到 cs 和 IP 寄存器中, cpu 就会 从内存中取出相应的指令放入指令缓冲器中执行
课后实验
- 安装DosBox
- 使用DosBox进入Debug模式
- Debug模式下各种command的使用
安装DosBox
使用DosBox进入Debug模式

mount c Dosbox安装地址 --> 将Dosbox 挂载到虚拟的C盘
c: --> 进入 虚拟C盘
debug --> 进入debug模式
其实就是运行 Dosbox 安装路径下的 debug.exe 程序
Debug模式下各种command的使用
- 使用 R 命令查看,改变CPU寄存器的内容
- 使用 D 命令查看内存中的命令
- 使用 E 命令改写内存中的内容
- 使用 U 命令将内存中机器指令翻译成汇编指令
- 使用 T 命令执行一条机器指令
- 使用 A 命令以汇编指令的格式在内存中写入一条机器指令
可以自己在电脑上查找指令的使用方法并实验各种command的功能
参考
<<汇编语言第四版>>-王爽
浙公网安备 33010602011771号