私が読んだことから、9つの異なるフラグがあるようです。それらを直接読み取ったり変更したりすることは可能ですか?たとえば、cmp/jmp命令を実行した後にゼロフラグが設定されているかどうかはわかりますが、次のようなことが可能かどうかを尋ねています。
mov eax, flags
か何か。
また、書くために、手で設定することは可能ですか?
一部のフラグは、特定の手順で直接設定またはクリアできます。
符号、ゼロ、補助キャリー、パリティ、およびキャリーフラグの読み取りと書き込みには、 [〜#〜] lahf [〜#〜] を使用して下位8ビット(これらの5つのフラグと3つの不確定ビット)をAHレジスタに挿入し、 [〜#〜] sahf [〜#〜] を使用して、これらの値をAHからフラグレジスタに格納し直すことができます。
[〜#〜] pushf [〜#〜] 命令を使用してフラグをスタックにプッシュし、スタックでフラグを読み取って変更してから、 [〜 #〜] popf [〜#〜]1 それらをフラグレジスタに格納するための命令。
VMおよびRFフラグをPOPFで設定することはできません。これらは以前の値を保持します。同様に、変更できるのはI/O特権レベルのみです。特権レベル0で実行する場合、および割り込みフラグは、少なくともI/O特権レベルと同じ特権レベルで実行する場合にのみ変更できます。
脚注1:
最近のCPUではpopf
が非常に遅いことに注意してください。 Agner Fog's 最適化ガイドと指示表を参照してください。カーネルモードではIFとAC、およびIO特権レベルを変更できるため、マイクロコード化されています。デコーダーはモードに依存しないため、現在のCPUのモードに関係なくペナルティが発生します。
可能であれば、パフォーマンスのためにpushf/popfの代わりにlahf/sahfを使用するか、_setc al
_のように気になる単一のフラグを保存してから_add al, 255
_を保存してCF = (AL!=0)
を設定します。または_setnc al
_/_sub al, 1
_など。 0または1レジスタに基づいてSFまたはOFを設定またはクリアするシーケンスも簡単で、フラグを反転する場合としない場合があります。
Pushfおよびpopf命令を使用して、フラグをスタックにプッシュし、それらを変更してから、元に戻すことができます。
フラグレジスタの下位バイト(SF、ZF、AF、PF、CFを含む)のみが必要な場合は、フラグレジスタの下位8ビットをロードする奇妙で便利な命令LAHF(ha ha)があります。 AH、およびAHをフラグに格納するための対応するSAHF。
特にキャリーフラグの場合、x86は、キャリーフラグをクリア、設定、および補完するために、それぞれCLC、STC、およびCMCを提供します。
SETcc
この命令ファミリは、いくつかのフラグ/フラグの組み合わせを監視する別の方法です。
個々のFLAGSに基づいてバイトの値を設定します。
例:CF
の場合:
stc
setc al
; al == 1
clc
setc al
; al == 0
アサーション付きの実行可能なGitHubアップストリーム 。
Jcc
もちろん、この命令ファミリは特定のフラグの別の可能性であり、SETcc
を実装するために使用できます。
jc set
mov al, 0
jmp end
set:
mov al, 1
end:
最も簡単な方法はpushf/popfを使用することです。
eflags
をeax
に移動する場合は、以下のコードを使用してください。
pushf # Push eflags into stack
pop %eax # pop it into %eax
フラグのコピーを保管のために変数に保存します
.data
saveflags BYTE ?
.code
lahf ; load flags into AH
mov saveflags,ah ; save them into a variable
SAHF:AHをステータスフラグに格納します
以前に保存されたフラグの値を取得します
.code
mov ah, saveflags ; load save flags into AH
sahf ; copy into flags register