寄存器是CPU的重要组成部分,代码层的操作基本都和寄存器相关。
一、 寄存器
1.1. CPU构成
对程序员来说,CPU中最主要部件是寄存器,可以通过改变寄存器的内容来实现对CPU的控制。
不同的CPU,寄存器的个数、结构是不相同的(8086是16位结构的CPU)。8086有14个寄存器,都是16位的寄存器,可以存放2个字节。
1.2. 通用寄存器
AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据,称为通用寄存器(有时也有特定用途)。通常,CPU会先将内存中的数据存储到通用寄存器中,然后再对通用寄存器中的数据进行运算。
假设内存中有块红色内存空间的值是3,现在想把它的值加1,并将结果存储到蓝色内存空间:
- CPU首先会将红色内存空间的值放到AX寄存器中:
mov ax,红色内存空间
- 然后让AX寄存器与1相加:
add ax,1
- 最后将值赋值给蓝色内存空间:
mov 蓝色内存空间,ax
AX、BX、CX、DX这4个通用寄存器都是16位的,如下图所示:
上一代8086的寄存器都是8位的,为了保证兼容, AX、BX、CX、DX都可分为2个独立的8位寄存器来使用。H代表高位寄存器,L代表低位寄存器。
1.3. 字节与字
在汇编的数据存储中,有2个比较常用的单位(Int、Double、String等都是高级语言的数据基本类型):
- 字节:byte,1个字节由8bit组成,可以存储在8位寄存器中
- 字:word,1个字由2个字节组成,这2个字节分别称为字的高字节和低字节。
比如数据20000(4E20H,0100111000100000B),高字节的值是78,低字节的值是32。
1个字可以存在1个16位寄存器中,这个字的高字节、低字节分别存储在这个寄存器的高8位寄存器、低8位寄存器中。
1.4. 段寄存器
8086在访问内存时要由相关部件提供内存单元的段地址和偏移地址,送入地址加法器合成物理地址。
是什么部件提供段地址?段地址在8086的段寄存器中存放。
8086有4个段寄存器:CS、DS、SS、ES,当CPU需要访问内存时由这4个段寄存器提供内存单元的段地址:
- CS (Code Segment):代码段寄存器
- DS (Data Segment):数据段寄存器
- SS (Stack Segment):堆栈段寄存器
- ES (Extra Segment):附加段寄存器
二、指令
CS为代码段寄存器,IP为指令指针寄存器(偏移地址),它们指示了CPU当前要读取指令的地址。任意时刻,8086CPU都会将CS:IP
指向的指令作为下一条需要取出执行的指令。
注意:IP只为CS服务。
2.1. 指令的执行过程
通过上面的过程展示,8086CPU的工作过程可以简要描述如下:
- 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器;
- IP = IP + 所读取指令的长度,从而指向下一条指令;
- 执行指令。转到步骤1,重复这个过程。
在8086CPU加电启动或复位后(即CPU刚开始工作时)CS和IP被设置为CS=FFFFH,IP=0000H,即在8086PC机刚启动时,CPU从内存FFFF0H单元中读取指令执行,FFFF0H单元中的指令是8086PC机开机后执行的第一条指令。
在内存或者磁盘上,指令和数据没有任何区别,都是二进制信息。CPU在工作的时候把有的信息看做指令,有的信息看做数据,为同样的信息赋予了不同的意义。
例如,内存中的二进制信息1000100111011000,计算机可以把它看作大小为89D8H的数据来处理,也可以将其看作指令mov ax, bx
来执行。
1 | 1000100111011000 -> 89D8H(数据) |
CPU根据什么将内存中的信息看做指令?CPU将CS:IP指向的内存单元的内容看做指令。如果内存中的某段内容曾被CPU执行过,那么它所在的内存单元必然被CS:IP指向过。
2.2. jmp指令
CPU从何处执行指令是由CS、IP中的内容决定的,我们可以通过改变CS、IP的内容来控制CPU执行目标指令。
8086提供了一个mov指令(传送指令),可以用来修改大部分寄存器的值,比如
1 | mov ax,10 |
但是,mov指令不能用于设置CS、IP的值,8086没有提供这样的功能。
8086提供了另外的指令来修改CS、IP的值,这些指令统称为转移指令,最简单的是jmp指令。
另外,也可以jmp 直接值
来改变IP的值,比如jmp 0100H
。