POPF/POPFD - 將堆疊彈入 EFLAGS 暫存器

操作碼

指令

說明

9D

POPF

將棧頂彈入 EFLAGS 的低 16 位

9D

POPFD

將棧頂彈入 EFLAGS

說明

將棧頂的雙字 (POPFD)(如果目前運算元大小屬性為 32)彈出,並將它的值儲存到 EFLAGS 暫存器,或是將棧頂的字(如果運算元大小屬性為 16)彈出,並將它儲存到 EFLAGS 暫存器的低 16 位(即 FLAGS 暫存器)。這些指令執行 PUSHF/PUSHFD 指令的逆操作。

POPF(彈出標誌)與 POPFD(彈出標誌雙字)助記符引用相同的操作碼。POPF 指令旨在用於運算元大小屬性為 16 時;POPFD 指令旨在用於運算元大小屬性為 32 時。某些彙編器可能在使用 POPF 時將運算元大小強制變成 16,而在使用 POPFD 時將運算元大小強制變成 32。其它彙編器可能會將這些助記符看作同義詞 (POPF/POPFD),並使用運算元大小屬性的當前設定來確定要從堆疊彈出的值的大小,而不管使用哪一個助記符。

根據處理器的操作模式,POPF/POPFD 指令對 EFLAGS 暫存器的影響略有差異。處理器在保護模式中操作時,如果特權級別為 0(或是在實地址模式中操作,它相當於特權級別 0),則 EFLAGS 暫存器中除 VIP、VIF 以及 VM 標誌之外的所有非保留位都可以修改。VIP 與 VIF 標誌被清除,VM 標誌不受影響。

在保護模式中操作時,如果特權級別大於 0 但小於或等於 IOPL,則除 IOPL 欄位與 VIP、VIF 以及 VM 標誌之外的所有標誌都可以修改。這裡,IOPL 標誌不受影響,VIP 與 VIF 標誌被清除,VM 標誌不受影響。只有在至少與 IOPL 相等的特權級別下執行時,才可以更改中斷標誌 (IF)。如果在特權不夠高的情況下執行 POPF/POPFD 指令,則不會發生異常,但特權位也不會改變。

在虛 8086 模式中操作時,I/O 特權級別 (IOPL) 必須等於 3 才能使用 POPF/POPFD 指令,此時 VM、RF、IOPL、VIP 以及 VIF 標誌不受影響。如果 IOPL 小於 3,POPF/POPFD 指令將導致一般保護性異常 (#GP)。

如需有關 EFLAGS 暫存器的詳細資訊,請參閱“IA-32 英特爾(R) 體系結構軟件開發人員手冊”第 1 卷第 3 章中標題為“EFLAGS 暫存器”的部分。

操作

IF VM=0 (* Not in Virtual-8086 Mode *)
THEN IF CPL=0
THEN
IF OperandSize 32;
THEN
EFLAGS Pop();
(* All non-reserved flags except VIP, VIF, and VM can be modified; *)
(* VIP and VIF are cleared; VM is unaffected*)
ELSE (* OperandSize 16 *)
EFLAGS[15:0] Pop(); (* All non-reserved flags can be modified; *)
FI;
ELSE (* CPL > 0 *)
IF OperandSize 32;
THEN
EFLAGS Pop()
(* All non-reserved bits except IOPL, VIP, and VIF can be modified; *)
(* IOPL is unaffected; VIP and VIF are cleared; VM is unaffected *)
ELSE (* OperandSize 16 *)
EFLAGS[15:0] Pop();
(* All non-reserved bits except IOPL can be modified *)
(* IOPL is unaffected *)
FI;
FI;
ELSE (* In Virtual-8086 Mode *)
IF IOPL=3
THEN IF OperandSize=32
THEN
EFLAGS Pop()
(* All non-reserved bits except VM, RF, IOPL, VIP, and VIF *)
(* can be modified; VM, RF, IOPL, VIP, and VIF are unaffected *)
ELSE
EFLAGS[15:0] Pop()
(* All non-reserved bits except IOPL can be modified *)
(* IOPL is unaffected *)
FI;
ELSE (* IOPL < 3 *)
#GP(0); (* trap to virtual-8086 monitor *)
FI;
FI;
FI;

影響的標誌

除保留位與 VM 位之外的所有標誌。

保護模式異常

#SS(0) - 如果棧頂不在堆疊段內。

#PF(錯誤程式碼) - 如果發生頁錯誤。

#AC(0) - 如果在目前特權級別為 3 且啟用對齊檢查的情況下進行未對齊的記憶體引用。

實地址模式異常

#SS - 如果棧頂不在堆疊段內。

虛 8086 模式異常

#GP(0) - 如果 I/O 特權級別小於 3。如果試圖執行帶運算元大小覆蓋字首的 POPF/POPFD 指令。

#SS(0) - 如果棧頂不在堆疊段內。

#PF(錯誤程式碼) - 如果發生頁錯誤。

#AC(0) - 如果在啟用對齊檢查的情況下進行未對齊的記憶體引用。