前言:学习8086指令体系中的寄存器组
首先,寄存器是什么?
我们通过CPU构造来引入。
这是CPU内部的构造。从逻辑上,CPU可以分为三个模块,分别是控制单元
、运算单元
和
存储单元
,三者由CPU内部总线连接起来。
可以将CPU工作分为5个阶段:取指令
、指令译码
、执行指令
、访存取数
、结果写回
。
取指令
:将内存中的指令读取到CPU中寄存器,程序寄存器用于存储下一条指令所在的地址。
指令译码
:指令译码器按照预定的指令格式,对取回的指令进行拆分和解释,识别区分不同指令类别以及各种获取操作数的方法。
执行指令
:完成指令中各种操作,实现指令具体的操作。
访问取数
:根据指令的需要,可能需要从内存中提取数据,所以需要根据指令地址,得到操作数在主存中的地址,并从主存中获取该操作数用于运算。
结果写回
:将执行指令阶段的运行结果数据写回到CPU的内部寄存器中,一边后续的指令快速读取。
可以看出,CPU工作的过程中离不开寄存器,它具有存储数据的功能,接下来我们详细介绍
寄存器在读取数据的速度是非常快的。我们以intel 8086处理器为例分析,8086
处理器是x86架构的前身。在8086CPU中,地址底线达到20根,最大寻址能力可以达到2^20次幂也就是1MB的寻址能力。
从这幅图中,我们大概可以将寄存器分为通用寄存器,段寄存器,控制寄存器。
通用寄存器
通用寄存器在处理器中数量较多,使用频率较高,具有多种用途。通用寄存器主要分为三种:数据寄存器,变址寄存器,指针寄存器。还有标志寄存器和指令指针。
8086处理器有8个16位通用寄存器:AX、BX、CX、DX、SI、DI、BP、SP
前四个通用寄存器主要是用来储存数据。8086CPU的上一代是8080,8080是一类8位的CPU,为了保证兼容性,8086在8080上做了小的修改,这些都是由两个独立的8位寄存器组成。
以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 | mov ebx,0x1000 ;将基址地址存储到ebx寄存器中 |
CX寄存器
CX寄存器通常用于存储循环计数器(Loop Counter)。在串操作时用作串长计数器;在汇编语言编程中,用CX存储循环计数,用代码举例:
1 | assume cs:code ;将代码段与代码寄存器CS相关联,使汇编器知道接下来的代码放在叫做code的代码段中 |
如此来看,当我们想计算2的几百次幂的时候,重复add eax,eax
这串代码显然不显示,这时候就要用到CX寄存器的功能了。
1 | assume cs:code |
在这个程序中,但执行到loop指令时,CPU会执行两件事:
1、计数器减1
2、判断ECX中从值是否为0,为0则结束循环,不为0则继续下列指令
DX寄存器
DX寄存器又叫做数据寄存器,在寄存器间接寻址中的I/O指令中存放I/O端口的地址;在字乘时存放积的高字节;在字除时提供被除数的高位,并存放余数。
指针寄存器
BP寄存器
BP寄存器(Base Pointer)又叫做基址指针寄存器。用来指示堆栈中某个数据区的偏移地址——基地址,与SS堆栈段寄存器一起形成堆栈中某个存储单元的物理地址。BP可以对堆栈中任意位置的数据进行操作,但不具备SP始终指向堆栈栈顶的含义。
下面用代码的方式体现bp在寻址中的作用:
1 | mov ebp,0 |
bp不是数据寄存器,也就意味着其不能分割成2个独立的8位寄存器使用。
当以[…]的方式访问内存单元并且使用bp的,那么如果在指令中没有明确或者说显示的给出段地址时,**段地址则使用默认的SS寄存器中的值(BX,SI,DI会默认使用DS寄存器)**,比如:
DS:[BP]明确给出了段地址位于DS中,所以这里代表的内存单元即是段地址DS,偏移量为BP寄存器中的值的内存单元。
SP寄存器
SP寄存器(Stack Pointer)又叫做堆栈指针寄存器。堆栈是指内存中开辟一个专用的数据存储区,它具有”先进后出“的存储特性。主要用来保护程序的现场和断点,在子程序中调用和中断操作中使用。
SP用来指出当前堆栈的栈顶的位置,在堆栈指令操作时,由它给出入栈或出栈的数据在栈中的偏移地址,与SS堆栈段寄存器一起形栈顶存储单元的物理地址。
在8086系统中,堆栈是由高地址向低地址端扩展,即入栈时SP减2.随着入栈数据的增多,堆栈扩展,SP值减小。
变址寄存器
顾名思义,变址的含义是内存地址会变动的,也就是说变址寄存器中存放会变动的内存地址。分为SI和DI。
这两个寄存器与DS数据段寄存器一起用来确定数据段中某一存储单元的物理地址。
这两个寄存器都有自动增量和自动减量功能,用于变址很方便。
在串处理指令中,SI和DI作为隐含的源变址寄存器和目的变址寄存器。此时SI和DS联用,DI和ES附加数据段寄存器联用,分别达到在数据段中和在附加段中寻址的目的。
SI寄存器
SI(Source Index)又称源变址寄存器,通常存放要处理的数据的内存的地址。
DI寄存器
DI(Destination Index)又称目的变址寄存器,通常存放处理后的数据的内存地址。
下列代码来实现SI和DI的寻址操作
1 | mov esi,0 ;初始化偏移地址为0 |
段寄存器
段寄存器主要有**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 | mov al,98 |
如这段代码所示,经过计(al)的值为197超出8位的表示范围,所以此时OF=1,值应该为197-256=-59
SF(Sign Flag)
SF是符号标志位。用于记录结果的符号,结果为负时SF位置1,否则置0。(针对有符号数的计算)。
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。
常用于逻辑运算中,在数据传输中可通过检查本标志判定是否产生数据传输错误。
控制标志位
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响应外部可屏蔽中断请求;否则关闭中断禁止外部中断请求。本标志对外部中断进行管理。