0%

x86指令体系中的寄存器组

前言:学习8086指令体系中的寄存器组

首先,寄存器是什么?

img

我们通过CPU构造来引入。

这是CPU内部的构造。从逻辑上,CPU可以分为三个模块,分别是控制单元运算单元

存储单元,三者由CPU内部总线连接起来。

可以将CPU工作分为5个阶段:取指令指令译码执行指令访存取数结果写回

取指令:将内存中的指令读取到CPU中寄存器,程序寄存器用于存储下一条指令所在的地址。

指令译码:指令译码器按照预定的指令格式,对取回的指令进行拆分和解释,识别区分不同指令类别以及各种获取操作数的方法。

执行指令:完成指令中各种操作,实现指令具体的操作。

访问取数:根据指令的需要,可能需要从内存中提取数据,所以需要根据指令地址,得到操作数在主存中的地址,并从主存中获取该操作数用于运算。

结果写回:将执行指令阶段的运行结果数据写回到CPU的内部寄存器中,一边后续的指令快速读取。


可以看出,CPU工作的过程中离不开寄存器,它具有存储数据的功能,接下来我们详细介绍

img

寄存器在读取数据的速度是非常快的。我们以intel 8086处理器为例分析,8086

处理器是x86架构的前身。在8086CPU中,地址底线达到20根,最大寻址能力可以达到2^20次幂也就是1MB的寻址能力。

8086的内部结构

8086的寄存器

从这幅图中,我们大概可以将寄存器分为通用寄存器,段寄存器,控制寄存器。


通用寄存器

通用寄存器在处理器中数量较多,使用频率较高,具有多种用途。通用寄存器主要分为三种:数据寄存器,变址寄存器,指针寄存器。还有标志寄存器和指令指针。

8086处理器有8个16位通用寄存器:AX、BX、CX、DX、SI、DI、BP、SP

在这里插入图片描述

前四个通用寄存器主要是用来储存数据。8086CPU的上一代是8080,8080是一类8位的CPU,为了保证兼容性,8086在8080上做了小的修改,这些都是由两个独立的8位寄存器组成。img

以AX为例,AL是AX的低8位,AH是AX的高八位。同理可得,EAX、EBX、ECX、EDX这些32位数据寄存器中,AX、BX、CX、DX分别是对应的低16位。

8086可以存储两种类型的数据:

1、字节(BYTE):一个字节由8bit组成。

2、字(WORD):字是由指令集或处理器硬件作为单元处理的固定大小的数据,对于intel来说,一个字长就是两个字节。对于不同指令集架构来说,计算机一次能处理的数据不同的,大小用字体现。


AX寄存器

AX寄存器又叫做累加器,主要用作算数,逻辑运算,以及与外设传递信息。

AX寄存器相比于其他的寄存器又有点特殊:

DIV 是 8086 CPU 中的除法指令。
MUL 是 8086 CPU 中的乘法指令。

BX寄存器

BX寄存器是用来寻址,即寻址物理内存地址。在计算存储器地址时,它经常用作基址寄存器;在XLAT指令中提供被查表格中源操作数的间接地址;BX存储基址地址,后结合偏移量有效定位具体的内存地址。实例代码如下:

1
2
3
mov ebx,0x1000 ;将基址地址存储到ebx寄存器中
mov esi,2 ;将偏移量(数组索引)存储到esi寄存器
mov eax,[ebx + esi*2] ;访问数组元素,假设每个元素占两个字节

CX寄存器

CX寄存器通常用于存储循环计数器(Loop Counter)。在串操作时用作串长计数器;在汇编语言编程中,用CX存储循环计数,用代码举例:

1
2
3
4
5
6
7
8
9
10
assume cs:code  ;将代码段与代码寄存器CS相关联,使汇编器知道接下来的代码放在叫做code的代码段中

code segment ;定义一个代码段的开始
mov eax,2 ;将2存储再eax寄存器中
add eax,eax ;将eax中数组*2然后再存入eax中

mov eax,4c00H ;将立即数4c00H(16进制)存储到eax中,覆盖之前计算到的值4
int 21H ;触发DOS中断21H,根据中断调用号4c00H
code ends ;代码段结束标记
end ;程序结束标记

如此来看,当我们想计算2的几百次幂的时候,重复add eax,eax这串代码显然不显示,这时候就要用到CX寄存器的功能了。

