【汇编】汇编系列二 - 寄存器和指令

寄存器是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的工作过程可以简要描述如下:

  1. 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器;
  2. IP = IP + 所读取指令的长度,从而指向下一条指令;
  3. 执行指令。转到步骤1,重复这个过程。

在8086CPU加电启动或复位后(即CPU刚开始工作时)CS和IP被设置为CS=FFFFH,IP=0000H,即在8086PC机刚启动时,CPU从内存FFFF0H单元中读取指令执行,FFFF0H单元中的指令是8086PC机开机后执行的第一条指令。

在内存或者磁盘上,指令和数据没有任何区别,都是二进制信息。CPU在工作的时候把有的信息看做指令,有的信息看做数据,为同样的信息赋予了不同的意义。

例如,内存中的二进制信息1000100111011000,计算机可以把它看作大小为89D8H的数据来处理,也可以将其看作指令mov ax, bx来执行。

1
2
1000100111011000 -> 89D8H(数据)
1000100111011000 -> mov ax, bx(程序)

CPU根据什么将内存中的信息看做指令?CPU将CS:IP指向的内存单元的内容看做指令。如果内存中的某段内容曾被CPU执行过,那么它所在的内存单元必然被CS:IP指向过。

2.2. jmp指令

CPU从何处执行指令是由CS、IP中的内容决定的,我们可以通过改变CS、IP的内容来控制CPU执行目标指令。

8086提供了一个mov指令(传送指令),可以用来修改大部分寄存器的值,比如

1
2
3
4
mov ax,10
mov bx,20
mov cx,30
mov dx,40

但是,mov指令不能用于设置CS、IP的值,8086没有提供这样的功能。

8086提供了另外的指令来修改CS、IP的值,这些指令统称为转移指令,最简单的是jmp指令。

另外,也可以jmp 直接值来改变IP的值,比如jmp 0100H