如何直接读写x86标志寄存器?

时间:2009-09-10 17:58:30

标签: assembly x86

从我所看到的,似乎有9种不同的旗帜。是否可以直接读取/更改它们?我知道我可以知道例如在执行cmp / jmp指令后是否设置了零标志,但我问是否可以做类似的事情

mov eax, flags

或其他什么。

另外,对于写作,是否可以手动设置它们?

6 个答案:

答案 0 :(得分:27)

可以使用特定说明直接设置或清除某些标志:

  • CLCSTCCMC:清除,设置和补充进位标记
  • CLISTI:清除并设置中断标志(应该以原子方式完成)
  • CLDSTD:清除并设置方向标志

对于读写符号,零,辅助进位,奇偶校验和进位标志,可以使用LAHF将低8位(这5个标志加3个不确定位)加载到AH寄存器中,并且您可以使用SAHF将AH中的值存储回标志寄存器。

您还可以使用PUSHF指令将标志推入堆栈,在堆栈上读取和修改它们,然后使用POPF指令将它们存储回标志寄存器。 / p>

请注意,您无法使用POPF设置VM和RF标志 - 它们保留以前的值。同样,只能在特权级别0执行时更改I / O特权级别,并且只能在特权级别执行时更改中断标志,至少与I / O特权级别一样具有特权。

答案 1 :(得分:8)

你可以使用pushf和popf指令将标志推入堆栈,你可以修改它们,然后将它们弹回。

答案 2 :(得分:5)

如果你只需要标志寄存器的低字节(包含SF,ZF,AF,PF,CF),那么有一个奇怪但方便的指令LAHF(哈哈),它加载了底部的8位flags注册到AH,以及其对应的SAHF将AH存储到标志中。

对于进位标志,x86提供CLC,STC和CMC,分别清除,设置和补充进位标志。

答案 3 :(得分:2)

最简单的方法是使用 pushf / popf

如果要将eflags移至eax,请使用下面的代码。

pushf                  # push eflags into stack
pop %eax               # pop it into %eax

答案 4 :(得分:1)

<强> SETcc

该指令族是观察某些标志/标志组合的另一种方法。例如,CF

stc
setc al
; al == 1

clc
setc al
; al == 0

<强> JCC

此指令系列当然是某些标志的另一种可能性,可用于实现SETcc

jc set
mov al, 0
jmp end
set:
mov al, 1
end:

答案 5 :(得分:0)

  • LAHF:将状态标志加载到AH
  • 复制EFLAGS寄存器的低字节,包括Sign,Zero和Carry标志。
  • 将标志的副本保存在变量中以便妥善保管

    .data
     saveflags BYTE ? 
    .code 
     lahf ; load flags into AH 
     mov saveflags,ah ; save them into a variable 
    
  • SAHF:将AH存储到状态标志

  • 将AH复制到EFLAGS寄存器的低字节
  • 检索先前存储的标志的值

    .code
     mov ah, saveflags ; load save flags into AH 
     sahf ; copy into flags register