标志寄存器作用
x86架构CPU中,标志寄存器主要有3种作用:
- 存储相关指令执行后的结果,例如CF、PF、AF、ZF、OF标志位
- 执行相关指令时,提供行为依据,例如执行
JE
指令时会读取ZF的值,来决定是否进行跳转。 - 控制CPU的工作方式,例如IF、VM、TF等标志位。
16位模式下,标志寄存器名称为FLAG
,寄存器大小16位。
32位模式下,标志寄存器的名称为EFLAG
,寄存器大小32位。
64位模式下,为RFLAG
,寄存器大小64位。
EFLAG寄存器各个位的用途如下,其中灰色的部分为保留位。
对于16位模式下的标志寄存器,前16位和EFLAG寄存器相同。
对于64位模式下的标志寄存器,低32位均和EFLAG寄存器相同,高32位均为保留位。
在x86汇编语言中,读取FLAG寄存器的方式为:
通过汇编指令PUSHF
将FLAG寄存器数据压入栈,然后通过POP
将FLAG寄存器数据读入到通用寄存器,例如下面将FLAG寄存器内容写入AX寄存器
pushf
pop ax
如果需要写入FLAG寄存器,可通过POPF
指令将栈顶数据送入FLAG寄存器。
如果只需要访问FLAG寄存器低8位的数据,可以通过LAHF
指令将FLAG低8位数据送入AH寄存器,同时也可以执行SAHF
指令将AH寄存器数据送入FLAG寄存器中的低8位。
CF标志位
CF标志位位于标志寄存器的第0位,在进行无符号数运算时,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。
例如两个16位数据0xFFFF
和0x1000
相加,会产生进位,这个进位值在16位寄存器中无法保存,为了解决这个问题,进位值会被保存到CF标志位中。
比如在16位汇编语言中:
mov ax, 0xFFFF
add ax, ax
执行完成后,AX寄存器的值为0xFFFE
,CF标志位为1。
因为0xFFFF + 0xFFFF = 0x1FFFE
,但是AX寄存器只有16位,所以将最高位1放置于CF标志位。
PF标志位
PF标志位位于标志寄存器的第2位,用途是记录指令执行后,其运算结果的所有位中1的个数是否为偶数:
- 当PF位为1时,表示1的个数为偶数
- 当PF位为0时,表示1的个数为奇数
例如:
mov al, 10
add al, 100
执行后,AL寄存器为01101110
(二进制),其1的个数为5,所以PF位为0。
AF标志位
AF标志位位于标志寄存器的第4位,为辅助进位标志位,当执行一条运算指令后,如果第3位向第4位发生了进位,那么AF标志位为1,例如:
mov al, 0xF
add al, 1
此时AL寄存器为0x10,AF标志位为1。
ZF标志位
ZF标志位位于标志寄存器的第6位,用于记录相关指令执行后,其结果是否为0,如果结果为0,那么ZF标志位为1。
例如:
mov ax, 10
sub ax, 10
执行后,AX寄存器为0,ZF标志位为1。
SF标志位
SF标志位位于标志寄存器的第7位,用于记录相关指令执行后,其结果是否为负数(最高位为1表示负数),如果为负数,那么SF为1,如果不为负数,那么SF为0。
SF标志位是CPU对有符号数运算结果的一种记录,用于记录数据的正负,即最高位是否为1。
如果程序将其视为无符号数计算,那么SF标志位的值可以忽略。
例如:
mov al, 0
sub al, 1
此时,AL的值为11111111
(-1),SF值为1。
TF标志位
TF标志位位于标志寄存器的第8位,名称为调试标志位,当TF值为1时,CPU每执行一条指令就会触发1号中断,典型案例就是MASM的Debug程序。
IF标志位
IF标志位位于标志寄存器第8位,表示是否响应中断。
- 如果IF为1,那么会响应所有类型的中断
- 如果IF为0,那么只响应不可屏蔽中断。
IF标志位的值可通过指令CLI
设置为0,通过STI
指令设置为1,这两个指令均没有操作数。
DF标志位
IF标志位位于标志寄存器第9位,名称为方向标志位,默认为0
- 当DF为1时,存储器地址自动减少,串操作指令为自动减量指令。
- 当DF为0时,存储器地址自动增加,串操作指令为自动增量指令。
可通过汇编指令CLD
将DF标志位设置为0,也可通过STD
将DF设置为1。
串操作指令包含MOVSB
,MOVSW
,MOVSD
。
例如下面的案例,需要将DS:SI
后面的100字节数据复制到ES:DI
开始的内存区域:
mov cx, 100
cld
rep movsb
如果是将DS:SI
前面的100字节数据复制到ES:DI
前面的内存区域:
mov cx, 100
std
rep movsb
OF标志位
OF标志位位于标志寄存器的第9位,名称为溢出标志位。对于有符号数运算而言,如果计算后发生了溢出,那么OF标志位会设置为1。
例如:
mov al, 100
add al, 30
由于AL是8位寄存器,所以相加后会溢出(AL寄存器的值为-126
,二进制表示为1000 0010
),运算结果将不正确,此时OF标志位就会设置为1。