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

C 使用“pushf”并弹出到32位寄存器会破坏堆栈吗?,c,assembly,kernel,osdev,C,Assembly,Kernel,Osdev,我想通过将CPU标志推到堆栈上读取它们,然后将它们弹出到如下寄存器: uint32_t getEflags() { uint32_t eflags; asm ("pushf"); asm ("pop %eax"); asm ("mov %%eax, %0" : "=r"(eflags)); return eflags; } __asm__ __volatile__( "pushf\n\t" "pop %0" : "=rm" (eflags

我想通过将CPU标志推到堆栈上读取它们,然后将它们弹出到如下寄存器:

uint32_t getEflags() {
    uint32_t eflags;
    asm ("pushf");
    asm ("pop %eax");
    asm ("mov %%eax, %0" : "=r"(eflags));
    return eflags;
}
__asm__ __volatile__(
    "pushf\n\t"
    "pop %0"
: "=rm" (eflags));
现在我看到这是一个错误,因为pushf只推送eflag的低16位,然后我将它们放入一个32位寄存器,我需要pushfd


这意味着我弹出的内容基本上比我最初推动的内容要多-当我返回这里时,堆栈会发生什么情况?

指令集参考说明如下:

如果当前操作数大小为,则将堆栈指针递减4 属性为32并推送EFLAGS寄存器的全部内容 上架

它还说:

PUSHF push flags和PUSHFD push flags是双助记符 引用相同的操作码。PUSHF指令旨在使用 当操作数大小属性为16且PUSHFD指令 当操作数大小属性为32时。一些汇编程序可能会强制 使用PUSHF时操作数大小为16,使用PUSHFD时操作数大小为32。 其他人可能将这些助记符视为同义词PUSHF/PUSHFD并使用 用于确定挖掘的操作数大小属性的当前设置 要从堆栈中推送的值的大小,与助记符无关 用过

所以没问题。但是,您的asm已损坏,应该是这样的:

uint32_t getEflags() {
    uint32_t eflags;
    asm ("pushf");
    asm ("pop %eax");
    asm ("mov %%eax, %0" : "=r"(eflags));
    return eflags;
}
__asm__ __volatile__(
    "pushf\n\t"
    "pop %0"
: "=rm" (eflags));

指令集参考说明如下:

如果当前操作数大小为,则将堆栈指针递减4 属性为32并推送EFLAGS寄存器的全部内容 上架

它还说:

PUSHF push flags和PUSHFD push flags是双助记符 引用相同的操作码。PUSHF指令旨在使用 当操作数大小属性为16且PUSHFD指令 当操作数大小属性为32时。一些汇编程序可能会强制 使用PUSHF时操作数大小为16,使用PUSHFD时操作数大小为32。 其他人可能将这些助记符视为同义词PUSHF/PUSHFD并使用 用于确定挖掘的操作数大小属性的当前设置 要从堆栈中推送的值的大小,与助记符无关 用过

所以没问题。但是,您的asm已损坏,应该是这样的:

uint32_t getEflags() {
    uint32_t eflags;
    asm ("pushf");
    asm ("pop %eax");
    asm ("mov %%eax, %0" : "=r"(eflags));
    return eflags;
}
__asm__ __volatile__(
    "pushf\n\t"
    "pop %0"
: "=rm" (eflags));

请问,你的代码和OP的代码到底有什么区别?它们都很好,在我的电脑上的工作方式完全相同。好的,谢谢。你能描述一下为什么我的asm代码不是这样工作的吗?首先,OP的代码忘记告诉编译器eax被破坏了,所以它可能会破坏周围的代码。此外,编译器还可以对单独的asm块重新排序。此外,作为优化点,输出操作数可以是任何寄存器或内存,无需经过eax。仅供将来参考,在GNU和32位模式下的AT&T语法中,pushf和pushfl都是32位push,即Intel语法中的PUSHFD。如果你想要16位版本,它是pushfw。我可以问一下,你的代码和OP的代码有什么区别吗?它们都很好,在我的电脑上的工作方式完全相同。好的,谢谢。你能描述一下为什么我的asm代码不是这样工作的吗?首先,OP的代码忘记告诉编译器eax被破坏了,所以它可能会破坏周围的代码。此外,编译器还可以对单独的asm块重新排序。此外,作为优化点,输出操作数可以是任何寄存器或内存,无需经过eax。仅供将来参考,在GNU和32位模式下的AT&T语法中,pushf和pushfl都是32位push,即Intel语法中的PUSHFD。如果你想要16位版本,它是pushfw。