汇编-寄存器

一个典型的CPU通常由运算器/控制器/寄存器等器件组成,这些器件由内部总线相连接,外部总线则实现CPU与主板上其他器件的联系.

其中寄存器是可以由程序员用与指令读写的部件,即程序员通过改变各个寄存器的内容来实现对CPU的控制.

不同类型的CPU,它们的寄存器个数,结构可能是不同的,例如8086CPU有着14个寄存器,分别是:AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DE,ES,PSW.

数据寄存器

32位CPU有4个32位的数据寄存器EAX,EBX,ECX,EDX.并且完全兼容16位CPU的AX,BX,CX,DX数据寄存器.

在16位CPU中,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址,但在32位CPU中,其32位寄存器EAX,EBX,ECX,EDX不仅可传送数据,暂存数据保存算术逻辑运算结果,而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。

16位CPU中有4组是数据寄存器,也简称通用寄存器,分别是AX,BX,CX,DX;而在32位CPU上则有8组数据寄存器;到了64位CPU,则扩展到了16组数据寄存器.

16位CPU的所有寄存器都是16位,分为高8位和低8位.所以一个寄存器可以存放两个字节,连个字节组成一个字,即:
– AX分高AH和低AL;
– BX分高BH和低BL;
– CX分高CH和低CL;
– DX分高DH和低DL;

变址寄存器

32位CPU有2个32位变址寄存器ESI,EDI,完全兼容16位CPU中的SI,DI.对低16位数据的存取,不影响高16位的数据.

变址寄存器主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便.

变址寄存器不可分割成8位寄存器.作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果.它们可作一般的存储器指针使用.在字符串操作指令的执行过程中, 对它们有特定的要求,而且还具有特殊的功能.

指针寄存器

32位CPU有2个32位通用寄存器EBP,ESP,完全兼容16位CPU中的BP,SP.对低16位数据的存取,不影响高16位的数据.

指针寄存器主要用于存放堆栈内存储单元的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便.
指针寄存器不可分割成8位寄存器.作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果.

它们主要用于访问堆栈内的存储单元,并且规定:
– BP 为基指针(Base Pointer)寄存器,用它可直接存取堆栈中的数据;
– SP为堆栈指针(Stack Pointer)寄存器,用它只可访问栈顶.

指令指针寄存器

32位CPU的指令指针为EIP,它的低16位与先前CPU中的IP作用相同.

指令指针EIP/IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量.在具有预取指令功能的系统中,下次要执行的指令通常已被预取到指令队列中,除非发生转移情况.所以,在理解它们的功能时,不考虑存在指令队列的情况.

在实方式下,由于每个段的最大范围为64K,所以,EIP中的高16位肯定都为0.此时,相当于只用其低16位的IP来反映程序中指令的执行次序.

段寄存器

CPU访问某个内存单元时,是需要给出该内存单元的地址数据的,而构成内存单元的存储空间的是一个一维的线性地址.每个内存单元在该线性地址中都有自己的唯一地址,我们称之为物理地址.而CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址.而在此之前,不同CPU有不同生成物理地址的方式.

典型的8086CPU是16位结构的CPU,其含义是:
* 运算器一次最多可以处理16位的数据.
* 寄存器最大宽度为16.
* 寄存器与运算器直接的通路位16.
因此,也就是说8086CPU能够一次性处理/传输/暂存的信息的最大长度位16位.

8086CPU的地址总线有20位,也就是说,最大一次可以传输20位地址,达到1MB的寻址能力.但8086又是16位结构,若只是简单的从内部发出最大的16位地址,则其寻址能力则只有64KB.因此8086CPU在内部使用共两个16位的地址合成一个新的20位物理地址.

所以8086CPU要对内存进行读写时:
1. CPU提供两个16位地址,一个是段地址,一个是偏移地址.
2. 段地址和偏移地址通过内部总线送入地址加法器.
3. 地址加法器将两个地址合成一个20位的物理地址.
4. 地址加法器通过内部总线,将20位物理地址送入I/O控制器.
5. I/O控制器将20位物理地址送入地址总线.
6. 20位物理地址被地址总线传输到存储器.

地址加法器合成物理地址的计算方式如下:

物理地址=段地址x16+偏移地址

其含义就是段地址x16作为一个约定,当基地址使用,而段地址则是在CPU的段寄存器中存放.

8086CPU共有4组段寄存器,分别是:
1. CS: Code Segment Register(代码寄存器) 指向含有程式指令的一个空间
2. DS: Data(数据寄存器) 指向含有全局或静态数据的一個寄存器
3. ES: Extra(附加寄存器)
4. SS: Stack(堆栈寄存器) 指向含有当前程序堆栈的一个空间
在80386系列后,新增了两段寄存器:
5. FS: Extra(附加段寄存器),其值为附加数据段的段值
6. GS: Extra(附加段寄存器),其值为附加数据段的段值
IP则是指令寄存器(相当于偏移地址,有特殊含义).

