文章目录
第二章 寄存器
一个典型的CPU由运算器,控制器,寄存器等器件构成,这些器件靠内部总线连接(前一章的总线相对CPU内部是外部总线)
CPU中:运算器进行信息处理;寄存器进行信息存储;控制器控制器件工作;内部总线连接器件并进行数据传送
- 对汇编程序员来说,CPU中主要部件是寄存器,因为寄存器可以通过指令读写,进而实现对CPU的控制
- 8086CPU有14个寄存器:AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW
2.1 通用寄存器
8086所有的寄存器都是16位的,可以存放两个字节;AX、BX、CX、DX这四个寄存器用来放一般性的数据,被称为通用寄存器
- 一个16位寄存器可以存放一个16位的数据
- 8086CPU上一代CPU寄存器都是8位的,为了保证兼容,AX、BX、CX、DX这四个寄存器可以分为两个可以独立使用的8位寄存器使用(16=8+8)

2.2 字在寄存器中的存储
8086CPU可以一次性处理以下两种尺寸的数据:
- 字节:Byte,一个Byte由8个bit组成,可以存放在8位寄存器中
- 字:word,一个word由2个Byte组成,分别称为高位字节和低位字节
一个字型数据存放在AX寄存器中,AH存储高8位,AL存储低8位
- AH和AL中的数据既可以看成一个字型数据的高8位和低8位
- 也可以看成两个独立的字节型数据

2.3 几条汇编指令
在写一条汇编指令或一个寄存器的名称时不区分大小写
问题2.1:指令执行后AX中数据是多少?
- ax是16位寄存器,只能存放4位十六进制数据,最高位的1不能在ax中保存,AX中数据位044CH

问题2.2:指令执行后AX中的值是多少?
- al是8位寄存器,只能存放2位16进制数据,最高位的1丢失(不能在8位寄存器中保存,不是CPU真丢弃这个值),add al,93h进行的是8位运算
2.4 物理地址
CPU访问内存单元时要给出内存单元的地址,所有内存单元构成的空间是一个一维线性空间
- 每一个内存单元在这个空间中都有唯一的地址,这就是物理地址
- CPU通过==地址总线送入存储器的必须是一个的内存单元的物理地址==
送入存储器之前,CPU内部会先形成一个物理地址
2.5 16位结构的CPU
8086是16位结构的CPU,什么是16位结构的CPU呢?有以下的结构特性
- 运算器一次最多可以处理16位的数据
- 寄存器最大宽度为16位
- 寄存器和运算器之间的通路为16位
内存单元的地址在送上地址总线之前,必须在CPU中处理、传输、暂时存放
2.6 8086CPU给出物理地址的方法
- 8086CPU有20位地址总线,可以传送20位地址,达到1MB的寻址能力
- 但8086CPU是16位架构,内部一次处理,传输,暂时存储的地址只有16位,表现出的寻址能力只有64KB
8086CPU在内部用两个16位地址形成一个20位的物理地址,通过地址加法器实现

以下8086CPU读写内存的过程非常重要,一定熟读多次并理解记忆:
- CPU中相关部件给出两个16位地址,一个为段地址,一个为偏移地址
- 段地址和偏移地址通过内部总线送入地址加法器
- 两个16位地址被合成一个20位物理地址
- 输入输出控制电路将20位物理地址送上地址总线
- 20位物理地址被地址总线传送到存储器
- 地址加法器合成物理地址:物理地址=段地址*16+偏移地址
“段地址*16”也会被称为左移四位,这里的位是二进制的位

