x86フラグレジスタを直接読み書きする方法は?
質問
私が読んだことからすると、9つの異なるフラグがあるようです。それらを直接読み取り/変更することは可能ですか?たとえば、cmp / jmp命令を実行した後にゼロフラグが設定されているかどうかはわかりますが、次のようなことができるかどうかを尋ねています
mov eax, flags
または何か。
また、書くために、それらを手で設定することは可能ですか?
解決
いくつかのフラグは、特定の指示で直接設定またはクリアできます:
- CLC 、 STC 、および CMC :キャリーフラグをクリア、設定、補完
- CLI および STI :割り込みフラグをクリアして設定します(アトミックに実行する必要があります)
- CLD および STD :方向フラグをクリアして設定します
符号、ゼロ、補助桁上げ、パリティ、桁上げフラグの読み取りと書き込みには、 LAHF を使用して下位8ビット(5つのフラグと3つの不確定ビット)をAHレジスタにロードします。 SAHF は、AHからそれらの値をフラグレジスタに保存します。
PUSHF 命令も使用できます。フラグをスタックにプッシュするには、スタックでフラグを読み取って変更し、 POPF 1 命令を使用してフラグレジスタに保存します。
POPFではVMおよびRFフラグを設定できないことに注意してください。以前の値は保持されます。同様に、特権レベル0で実行する場合にのみI / O特権レベルを変更でき、少なくともI / O特権レベルと同じ特権レベルで実行する場合にのみ割り込みフラグを変更できます。
脚注1:
最近のCPUでは popf
は非常に遅いことに注意してください。 Agner Fogの最適化ガイドと手順表をご覧ください。カーネルモードでは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を含む)のみが必要な場合は、奇数ですが便利な命令LAHF(ha ha)があります。フラグはAHに登録され、対応するSAHFはAHをフラグに保存します。
特にキャリーフラグについては、x86はCLC、STC、およびCMCを提供し、それぞれキャリーフラグをクリア、設定、および補完します。
最も簡単な方法は、 pushf / popf を使用することです。
eflags
を eax
に移動する場合は、以下のコードを使用します。
pushf # push eflags into stack
pop %eax # pop it into %eax
SETcc
この命令ファミリは、いくつかのフラグ/フラグの組み合わせを観察する別の方法です。
個々のフラグに基づいてバイトの値を設定します。
例: 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:
- LAHF:ステータスフラグをAHに読み込みます
- EFLAGSレジスタの下位バイトをコピーし、Sign、Zero、およびCarryフラグを含めます。
-
フラグのコピーを安全のために変数に保存します
.data saveflags BYTE ? .code lahf ; load flags into AH mov saveflags,ah ; save them into a variable
-
SAHF:AHをステータスフラグに保存します
- AHをEFLAGSレジスタの下位バイトにコピーします
-
以前に保存されたフラグの値を取得
.code mov ah, saveflags ; load save flags into AH sahf ; copy into flags register