详解EFLAGS寄存器(标志寄存器)

我们都知道寄存器就相当于容器,是拿来存储数据的。标志寄存器它也是拿来存储数据的。
那他们有什么区别呢?
我们常用的寄存器,里面存的数据,都只有一个含义,而标志寄存器是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息。
在这里插入图片描述
重点把CF/PF/AF/ZF/SF/OF的位置记住,图上面有对应的序号

CF/PF/AF/ZF/SF/OF的位的解析

  1. 进位标志CF(Carry Flag):如果运算的结果的最高位产生了一个进位或者借位,那么其值为1,否者其值为0
    这里的进位是指:如果说用一个8位的寄存器进行运算,最终运算结果,会变成9位,但是寄存器这时候的数据宽度是8位,所以最高位会产生进位。这就表示最高位进位了,这时候CF的值会变成1,进位标志并不是指简单的最高位加1。
    可能这样用文字说不是很好理解。我用DTDebug给你们实验一下.
    MOV AL,0xEF
    ADD AL,2
    在这里插入图片描述
    目前程序执行到 MOV AL,0xEF这条语句,我们在DTDebug按f8单步执行一下这条语句看一下结果

在这里插入图片描述
执行完MOV这条语句后发现CF位没有发生变化,其实只有运算指令才会让标志寄存器的各个位发生变化
比如ADD,SUB,XOR。。。。。。。等一系列的运算指令。其他的与运算无关的指令,不会对标志寄存器的任何一位产生影响。

然后再执行下一条语句 ADD AL,2,结果如下图所示
在这里插入图片描述
在这里插入图片描述

执行完ADD AL,2后CF位还是为0,因为运算的结果是最高位并没有加进位,只是加1了而已。
2. 奇偶标志PF(Parity Flag):奇偶标志PF用于反应运算结果中 "1"的个数的奇偶性。如果 “1”的个数为偶数,则PF的值为1,否则其值为0.它只看最低的8位。
我们用DTDebug来演示以下以下指令,观察以下PF位的变化
MOV AL,3
ADD AL,3
ADD AL,2

在这里插入图片描述

目前程序执行到 MOV AL,0x3这条语句,我们在DTDebug按f8单步执行一下这条语句看一下结果

在这里插入图片描述

在上面已经说了只有运算指令才会影响标志寄存器,其他指令不会。
然后再执行下一条语句 ADD AL,3,结果如下图所示

在这里插入图片描述
这时候我们发现PF位变成了1,是因为当执行完ADD,AL,3这条指令后,AL里面的值就变成了6,对应的二进制是0110,
里面有两个1是偶数,所以PF位会变成1.

然后执行下一条语句ADD AL,2结果如下图所示
在这里插入图片描述
这时候我们发现PF位的值又变成了0,是因为当执行完ADD AL,2这条指令后,AL的值就变成了8,对应的二进制是1000,
里面只有一个1是奇数,所以PF位会变成0
3. 辅助进位标志AF(Auxiliary Carry Flag):需要根据数据宽度来确定是哪一位进位。数据宽度的位数除以2右边那一位。如果它进位了那么AF会变为1,如果它没有进位,则会变成0.
比如这样一个数据0x55EEFFFF,经过运算后我们只需要从右往左看第4个F是否进位就可以了。
再比如这样一个数据0x5EFE,经过运算后我们只需要从右往左看第二个F是否进位就可以了。
4.零标志位ZF(Zero Flag):零标志位用来反映运算结果是否为0.如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可以使用此标志。
5.符号标志SF(Sign Flag):符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。

6.溢出标志OF(Overflow Flag):溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否*则,OF的值被清为0.

那么CF与OF有什么区别呢
进位标志表示无符号数运算结果是否超出范围。
溢出标志表示有符号数运算结果是否超出范围。
溢出主要是给有符号运算使用的,在有符号数的运算中,有如下规律:
正+正=正 如果结果是负数,则说明有溢出
负+负=负 如果结果是正数,则说明有溢出
正+负 永远都不会有溢出
在这里插入图片描述
这个圆非常重要,一定要把它理解到。不懂的可以看一下这篇
数据宽度

一些有关的指令

ADC指令:带进位加法

格式:ADC R/M,R/M/IMM 两边不能同时为内存 宽度要一样 样

ADC AL,CL

ADC BYTE PTR DS:[12FFC4],2

ADC BYTE PTR DS:[12FFC4],AL

SBB指令:带借位减法

格式:SBB R/M,R/M 两边不能同时为内存 宽度要一样

SBB AL,CL

SBB BYTE PTR DS:[12FFC4],2

SBB BYTE PTR DS:[12FFC4],AL

XCHG指令:交换数据

格式:XCHG R/M,R/M/IMM 两边不能同时为内存 宽度要一样

XCHG AL,CL

XCHG DWORD PTR DS:[12FFC4],EAX

XCHG BYTE PTR DS:[12FFC4],AL

MOVS指令:移动数据 内存-内存

BYTE/WORD/DWORD

MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 简写为:MOVSB

MOVS WORD PTR ES:[EDI],BYTE PTR DS:[ESI] 简写为:MOVSW

MOVS DWORD PTR ES:[EDI],BYTE PTR DS:[ESI] 简写为:MOVSD

例子:

MOV EDI,12FFD8
MOV ESI,12FFD0
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 观察EDI的值
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

修改标志寄存器中D位的值,然后在执行下面的指令:

MOV EDI,12FFD8
MOV ESI,12FFD0
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 观察EDI的值
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

STOS指令:讲Al/AX/EAX的值存储到[EDI]指定的内存单元

STOS BYTE PTR ES:[EDI] 简写为STOSB

STOS WORD PTR ES:[EDI] 简写为STOSW

STOS DWORD PTR ES:[EDI] 简写为STOSD

MOV EAX,12345678
MOV EDI,12FFC4
STOS BYTE PTR ES:[EDI] 观察EDI的值
STOS WORD PTR ES:[EDI]
STOS DWORD PTR ES:[EDI]

修改标志寄存器中D位的值,然后在执行下面的指令:

MOV EAX,12345678
MOV EDI,12FFC4
STOS BYTE PTR ES:[EDI] 观察EDI的值
STOS WORD PTR ES:[EDI]
STOS DWORD PTR ES:[EDI]

REP指令:按计数寄存器 (ECX) 中指定的次数重复执行字符串指令

MOV ECX,10

REP MOVSD

REP STOSD
你们可以用DTDebbug自己去实验下。

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页