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

发布于 2024-08-03 23:43:12 字数 164 浏览 6 评论 0原文

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

mov eax, flags

另外,对于书写,可以手动设置它们吗?

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

or something.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

你的笑 2024-08-10 23:43:12

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

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

对于读写符号、零、辅助进位、奇偶校验和进位标志,可以使用 < a href="http://pdos.csail.mit.edu/6.828/2008/readings/i386/LAHF.htm" rel="noreferrer">LAHF 加载低 8 位(这 5 个标志加上3 个不确定位)写入 AH 寄存器,您可以使用 SAHF< /a> 将 AH 中的这些值存储回标志寄存器。

您还可以使用 PUSHF 指令推送标志到堆栈上,在堆栈上读取并修改它们,然后使用 POPF1 指令将它们存储回标志寄存器。

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


脚注 1:

请注意,popf 在现代 CPU 上相当慢;请参阅 Agner Fog 优化指南和说明表。它是微编码的,因为在内核模式下它能够更改 IF 和 AC 以及 IO 特权级别。无论当前 CPU 的模式如何,我们都会遭受损失,因为解码器对模式不敏感。

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

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.

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.

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.


Footnote 1:

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.

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.

巾帼英雄 2024-08-10 23:43:12

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

You can use the pushf and popf instructions which will push the flags onto the stack, you can modify them, and then pop them back off.

翻身的咸鱼 2024-08-10 23:43:12

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

具体来说,对于进位标志,x86 提供了 CLC、STC 和 CMC,分别用于清除、设置和补充进位标志。

If you need only the lower byte of the flags register (which contains SF,ZF,AF,PF,CF), then there is the odd but convenient instruction LAHF (ha ha), which loads the bottom 8 bits of the flags register into AH, and its counterpart SAHF to store AH into flags.

For the carry flag specifically, x86 offers CLC, STC and CMC, to clear, set, and complement the carry flag, respectively.

一江春梦 2024-08-10 23:43:12

最简单的方法是使用pushfd/pushfw 和pop (r16/r32)。

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

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

或者,如果您只需要 eflags 中的前 16 位:

pushfw
pop %ax

在大多数汇编器中(至少是 GAS 和 NASM,可能还有其他汇编器),没有显式操作数大小的 pushf 默认为您所处的模式。例如 64 位模式下的 pushfq。如果您想在 16 位模式下使用 pushfd 来匹配 32 位 pop,通常只需要显式操作数大小。但这并没有什么坏处。

Simplest way is using pushfd/pushfw and pop (r16/r32).

If you want to move eflags into eax, use code below.

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

Or, if you only want the first 16 bits from eflags:

pushfw
pop %ax

In most assemblers (at least GAS and NASM, likely others), pushf without an explicit operand-size defaults to the mode you're in. e.g. pushfq in 64-bit mode. You'd normally only need an explicit operand-size if you wanted to use pushfd in 16-bit mode to match a 32-bit pop. But it doesn't hurt.

停滞 2024-08-10 23:43:12

SETcc

该指令系列是观察某些标志/标志组合的另一种方法。

它根据各个标志设置字节的值。

例如,对于 CF

stc
setc al
; al == 1

clc
setc al
; al == 0

可使用断言在 GitHub 上游运行

Jcc

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

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

带有断言的可运行 GitHub 上游

SETcc

This instruction family is another way to observe some flags / combination of flags.

It sets the value of a byte based on the individual FLAGS.

E.g., for CF:

stc
setc al
; al == 1

clc
setc al
; al == 0

Runnable GitHub upstream with assertions.

Jcc

This instruction family is of course another possibility for certain flags, and could be used to implement SETcc:

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

Runnable GitHub upstream with assertions.

白衬杉格子梦 2024-08-10 23:43:12
  • LAHF:将状态标志加载到 AH 中
  • 复制 EFLAGS 寄存器的低字节,包括符号、零和进位标志。
  • 将标志的副本保存在变量中以供妥善保管

    <前><代码>.data
    保存标志字节?
    。代码
    拉夫;将标志加载到 AH 中
    mov saveflags,啊;将它们保存到变量中

  • SAHF:将 AH 存储到状态标志

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

    <前><代码>.code
    mov 啊,saveflags ;将保存标志加载到 AH 中
    萨赫夫;复制到标志寄存器中

  • LAHF: loads status flags into AH
  • Copies the low byte of the EFLAGS register including Sign, Zero, and Carry flags.
  • Save a copy of the flags in a variable for safekeeping

    .data
     saveflags BYTE ? 
    .code 
     lahf ; load flags into AH 
     mov saveflags,ah ; save them into a variable 
    
  • SAHF: stores AH into status flags

  • Copies AH into the low byte of the EFLAGS register
  • Retrieve the value of flags stored earlier

    .code
     mov ah, saveflags ; load save flags into AH 
     sahf ; copy into flags register 
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文