关于标志寄存器的简单总结


标志寄存器

img

标志寄存器的标志位,是对数据逻辑运算的结果进行特殊标记。比如两个数相加是否产生了数据外溢,相减结果是否为零等等。通过对运算结果的标记,来进行判断下一步执行的语句,从而达到分支语句的作用(跳转)等操作。因此对标志寄存器的理解学习尤为重要。


影响标志寄存器变化的操作---数据逻辑运算

add
sub
xor
or
and
....
;注意:数据移动操作不能影响标志寄存器,如mov

零标志位(6)

变化条件

标记了运算结果是否为零,如果为零,那么该标志位为1,反之为0。

功能作用

可用于两个数值比较,如果两个数值相同,那么两个数相减的结果一定为0,相反如果结果不为0,那么两个数值不相等。

测试代码

mov eax,0
add eax,0x0

image-20220205111040569


奇偶标志位(2)

变化条件

运算结果的二进制数值中的最低有效字节(末尾的八位),如果1的个数是奇数,那么标志位为0,反之1的个数为偶数,标志位为1

功能作用

主要用于检查数据传送过程中的错误

测试代码

mov eax,0x0
add eax,0x1

image-20220205112517983

在上述结果上再次加二,观察结果

add eax,0x2

image-20220205112753912


进位标志(0)与溢出标志(11)

变化条件

1)进位标志:在运算过程中,如果产生了向高位进位或借位的情况,那么该标记位置为1,反之置为0

2)溢出标志:在运算过程中,运算结果超出了寄存器最大表示范围,如:两个正数相加结果变为了负数

功能作用

1)进位标志:如果我们计算一个非常大的加法运算时,需要多个dword空间存放一个运算数。

如下十六进制运算过程
    00000001 ffffffff
+   00000000 00000001
----------------------
    00000002 00000000
1)上述运算过程在人眼下能够一眼算出答案,但是计算机需要进行分步操作,原因是32位操作系统,操作数据的最大范围是32位(八位十六进制数)
2)因此,需要对每个对应的32位数据依次进行加法运算
3)首先将ffffffff与00000001相加,结果为0000000,但是此时的标记位cf为1
4)利用带进位加法adc指令运算00000001与00000000的相加,那么将会在结果的基础上加上标记位
5)也就是1 + 0 + 1

2)溢出标志:判断结果是否产生了溢出,正溢|负溢

综合总结

两个标记位都是记录了数据运算过程中的进位问题,但是记录的角度不同。发生进位不一定发生溢出,比如负数加上正数,永远不会溢出但是会产生进位。同样的发生溢出也不一定发生进位,如两个正数相加,结果最高为被置为1时,将结果看作是有符号数时,那么就等同于:正数 + 正数 = 负数,产生了溢出,但是没有产生进位。

1)将运算数据看做无符号数:进位标志

2)将运算数据看做有符号数:溢出标志

测试代码

1)进位标志

;向高位进位测试代码
mov eax,0x0		;将eax清空,方便观察
mov ax,0xffff
add ax,0x1

image-20220205114649796

;向高位借位测试代码
mov eax,0x0
sub eax,0x1

image-20220205115007225

2)溢出标志

;正溢出代码,两个正数相加,结果变为负数
mov eax,0x7fffffff
add eax,0x1

image-20220205114022139

;负溢出代码,两个负数相减,结果变为正数
mov eax,0x80000000
sub eax,0x1

image-20220205114259595

辅助进位标志(4)

变化条件

当前操作的数据宽度的中间位置发生了进位/借位操作时,该标记位被置为1,反之为0

如八位的操作数据,位置1向位置2进位或借位时辅助进位标志发生变化(16位,32位同理):

image-20220207152327631

测试代码

mov eax,0x0000ffff
add eax,0x1

image-20220207152619036


符号标志(7)

变化条件

数据的运算结果是负数时,标记位置为1,反之置为0

测试代码

mov eax,0x0
mov al,0x7f
add al,0x1

image-20220207152946329


方向标志(10)

例如在执行MOVS指令时,如果标志位置为1,那么esi、edi同时减4,反之标志位为0时,esi、edi同时加4

中断使能标志(9)与单步标志(8)

涉及到程序的单步执行

X86