2

私は、書く方法と理解する方法、そしてツールと関連ツールを効果的x86 Assemblyに使用する方法を学ぼうとしています。GDBこれを行うために、私はDDDのフロントエンドとして使用していGDBます。

すべて同じレジスタに格納されているように見える条件フラグ(eflags?)が何であるかを理解するのに苦労しています。レジスタ、アセンブリコード、および関連するCコードを投稿します。助けてくれてありがとう。

指定されたブレークポイントで、レジスタは次のように表示されます。0x293 [CF AF SF IF]

以下は実行中のCコードです。(これは私のコーディングスタイルの例ではありません。GCCにcompl操作を強制的に使用させようとしています。)

int main( int argc, char* argv[] )
{
  int a = 0;
  int b = 2;
  if( a == b ) // There is a breakpoint here!
    goto EQUAL;
  else
    goto NEQUAL;

  EQUAL:
    return 3;

  NEQUAL:
    return 1;
}

以下は、私のマシンがそれを分解したアセンブリです。

Dump of assembler code for function main:
0x0000000000400474 <+0>:     push   %rbp
0x0000000000400475 <+1>:     mov    %rsp,%rbp
0x0000000000400478 <+4>:     mov    %edi,-0x14(%rbp)
0x000000000040047b <+7>:     mov    %rsi,-0x20(%rbp)
0x000000000040047f <+11>:    movl   $0x0,-0x8(%rbp)
0x0000000000400486 <+18>:    movl   $0x2,-0x4(%rbp)
0x000000000040048d <+25>:    mov    -0x8(%rbp),%eax
0x0000000000400490 <+28>:    cmp    -0x4(%rbp),%eax
0x0000000000400493 <+31>:    jne    0x40049d <main+41> # Break point here
0x0000000000400495 <+33>:    nop
0x0000000000400496 <+34>:    mov    $0x3,%eax
0x000000000040049b <+39>:    jmp    0x4004a3 <main+47>
0x000000000040049d <+41>:    nop
0x000000000040049e <+42>:    mov    $0x1,%eax
0x00000000004004a3 <+47>:    leaveq 
0x00000000004004a4 <+48>:    retq   
End of assembler dump.
4

2 に答える 2

3

eflagsレジスタは、それぞれがフラグである単一ビットで構成されています。

フラグを表示するときは、より大きな数値エンティティ(この例では0x293など)に組み合わせるか、それぞれに独自のシンボルを含めることができます(「[CFAF SF IF]」のように、キャリーフラグCF、調整フラグを使用) AF、サインフラグSFおよび割り込みフラグIF。

Intel64およびIA32アーキテクチャソフトウェア開発者マニュアルVol1は、3.4.3章でフラグについて詳しく説明しています。

(アプリケーション開発者にとって)最も重要なものは次のとおりです。

ビット| sym | 名前
------------------
  0 | CF | 運ぶ
  1 | -| (常に1)
  2 | PF | パリティ
  3 | -| (常に0)
  4 | AF | 調整
  5 | -| (常に0)
  6 | ZF | 零
  7 | SF | サイン
  8 | TF | トラップ
  9 | IF | 割り込み
 10 | DF | 方向
 11 | OF | オーバーフロー

これらを例(CF AF SF IF)で組み合わせると、バイナリ値1010010011が得られます。ここで、右端の桁はキャリーフラグで、左端の桁は割り込みフラグです。16進数に変換すると、正確に0x293になります。

于 2012-09-12T20:40:43.633 に答える
2

(R/E)FLAGSレジスタには、次の条件フラグが含まれています。

OF(オーバーフローフラグ)-符号付きオペランドの整数算術演算(、、、、命令など)のオーバーフローを判別するために使用ADDされADCますSUBSBB条件付き分岐/ジャンプ(Jcc命令)は、このフラグを直接調べることができます。

SF(符号フラグ)-最後の整数算術演算の結果が負の値であるかどうかを判別するために使用されます。SFは基本的に結果の符号ビット(=最上位ビット)のコピーです。繰り返しますが、条件付きブランチ/ジャンプはそれを直接調べることができます。

ZF(ゼロフラグ)-最後の整数の算術演算または論理演算の結果が0であるかどうかを判別するために使用されます。条件付きブランチ/ジャンプも直接調べることができます。

CF(キャリーフラグ)-オーバーフローフラグ(OF)と同様に、符号なしオペランドで実行される整数算術演算のオーバーフローを判別するために使用できます。違いに注意してください。CFは符号なし、OFは符号付きです。また、CPUはCFOFの両方を計算することが多く、正しいフラグを調べるのはプログラマーの責任であることに注意してください 。ほとんどの場合、結果は同じ方法で計算され、CPUへのすべてのデータであるため、CPUは符号付きオペランドと符号なしオペランドを区別できません。値をCPUではなく、符号付きまたは符号なしとして解釈するのはプログラマーの責任です。条件付きブランチ/ジャンプは、 CFを直接調べることもできます。

編集CFrotate through carryを使用する命令(RCLおよびRCR)もあります。

(命令との)整数比較のCMP結果、上記の4つのフラグが設定されます。符号なし整数を比較する場合は、ZFCFを調べます。符号付き整数の比較では、 ZFおよび/またはSF + OFペアを調べる必要があります。条件付き分岐/ジャンプ命令(JccJB、、、、JNCなど)JEを参照してくださいJNGE

パリティフラグPFと補助キャリーフラグAFは他の条件フラグですが、ほとんど使用されません。

の残りのビット(R/E)FLAGSは、システムフラグまたは制御フラグのいずれかです。それらのうち、おそらく2つだけ知りたいと思うでしょう。

DF(方向フラグ)-文字列命令の方向を設定するために使用されます。文字列命令は、ブロックメモリコピー、ブロックメモリ比較、ブロックメモリ検索、ブロックメモリフィルなどのメモリへの順次アクセスに使用されます(、、、、、を参照MOVSB/W/D/Q)。このフラグの値は、各反復後にメモリオペランドアドレスをインクリメントするかデクリメントするかを示します。CMPSB/W/D/QSCASB/W/D/QSTOSB/W/D/QLODSB/W/D/Q

IF(割り込みフラグ)-ハードウェア割り込みの処理を有効または無効にするために使用されます。非常に低レベルのプログラミング(ドライバー、OSカーネルなど)を使用する場合は、このフラグを使用する必要があります。

それについてです。詳細はすべて、IntelおよびAMDの公式CPUドキュメントに記載されています。行って、CPUマニュアルをダウンロードしてください。

編集:これらの質問/回答が役立つ場合があります:1、2

また、知っておくと便利です。

  • すべての命令が条件フラグを変更するわけではありません
  • それらを常に変更し、0または1に設定するものもあります
  • それらを不特定の値に設定するものもあり、0または1に依存したり期待したりすることはできません
于 2012-09-12T20:53:22.513 に答える