段地址工作流程如下:
1. 从CS:IP指向的内存单元读取指令,放入指令缓冲器.
2. IP=IP+读取的指令长度,从而再指向下一条指令.
3. 执行指令,再重复步骤 1.
在16位CPU中只有4个段寄存器,因此同一时刻最多只有4个段地址正在被访问;而32位CPU中增加到了6个,即同一时间可访问的段地址增加到了6个.
并且32位CPU有了两个不同的工作方式,且不同方式下的段寄存器的作用是不同的,其规定如下:

实方式(Real Mode):
– 前4个段寄存器CS,DS,ES,SS与先前CPU中的所对应的段寄存器的含义完全一致,内存单元的逻辑地址仍为”段值:偏移量”的形式.为访问某内存段内的数据,必须使用该段寄存器和存储单元的偏移量.

保护方式(Protected Mode):
– 在此方式下,情况要复杂得多,装入段寄存器的不再是段值,而是称为”选择子”(Selector)的某个值.

在CPU加电时,CS和IP被置为CS=FFFFH,IP=0000H,从该地址读取第一条指令.

标志寄存器

1.运算结果标志位:

  • 进位标志CF(Carry Flag): CF主要用来反映运算是否产生进位或借位.如果运算结果的最高位产生了一个进位或借位,那么其值为1;否则其值为0.使用该标志位的情况有:多字(字节)数的加减运算;无符号数的大小比较运算,移位操作,字(字节)之间移位,专门改变CF值的指令等.

  • 奇偶标志PF(Parity Flag): PF用于反映运算结果中”1″的个数的奇偶性.如果”1″的个数为偶数,则PF的值为1.否则其值为0.利用PF可进行奇偶校验检查,或产生奇偶校验位.在数据传送过程中,为了提供传送的可靠性,如果采用奇偶校验的方法,就可使用该标志位.

  • 零标志ZF(Zero Flag): ZF用来反映运算结果是否为0.如果运算结果为0,则其值为1,否则其值为0.在判断运算结果是否为0时,可使用此标志位.

  • 符号标志SF(Sign Flag): SF用来反映运算结果的符号位.它与运算结果的最高位相同.在微机系统中,有符号数采用补码表示法,所以SF也就反映运算结果的正负号.运算结果为正数时,SF的值为0,否则其值为1.

  • 溢出标志OF(Overflow Flag): OF用于反映有符号数加减运算所得结果是否溢出.如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1.否则,OF的值被清为0.溢出和进位是两个不同含义的概念.

  • 辅助进位标志AF(Auxiliary Carry Flag): 发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0:

    在字操作时,发生低字节向高字节进位或借位时.
    在字节操作时,发生低4位向高4位进位或借位时.

对以上6个运算结果标志位,在一般编程情况下,标志位CF,ZF,SF,OF的使用频率较高,而标志位PF,AF的使用频率较低.

2.状态控制标志位:

  • 追踪标志TF(Trap Flag): TF被置为1时,CPU进入单步执行方式,即每执行一条指令,产生一个单步中断请求.这种方式主要用于程序的调试.指令系统中没有专门的指令来改变标志位TF的值,但程序员可用其它办法来改变其值.

  • 中断允许标志IF(Interrupt-enable Flag): IF是用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求.但不管该标志为何值,CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求,以及CPU内部产生的中断请求.具体规定如下:

    当IF为1时,CPU可以响应CPU外部的可屏蔽中断发出的中断请求.
    当IF为0时,CPU不响应CPU外部的可屏蔽中断发出的中断请求.

  • 方向标志DF(Direction Flag): DF用来决定在串操作指令执行时有关指针寄存器发生调整的方向.

3.32位CPU新增的标志寄存器的标志位:

  • I/O特权标志位IOPL(I/O Privilege Level): I/O特权标志用两位二进制位来表示,也称为I/O特权级字段.该字段指定了要求执行I/O指令的特权级.如果当前的特权级别在数值上小于等于IOPL的值,那么该I/O指令可执行,否则将发生一个保护异常.

  • 嵌套任务标志NT(Nested Task): NT用来控制中断返回指令IRET的执行,具体规定如下:

    当NT为0,用堆栈中保存的值恢复EFLAGS,CS,EIP执行常规的中断返回操作.
    当NT为1,通过任务转换实现中断返回.

  • 重启动标志RF(Restart Flag): RF用来控制是否接受调试故障.规定:RF为0时,表示接受调试故障,否则拒绝之.在成功执行完 一条指令后,处理机把RF置为0,当接受到一个非调试故障时,处理机就把它置为1.

  • 虚拟8086方式标志VM(Virtual 8086 Mode): 如果VM标志的值为1,则表示处理机处于虚拟的8086方式下的工作状态,否则,处理机处于一般保护方式下的工作状态.