1
2
3
4
5
6
7
8
9
10
11
12
assume cs:code
code segment
mov eax,2

mov ecx,11 ;
s:add eax eax ;s: 定义了标签s,用于循环的开始。
loop s ;循环指令,将标签s处的指令循环执行ecx寄存器中的次数,即执行10次*2的操作

mov eax,4c000H
int 21H
code ends
end

在这个程序中,但执行到loop指令时,CPU会执行两件事:

1、计数器减1

2、判断ECX中从值是否为0,为0则结束循环,不为0则继续下列指令

DX寄存器

DX寄存器又叫做数据寄存器,在寄存器间接寻址中的I/O指令中存放I/O端口的地址;在字乘时存放积的高字节;在字除时提供被除数的高位,并存放余数。


指针寄存器

BP寄存器

BP寄存器(Base Pointer)又叫做基址指针寄存器。用来指示堆栈中某个数据区的偏移地址——基地址,与SS堆栈段寄存器一起形成堆栈中某个存储单元的物理地址。BP可以对堆栈中任意位置的数据进行操作,但不具备SP始终指向堆栈栈顶的含义

下面用代码的方式体现bp在寻址中的作用:

1
2
3
mov ebp,0
mov eax,[ebp] ;将SS:bp代表的内存单元移入eax中
mov eax,cs:[ebp] ;将CS:[bp]代表的内存单元移入eax中

bp不是数据寄存器,也就意味着其不能分割成2个独立的8位寄存器使用

以[…]的方式访问内存单元并且使用bp的,那么如果在指令中没有明确或者说显示的给出段地址时,**段地址则使用默认的SS寄存器中的值(BX,SI,DI会默认使用DS寄存器)**,比如:

DS:[BP]明确给出了段地址位于DS中,所以这里代表的内存单元即是段地址DS偏移量为BP寄存器中的值的内存单元

SP寄存器

SP寄存器(Stack Pointer)又叫做堆栈指针寄存器。堆栈是指内存中开辟一个专用的数据存储区,它具有”先进后出“的存储特性。主要用来保护程序的现场和断点,在子程序中调用和中断操作中使用。

SP用来指出当前堆栈的栈顶的位置,在堆栈指令操作时,由它给出入栈或出栈的数据在栈中的偏移地址与SS堆栈段寄存器一起形栈顶存储单元的物理地址

在8086系统中,堆栈是由高地址向低地址端扩展,即入栈时SP减2.随着入栈数据的增多,堆栈扩展,SP值减小


变址寄存器

顾名思义,变址的含义是内存地址会变动的,也就是说变址寄存器中存放会变动的内存地址。分为SIDI

这两个寄存器与DS数据段寄存器一起用来确定数据段中某一存储单元的物理地址。

这两个寄存器都有自动增量和自动减量功能,用于变址很方便。

在串处理指令中,SI和DI作为隐含的源变址寄存器和目的变址寄存器。此时SI和DS联用DI和ES附加数据段寄存器联用,分别达到在数据段中和在附加段中寻址的目的。

SI寄存器

SI(Source Index)又称源变址寄存器,通常存放要处理的数据的内存的地址。

DI寄存器

DI(Destination Index)又称目的变址寄存器,通常存放处理后的数据的内存地址。

下列代码来实现SI和DI的寻址操作

1
2
3
4
5
6
7
8
9
mov esi,0  ;初始化偏移地址为0
mov eax,[esi] ;初始化偏移地址为0
mov eax,ds:[esi] ;将段地址ds偏移地址为si的内存单元中的值移入ax中
mov eax,ss:[esi] ;将段地址为ss偏移地址为si中内存单元中的值移入ax中

mov edi,0 ;初始化偏移地址为0
mov eax,[edi] ;初始化偏移地址为0
mov eax,ds[edi] ;将段地址ds偏移地址为di的内存单元中的值移入ax中
mov eax,ss:[edi] ;将段地址为ss偏移地址为di中内存单元中的值移入ax中

段寄存器

段寄存器主要有**CS(Code Segment Register,代码段寄存器)SS(Stack Segment Register,堆栈段寄存器)DS(Data Segment Register,数据段寄存器)ES(Extra Segment Register)**,附加段寄存器)四个16位寄存器。

SS寄存器

