Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read and write x86 flags registers directly?

Tags:

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?

like image 270
devoured elysium Avatar asked Sep 10 '09 17:09

devoured elysium


People also ask

How do you read a flag register?

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.

What instruction would you use to save the entire Eflags register?

Only certain flags are copied across with these instructions. The whole FLAGS / EFLAGS / RFLAGS register can be saved or restored on the stack: PUSHF / POPF Push/pop 16-bit FLAGS onto/from the stack.

What is flag register in assembly language?

The flag register is one of the special purpose register. The flag bits are changed to 0 or 1 depending upon the value of result after arithmetic or logical operations. 8086 has 16-bit flag register, and there are 9 valid flag bits. The format of flag register is like below.

What is the size of register refernce in x86?

64-bit x86 adds 8 more general-purpose registers, named R8, R9, R10 and so on up to R15. R8–R15 are the new 64-bit registers. R8D–R15D are the lowermost 32 bits of each register. R8W–R15W are the lowermost 16 bits of each register.


1 Answers

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.

like image 187
Adam Rosenfield Avatar answered Nov 06 '22 22:11

Adam Rosenfield