web-dev-qa-db-ja.com

レジスタ%eizとは何ですか?

objdumpを使用してダンプした次のアセンブリコードでは、次のようになっています。

lea    0x0(%esi,%eiz,1),%esi

レジスターとは%eiz?上記のコードはどういう意味ですか?

53

GCC LEA EIZを使用する理由 :を参照してください。

どうやら%eizは、常にゼロと評価される疑似レジスタです(MIPSのr0のように)。

.。

私は最終的に、binutilsの第一人者であるIan LanceTaylorによるメーリングリストの投稿を見つけました。 GCCがコードストリームにNOP命令を挿入して、適切な配置などを保証する場合があります。 NOP命令は1バイトかかるので、必要なだけ追加できると思います。しかし、Ian Lance Taylorによると、チップが1つの長い命令を実行する方が、多くの短い命令よりも高速です。したがって、7つのNOP命令を挿入するのではなく、代わりに1つの奇妙なLEAを使用します。これは、7バイトを使用し、意味的にはNOPと同等です。

55
Sinan Ünür

(ゲームに非常に遅れていますが、これは興味深い追加のように見えました):これはレジスターではなく、Intel命令エンコーディングの癖です。 ModRMバイトを使用してメモリからロードする場合、8つの可能なレジスタを格納するためにレジスタフィールドに3ビットが使用されます。ただし、ESP(スタックポインタ)が「なる」場所は、プロセッサによって「SIBバイトがこの命令の後に続く」と解釈されます(つまり、拡張アドレッシングモードであり、 ESP)。作成者だけが知っている理由により、GNUアセンブラは、常にこの「レジスタが存在するゼロ」を「%eiz」レジスタとして表していました。Intel構文はそれを削除するだけです。 。

23
Andy Ross

Andy Rossは、根底にある推論の多くを提供していますが、残念ながら間違っているか、少なくとも技術的な詳細について混乱しています。 _(%esp)_としてデコードされる代わりに、ModR/Mバイトだけでは_(%esp)_だけの実効アドレスをエンコードできないことは事実です。これは、SIBバイトも含まれていることを通知するために使用されます。ただし、_%eiz_疑似レジスタは、SIBバイトが使用されたことを表すためにSIBバイトで常に使用されるとは限りません。

SIBバイト(スケール/インデックス/ベース)には3つの部分があります:インデックス(スケールが適用される_%eax_や_%ecx_などのレジスタ)、スケール(2の累乗)インデックスレジスタに乗算される1から8まで)、およびベース(スケーリングされたインデックスに追加される別のレジスタ)。これは、add %al,(%ebx,%ecx,2)(マシンコード:_00 04 4b_ --opcode、modr/m、sib(SIBバイトが使用されていても%eizレジスタがないことに注意してください))(またはIntel構文では、「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命令の代わりに実行されます。

14
user3196531