max*_*dev 2 c assembly kernel osdev
我想通过将 CPU 标志压入堆栈来读取它们,然后将它们弹出到寄存器中,如下所示:
uint32_t getEflags() {
uint32_t eflags;
asm ("pushf");
asm ("pop %eax");
asm ("mov %%eax, %0" : "=r"(eflags));
return eflags;
}
Run Code Online (Sandbox Code Playgroud)
现在我发现这是一个错误,因为Pushf只压入 EFLAGS 的低 16 位,然后我将它们弹出到 32 位寄存器中(我需要Pushfd)。
这意味着我弹出的内容基本上比最初推送的要多 - 返回这里时我的堆栈会发生什么情况?
指令集参考是这样说的:
将堆栈指针减 4(如果当前操作数大小属性为 32)并将 EFLAGS 寄存器的全部内容压入堆栈
它还说:
PUSHF(推送标志)和 PUSHFD(双推送标志)助记符引用相同的操作码。PUSHF 指令适用于操作数大小属性为 16 时,PUSHFD 指令适用于操作数大小属性为 32 时。某些汇编器可能会在使用 PUSHF 时强制操作数大小为 16,在使用 PUSHFD 时强制操作数大小为 32。其他人可能将这些助记符视为同义词(PUSHF/PUSHFD),并使用操作数大小属性的当前设置来确定要从堆栈推送的值的大小,而不管使用的助记符如何。
所以没有问题。不过,您的汇编已损坏,它应该更像是这样的:
__asm__ __volatile__(
"pushf\n\t"
"pop %0"
: "=rm" (eflags));
Run Code Online (Sandbox Code Playgroud)