SS(Stack Segment)又叫做堆栈寄存器。用于存放堆栈段的段地址,只要和SP(Stack Point)堆栈指针寄存器联用对堆栈进行操作。在堆栈指令中会详细讲解这段指令的使用方法。

DS寄存器

DS(Data Segment)又叫做数据寄存器。用于指出当前程序使用的数据所存放段的最低地址,即存放数据段的段基址。这边制作简单的介绍,对于数据在程序中是如何存储的会额外写一篇博客。

ES寄存器

ES(Extra Segment)又叫做附加段寄存器。这附加段寄存器用法比较多:在串操作指令中目的串所在的段;同时也可以当作数据段存放数据所在的段。

CS寄存器

CS(Code Segment)又称代码段寄存器

顾名思义,该代码段是用来存放当前正在运行的程序代码所在段的段基址,表示当前指令代码可以从该段寄存器指定的存储器段中取得,相应的偏移量由IP提供

控制寄存器

控制寄存器分为两个16位的寄存器IP和PSW

IP寄存器

IP(Instruction Pointer)为指令指针寄存器,它用来存放代码段的偏移地址。在程序运行的过程中,它始终指向下一条指令的首地址

它与段寄存器CS联合使用确定下一条指令的物理地址。当这一地址送到存储器后,控制器可以获取下一条要执行的指令,而控制器一旦取得这条指令就马上修改IP的内容,使它指向下一条指令的首地址

PSW寄存器

PSW(Program Status Word)又叫做程序状态字寄存器,或叫做**标志寄存器(FLAGS)**。这是一个存放状态(或称条件码)标志、控制标志的寄存器。

请添加图片描述分为6个状态标志位和3个控制标志位

6个状态标志位:**CF(Carry Flag)AF(Auxiliary Carry Flag)OF(Overflow Flag)ZF(Zero Flag)SF(Sign Flag)PF(Parity Flag)**。

3个控制方向位:**DF(Direction Flag)IF(Interrupt Flag)TF(Trap Flag)**。

下面将详细介绍每个标志位的用途及表现方式。

OF(Overflow Flag)

OF是溢出标志。当我们在进行有符号数的运算的时候,结果超出机器能表示的范围就叫溢出(8位大于+127或小于-128、16位小于-32768或大于+32767),此时OF的值置1,否则置0

溢出时,表明计算结果不对,一般通过溢出中断处理加以解决。

1
2
mov al,98
add al,99

如这段代码所示,经过计(al)的值为197超出8位的表示范围,所以此时OF=1,值应该为197-256=-59

SF(Sign Flag)

SF是符号标志位。用于记录结果的符号,结果为负时SF位置1,否则置0。(针对有符号数的计算)。

image-20240410195900292

ZF(Zero Flag)

ZF是零标志位当运算结果为0的时候,ZF置1,否则置0。本标注常用于分支程序或者循环程序的转移控制中。

CF(Carry Flag)

CF是进位标志。这个标志位主要是记录运算时从最高位有效位产生的进位/借位值此时CF置1,否则置0。程序通常会根据CF标志位的状态决定程序是否转移。

AF(Auxiliary Carry Flag)

AF是辅助标志进位位。记录运算时第三位(0.5个字节)产生的进位值。有进位则置1,否则为0。

PF(Parity Flag)

PF是奇偶标志位。用来为机器中传送信息时可能产生的代码出错情况提供检验条件。当结果操作数中(二进制)1的个数为偶数时PF位置1,否则置0。

image-20240410204037139

常用于逻辑运算中,在数据传输中可通过检查本标志判定是否产生数据传输错误。

控制标志位
DF(Direction Flag)

DF是方向标志位。用于在串处理指令中控制处理信息的方向。当DF位为1时,每次操作后使变址寄存器SI和DI减小,这样就使串处理从高地址向低地址方向处理;当DF位为0时,则使SI和DI增大,使串处理从低地址向到地址方向处理

TF(Trap Flag)

TF是陷阱标志,又称单步跟踪标志,用于调试时的单步方式操作。当TF位为1时,每条指令执行完后产生陷阱,由系统控制计算机;当TF位为0时,CPU正常工作,不产生陷阱。

IF(Interrupt Flag)

IF时中断标志。当IF为1时,允许CPU响应外部可屏蔽中断请求;否则关闭中断禁止外部中断请求。本标志对外部中断进行管理。