次のアセンブリコードでは、以下を使用してダンプしましたobjdump
。
lea 0x0(%esi,%eiz,1),%esi
レジスターとは何%eiz
ですか?上記のコードはどういう意味ですか?
次のアセンブリコードでは、以下を使用してダンプしましたobjdump
。
lea 0x0(%esi,%eiz,1),%esi
レジスターとは何%eiz
ですか?上記のコードはどういう意味ですか?
なぜGCCLEAEIZなのかを参照してください。:
どうやら( MIPS
%eiz
のように)常にゼロと評価される疑似レジスタです。r0
..。
私は最終的に、binutilsの第一人者であるIanLanceTaylorによる答えを明らかにするメーリングリストの投稿を見つけました。GCCは、コードストリームにNOP命令を挿入して、適切な配置などを保証する場合があります。NOP命令は1バイトかかるので、必要なだけ追加できると思います。しかし、Ian Lance Taylorによると、チップが1つの長い命令を実行する方が、多くの短い命令よりも高速です。したがって、7つのNOP命令を挿入するのではなく、代わりに1つの奇妙なLEAを使用します。これは、7バイトを使用し、意味的にはNOPと同等です。
(ゲームに非常に遅れていますが、これは興味深い追加のように見えました):これはレジスターではなく、Intel命令エンコーディングの癖です。ModRMバイトを使用してメモリからロードする場合、8つの可能なレジスタを格納するためにレジスタフィールドに3ビットが使用されます。ただし、ESP(スタックポインタ)が「存在する」場所は、代わりにプロセッサによって「SIBバイトがこの命令に従う」と解釈されます(つまり、ESPへの参照ではなく、拡張アドレッシングモードです)。作者だけが知っている理由で、GNUアセンブラは常にこの「レジスタがなければゼロ」を「%eiz」レジスタとして表現してきました。Intel構文はそれを削除するだけです。
Andy Rossは、根底にある推論の多くを提供していますが、残念ながら間違っているか、少なくとも技術的な詳細について混乱しています。(%esp)
の実効アドレスは、としてデコードされるのではなく、ModR / Mバイトだけではエンコードできないことは事実です。これは(%esp)
、SIBバイトも含まれていることを通知するために使用されます。ただし、%eiz
SIBバイトが使用されたことを表すために、疑似レジスタがSIBバイトとともに常に使用されるとは限りません。
SIBバイト(スケール/インデックス/ベース)には、インデックス(スケールが適用されるなどのレジスタ)、スケール(インデックスレジスタに乗算される1から8までの2の累乗)の3つの部分があり%eax
ます%ecx
。 by)、およびベース(スケーリングされたインデックスに追加される別のレジスタ)。これにより、add %al,(%ebx,%ecx,2)
(マシンコード:00 04 4b
-opcode、modr / m、sib(SIBバイトが使用されていても%eizレジスタがないことに注意してください))(またはIntel構文では "add BYTE PTR [ecx * 2 + ebx]、al ")。
ただし、%esp
SIBバイトのインデックスレジスタとして使用することはできません。このオプションを許可する代わりに、Intelは、スケーリングやインデックス付けなしでベースレジスタをそのまま使用するオプションを追加します。したがって、add %al,(%ecx)
(マシンコード:00 01
-opcode、modr / m)とadd %al,(%ecx)
(マシンコード:00 04 21
-opcode、modr / m、sib)の場合を明確にするために、代わりに代替構文add %al,(%ecx,%eiz,1)
が使用されます(またはIntel構文の場合:) add BYTE PTR [ecx+eiz*1],al
。
また、Sinanがリンクしている記事で説明されているように、この特定の命令(lea 0x0(%esi,%eiz,1),%esi
)は単にマルチバイトnop(と同等esi = &*esi
)として使用されるため、複数のnop命令ではなく、1つのnopのような命令を実行するだけで済みます。