?
TF(Trap Flag)——位8,跟蹤標志。置1 則開啟單步執行調試模式,置0 則關閉。在單步執行模式下,處理器在每條指令后產生一個調試異常,這樣在每條指令執行后都可以查看執行程序的狀態。如果程序用POPF、POPFD 或者ET 指令設置TF 標志,那么這之后的第一條指令就會產生調試異常。
?
IF (Interrupt enable)——位9,中斷許可標志。控制處理器對可屏蔽硬件中斷請求的響應。置1 則開啟可屏蔽硬件中斷響應,置0 則關閉可屏蔽硬件中斷響應。IF 標志不影響異常和不可屏蔽中斷(NMI)的產生。CPL、IOPL 和控制寄存器CR4 中的VME 標志決定著IF 標志是否可由CLI、STI、POPF、POPFD 和IRET 指令修改。
?
IOPL(I/O Privilege Level Field)——位12&位13, I/O 特權域。標示當前進程或任務的I/O 特權級別。當前進程或任務的CPL 必須小于或等于IOPL 才可以訪問I/O 地址空間。只有CPL 為0 的進程才可用POPF 和IRET 指令修改這個域。IOPL 是控制IF 標志修改的機制之一,同時也是當虛擬模式擴展生效時(控制寄存器CR4 中的VME 置位),控制虛擬8086 模式下中斷處理的機制之一。
?
NT (Nested?Task)——位14,嵌套任務。控制被中斷和被調用的任務的嵌套執行鏈。處理器調用一個由CALL 指令、中斷或者異常觸發的任務時設置該位,調用IRET指令返回時檢測并修改該位。該標志可以由POPF/POPFD 指令直接置位或置0,然而在應用程序中修改該標志的狀態會產生不可預料的異常。
?
RF(Resume)——位16, 恢復。控制處理器對指令斷點的響應。置1 則暫時禁用指令斷點產生調試異常(debug exceptions,#DE),但是其它異常情況仍可以產生異常。置0 則指令斷點產生調試異常。RF 標志的主要功能是許可從調試異常(指令斷點引發的)后面的那個指令開始繼續執行。調試軟件必須在用IRETD 指令返回到被中斷程序之前,將棧中的EFLAGES 映象中的該位置為1,以阻止指令斷點產生另外的調試異常。在返回并成功執行斷點指令之后,處理器會自動清零該位,從而許可繼續產生指令斷點故障。
?
VM (Virtual-8086 mode)——位17,虛擬8086 模式。置1 則進入虛擬8086 模式,置0 則返回保護模式。
?
AC (Alignment check)——位18,對齊檢查。置位該標志和控制寄存器CR0 的AM 標志則啟用對內存引用的對齊檢查,清除這兩個標志則禁用對齊檢查。當引用一個沒有對齊的操作數時,將會產生一個對齊檢查異常,比如在奇地址引用一個字地址或在不是4 的倍數的地址引用一個雙字地址。對齊檢查異常只在用戶態(3 級特權)下產生。默認特權為0 的內存引用,比如段描述符表的裝載,并不產生這個異常,盡管同樣的操作在用戶態會產生異常。對齊檢查異常用于檢查數據的對齊,當處理器之間交換數據時這很有用,交換數據需要所有的數據對齊。對齊檢查異常也可供解釋程序使用。讓某些指針不對齊就好比做上特殊標記,這樣就無需對每個指針都進行檢查,只在用到的時候,對這些特殊指針進行處理就可以了。
?
VIF (Virtual Interrupt)——位19,虛擬中斷。是IF 標志的一個虛擬映象。這個標志是和VIP標志一起使用的。當控制寄存器CR4 中的VME 或者PVI 標志置為1 且IOPL小于3 時,處理器只識別VIF 標志(VME 標志用來啟用虛擬8086 模式擴展,PVI 標志啟用保護模式下的虛擬中斷)。
?
VIP (Virtual interrupt pending)——位20,虛擬中斷等待。置1 表明有一個正在等待處理的中斷,置0 表明沒有等待處理的中斷。該標志和VIF 一起使用。處理器讀取該標志但從來不修改它。當VME 標志或者控制寄存器CR4 中的PVI 標志置1 且IOPL 小于3 時,處理器只識別VIP 標志。(VME 標志啟用虛擬8086模式擴展,PVI 標志啟用保護模式虛擬中斷)。
?
ID (Identification)——識別(第21 位)。置1 或0 表明是否支持CPUID 指令。
?
其它的通用標志:
CF——進位標志
PF——恢復標志
AF——輔助標志
ZF——零標志
SF——負號標志
DF——方向標志
OF——溢出標志
?
上表是 32 位寄存器 EFLAGS 的低 16 位.
不能直接讀寫 EFLAGS, 但有些方便的指令, 如:
LAHF: 讀取EFLAGS 低 8 位到 AH;
SAHF是將AH存至EFLAG低8位
---------------------------------------------------------------------------------------------------
CLC?? ;置CF=0
STC?? ;置CF=1
CMC? ;置CF= (Not CF)進位標志求反
CLD?? ;置DF= 0?
STD?? ;置DF=1
---------------------------------------------------------------------------------------------------
.386
.modelflat,stdcall
include?? windows.inc
include?? kernel32.inc
include?? masm32.inc
include?? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.data
??? szBin1?db? 8 dup(?), 0
??? szBin2?db? 8 dup(?), 0
??? szBin3?db? 8 dup(?), 0
??? szBin4?db? 8dup(?), 0
.code
main proc
???stc?????;置位 CF, CF = 1
???lahf
???invoke byt2bin_ex,ah,addr szBin1????
?? clc;復位 CF, CF = 0
???lahf
???invokebyt2bin_ex,ah,addr szBin2
???
???stc
???cmc;取反 CF, CF = not CF
???lahf
???invoke byt2bin_ex,ah,addrszBin3
???
???clc
???cmc;取反 CF, CF = not CF
???lahf
???invokebyt2bin_ex,ah,addr szBin4
??? PrintString szBin1 ;xxxxxxx1
??? PrintString szBin2 ;xxxxxxx0
??? PrintString szBin3 ;xxxxxxx0
??? PrintString szBin4 ;xxxxxxx1
???ret
main endp
end main
---------------------------------------------------------------------------------------------------
如果要觀察整個 EFLAGS 的 32 個位, 可用 PUSHFD 和 POPFD 指令讓 EFLAGS 進棧、出棧
---------------------------------------------------------------------------------------------------
.586p
.model flat, stdcall
include?? windows.inc
include?? kernel32.inc
include?? masm32.inc
include?? debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib
.data
??? szBin db 32 dup(?), 0
.code
main proc
??? stc
??? pushfd
??? invoke dw2bin_ex, dword ptr [esp+4],addr szBin
??? popfd
??? PrintString szBin ;00000000000000000000001001000111
???
??? clc
??? pushfd
??? invoke dw2bin_ex, dword ptr [esp+4],addr szBin
??? popfd
??? PrintString szBin ;00000000000000000000001010000110
??? ret
main endp
end main