关于标志寄存器的简单总结
标志寄存器
标志寄存器的标志位,是对数据逻辑运算的结果进行特殊标记。比如两个数相加是否产生了数据外溢,相减结果是否为零等等。通过对运算结果的标记,来进行判断下一步执行的语句,从而达到分支语句的作用(跳转)等操作。因此对标志寄存器的理解学习尤为重要。
影响标志寄存器变化的操作---数据逻辑运算
add
sub
xor
or
and
....
;注意:数据移动操作不能影响标志寄存器,如mov
零标志位(6)
变化条件
标记了运算结果是否为零,如果为零,那么该标志位为1,反之为0。
功能作用
可用于两个数值比较,如果两个数值相同,那么两个数相减的结果一定为0,相反如果结果不为0,那么两个数值不相等。
测试代码
mov eax,0
add eax,0x0
奇偶标志位(2)
变化条件
运算结果的二进制数值中的最低有效字节(末尾的八位),如果1的个数是奇数,那么标志位为0,反之1的个数为偶数,标志位为1
功能作用
主要用于检查数据传送过程中的错误
测试代码
mov eax,0x0
add eax,0x1
在上述结果上再次加二,观察结果
add eax,0x2
进位标志(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
;向高位借位测试代码
mov eax,0x0
sub eax,0x1
2)溢出标志
;正溢出代码,两个正数相加,结果变为负数
mov eax,0x7fffffff
add eax,0x1
;负溢出代码,两个负数相减,结果变为正数
mov eax,0x80000000
sub eax,0x1
辅助进位标志(4)
变化条件
当前操作的数据宽度的中间位置发生了进位/借位操作时,该标记位被置为1,反之为0
如八位的操作数据,位置1向位置2进位或借位时辅助进位标志发生变化(16位,32位同理):
测试代码
mov eax,0x0000ffff
add eax,0x1
符号标志(7)
变化条件
数据的运算结果是负数时,标记位置为1,反之置为0
测试代码
mov eax,0x0
mov al,0x7f
add al,0x1
方向标志(10)
例如在执行MOVS指令时,如果标志位置为1,那么esi、edi同时减4,反之标志位为0时,esi、edi同时加4
中断使能标志(9)与单步标志(8)
涉及到程序的单步执行