Pregunta

I want to read the CPU flags by pushing them onto the stack and then pop them to a register like this:

uint32_t getEflags() {
    uint32_t eflags;
    asm ("pushf");
    asm ("pop %eax");
    asm ("mov %%eax, %0" : "=r"(eflags));
    return eflags;
}

Now I saw that this is a mistake because pushf only pushes the lower 16 bits of the EFLAGS, and I'm then popping them into a 32 bit register (i would need pushfd).

That means I'm basically popping more than I'm initially pushing - what happens with my stack when returning here?

¿Fue útil?

Solución

The instruction set reference says this:

Decrements the stack pointer by 4 (if the current operand-size attribute is 32) and pushes the entire contents of the EFLAGS register onto the stack

It also says:

The PUSHF (push flags) and PUSHFD (push flags double) mnemonics reference the same opcode. The PUSHF instruction is intended for use when the operand-size attribute is 16 and the PUSHFD instruction for when the operand-size attribute is 32. Some assemblers may force the operand size to 16 when PUSHF is used and to 32 when PUSHFD is used. Others may treat these mnemonics as synonyms (PUSHF/PUSHFD) and use the current setting of the operand-size attribute to deter- mine the size of values to be pushed from the stack, regardless of the mnemonic used.

So no problem there. Your asm is broken, though, it should be something more like this:

__asm__ __volatile__(
    "pushf\n\t"
    "pop %0"
: "=rm" (eflags));
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top