如何直接读写x86标志寄存器? [英] How to read and write x86 flags registers directly?

查看:220
本文介绍了如何直接读写x86标志寄存器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从我阅读的内容来看,似乎有9个不同的标志.是否可以直接读取/更改它们?我知道我可以例如在执行cmp/jmp指令后是否设置零标志,但是我问是否可以做类似的事情

From what I've read, seems like there are 9 different flags. Is it possible to read/change them directly? I know I can know for example if the zero flag is set after doing a cmp/jmp instruction, but I'm asking if it's possible to do something like

mov eax, flags

之类的.

另外,为了书写,可以手动设置它们吗?

Also, for writing, is it possible to set them by hand?

推荐答案

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

Some flags can be set or cleared directly with specific instructions:

  • CLC, STC, and CMC: clear, set, and complement the carry flag
  • CLI and STI: clear and set the interrupt flag (which should be done atomically)
  • CLD and STD: clear and set the direction flag

对于读写符号,零,辅助进位,奇偶校验和进位标志,可以使用

For reading and writing the sign, zero, auxiliary carry, parity, and carry flags, you can use LAHF to load the lower 8 bits (those 5 flags plus 3 indeterminate bits) into the AH register, and you can use SAHF to store those values from AH back into the flags register.

您还可以使用 PUSHF 指令将标志推送到堆栈上,在堆栈上读取和修改它们,然后使用 POPF 1 指令将其存储回标志寄存器中.

You can also use the PUSHF instruction to push the flags onto the stack, read and modify them on the stack, and then use the POPF1 instruction to store them back into the flags register.

请注意,您不能使用POPF设置VM和RF标志-它们保留其先前的值.同样,仅当以特权级别0执行时才能更改I/O特权级别,并且仅当以至少与I/O特权级别相同的特权级别执行时,才能更改中断标志.

Note that you cannot set the VM and RF flags with POPF -- they retain their previous values. Similarly, you can only change the I/O privilege level when executing at privilege level 0, and the interrupt flag can only be changed when executing at a privilege level at least as privileged as the I/O privilege level.

脚注1:

请注意,popf在现代CPU上相当慢.请参阅 Agner Fog的优化指南和说明表.它是经过微码处理的,因为在内核模式下它可以更改IF和AC,以及IO特权级别.由于解码器对模式不敏感,因此在当前CPU上无论采用哪种模式,我们都将受到损失.

Note that popf is quite slow on modern CPUs; see Agner Fog's optimization guide and instruction tables. It's microcoded because in kernel mode it's able to change IF and AC, and IO privilege level. We suffer the penalty regardless of mode on current CPUs because the decoders aren't mode-sensitive.

如果可能,请使用lahf/sahf代替pushf/popf来提高性能,或者保存一个您关心的标志,例如setc al,然后再保存add al, 255以设置CF = (AL!=0).或setnc al/sub al, 1或其他.基于0或1寄存器来设置或清除SF或OF的序列也很简单,带有/不带有反转标志.

If possible, use lahf/sahf instead of pushf/popf for performance, or save a single flag you care about like setc al then later add al, 255 to set CF = (AL!=0). Or setnc al / sub al, 1 or whatever. Sequences to set or clear SF or OF based on a 0 or 1 register are also straightforward, with/without inverting the flag.

这篇关于如何直接读写x86标志寄存器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