我们可以发现:
- 一个数据的二进制形式左移一位相当于该数据乘2
- 二进制形式左移N位相当于该数据乘 2 n 2^n 2n
- 地址加法器完成段地址*16就是通过左移四位得到的
我们可以用常用的十进制形式再想想:
- 一个数据的十进制形式左移一位相当于乘10(这个应该是比较好理解的)
- 那么一个数据的十六进制形式左移一位相当于乘16
- 一个X进制是数据左移一位相当于乘X
2.7 ”段地址*16+偏移地址=物理地址“的本质含义
-
本质含义就是:CPU在访问内存时,用一个基础地址(段地址*16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址(这里讨论是具体的8086CPU的段地址和偏移地址的本质含义,不是归纳总结)
-
8086CPU中,段地址*16可看作是基础地址
第一个比喻:说明“基础地址+偏移地址=物理地址”
第二个比喻:纸条通信但有限制
我们现在不能写四位纸条(或者就说8086CPU不会直接写“四位数纸条”),就通过两张三位纸条来表达超出三位纸条本身更多的信息
2.8 段的概念
- 首先明确:内存没有分段,段的划分来自于CPU
- 8086给出物理地址的方法是:基础地址(段地址*16)+偏移地址=物理地址,让我们可以用分段的方式管理内存
- 认为10000H~100FFH组成一个段,起始地址(基础地址)为10000H,段地址为1000H(左移一位为起始地址),大小为100H
- 也可以认为:10000H~10007FH、10080H-100FFH的内存单元组成两个段;起始地址为10000H和10080H,段地址为:1000H和1008H,大小都为80H
- 段地址*16必然是16的倍数,所以一个段的起始地址必须是16的倍数
- 偏移地址为16位,16位的寻址能力为64KB,一个段的最大长度为64KB
- CPU可以用不同的段地址和偏移地址形成同一个物理地址
- 给定一个段地址,仅通过变化偏移地址来寻址,最多可定位64KB个内存单元
数据在21F60H内存单元中,一般是不这么说的,而是:
- 数据存在内存2000:1F60单元中
- 数据存在内存2000H段中的1F60H单元中
这两种说法都体现出了8086CPU通过两个16位地址合成一个20位物理地址的“特点”
2.9 段寄存器
- 段地址在8086CPU中的段寄存器中存放
- 8086CPU有四个段寄存器:CS、DS、SS、ES
2.10 CS和IP
- CS是代码段寄存器,IP为指令指针寄存器
任何时刻,设CS中内容为M,IP中内容为N,8086CPU从内存:M*16+N开始读取一条指令并执行
- 8086机中,任意时刻,CPU将CS:IP指向的内容当成指令来执行
8086CPU的工作过程如下:
- 从CS:IP指向的内存读取指令(地址加法器、输入输出控制电路),将指令送入指令缓冲器
- IP=IP+读取指令的长度,然后就会指向下一条指令
- 执行指令后重复上述步骤
- 8086CPU在上电启动或复位后,CS和IP会被设置为:CS=FFFFH,IP=0000H,所以FFFF0H单元中的指令是8086PC机开机后执行的第一条指令
2.11 修改CS、IP的指令
- CPU中,我们能用指令读写的部件只有寄存器
- 可以通过改变寄存器中的内容实现对CPU的控制
- CPU执行的指令是由CS、IP中的值决定的
MOV指令被称为传送指令,但8086PC机不支持用MOV指令来修改CS:IP中的值
;想同时修改CS、IP中的内容,可用形如“jmp 段地址:偏移地址来完成”
jmp 2AE3:3 ;执行后,CS=2AE3H,IP=0003H,CPU从2AE33H处读取指令
jmp 3:0B16 ;执行后,CS=0003H,IP=0B16H,CPU从2AE33H处读取指令
- JMP 段地址:偏移地址的功能为:用指令中的段地址修改CS,偏移地址修改IP
; 若想只修改IP的内容,可以用“jmp 某一合法寄存器”完成
jmp ax
jmp bx
- ”jmp 某一合法寄存器“的功能为:用寄存器的值修改IP
- 我们可以这么理解(但是二者不等价):jmp ax和mov IP,ax 这两条的指令的意思意义(但后者不能代替前者)
;问题2.3 CPU初始状态为:CS=2000H,IP=0000H
mov ax,6622H
jmp 1000:3
mov ax,0000
mov bx,ax
jmp bx
mov ax,0123H
mov ax,0000 ;回去了
mov bx,ax
jmp bx
mov ax,0123H ;又回去了
2.12 代码段
对于8086PC机,我们可以根据需要将一组内存单元定义一个段
-
我们可以将长度为N(N<=64KB)的一组代码,存放在一组地址连续,起始地址为16的倍数的内存单元中,可以认为这段内存是来存放代码段,定义了一个代码段
-
但是我们要是想要代码段中的指令被执行,必须使得CS:IP的值指向第一条指令的首地址(代码段是我们这么认为的,CPU并不这么认为,CPU只认CS:IP的值为指令)