使用“pushf”并弹出到32位寄存器会破坏堆栈吗?

时间:2014-04-19 22:11:01

标签: c assembly kernel osdev

我想通过将CPU标志推入堆栈然后将它们弹出到这样的寄存器来读取它们:

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

现在我看到这是一个错误,因为 pushf 只推动EFLAGS的低16位,然后我将它们弹出到32位寄存器(我需要 PUSHFD )。

这意味着我基本上会弹出比我最初推动更多的东西 - 回到这里时我的筹码会发生什么?

1 个答案:

答案 0 :(得分:4)

指令集参考说明:

  

将堆栈指针减少4(如果是当前操作数大小   属性为32)并推送EFLAGS寄存器的全部内容   在堆栈上

它还说:

  

PUSHF(推旗)和PUSHFD(推旗双)助记符   引用相同的操作码。 PUSHF指令旨在使用   当operand-size属性为16且PUSHFD指令为   当operand-size属性为32.某些汇编程序可能会强制执行   使用PUSHF时操作数大小为16,使用PUSHFD时操作数大小为32。   其他人可能会将这些助记符视为同义词(PUSHF / PUSHFD)并使用   操作数大小属性的当前设置来确定   无论助记符如何,都要从堆栈中推送的值的大小   使用

那里没问题。你的asm坏了,但它应该是更像这样的东西:

__asm__ __volatile__(
    "pushf\n\t"
    "pop %0"
: "=rm" (eflags));