web-dev-qa-db-ja.com

x86フラグレジスタを直接読み書きする方法は?

私が読んだことから、9つの異なるフラグがあるようです。それらを直接読み取ったり変更したりすることは可能ですか?たとえば、cmp/jmp命令を実行した後にゼロフラグが設定されているかどうかはわかりますが、次のようなことが可能かどうかを尋ねています。

mov eax, flags

か何か。

また、書くために、手で設定することは可能ですか?

19

一部のフラグは、特定の手順で直接設定またはクリアできます。

符号、ゼロ、補助キャリー、パリティ、およびキャリーフラグの読み取りと書き込みには、 [〜#〜] 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を設定またはクリアするシーケンスも簡単で、フラグを反転する場合としない場合があります。

29
Adam Rosenfield

Pushfおよびpopf命令を使用して、フラグをスタックにプッシュし、それらを変更してから、元に戻すことができます。

8
Michael

フラグレジスタの下位バイト(SF、ZF、AF、PF、CFを含む)のみが必要な場合は、フラグレジスタの下位8ビットをロードする奇妙で便利な命令LAHF(ha ha)があります。 AH、およびAHをフラグに格納するための対応するSAHF。

特にキャリーフラグの場合、x86は、キャリーフラグをクリア、設定、および補完するために、それぞれCLC、STC、およびCMCを提供します。

5
I. J. Kennedy

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:

アサーション付きの実行可能なGitHubアップストリーム

最も簡単な方法はpushf/popfを使用することです。

eflagseaxに移動する場合は、以下のコードを使用してください。

pushf                  # Push eflags into stack
pop %eax               # pop it into %eax
2
Jiwon
  • LAHF:ステータスフラグをAHにロードします
  • サイン、ゼロ、キャリーフラグを含むEFLAGSレジスタの下位バイトをコピーします。
  • フラグのコピーを保管のために変数に保存します

    .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 
    
0
israa