19

Intel および AT&T 構文でのメモリ アドレッシングの一般的な形式は次のとおりです。

[base + index*scale + disp]
disp(base, index, scale)

私の質問は次のとおりです。

  • 任意のレジスタにすることがbaseできますか?index
  • scale1、2、4 、および 8 (デフォルトは 1) のどの値を取ることができますか?
  • indexと は互換性がありますかdisp(唯一の違いindexはレジスタでdispあり、即値であるということです)?
4

1 に答える 1

15

これは Intel のマニュアルに記載されています。

3.7.5 オフセット
の指定 メモリ アドレスのオフセット部分は、静的な値 (変位と呼ばれる) として直接指定するか、次のコンポーネントの 1 つ以上で構成されるアドレス計算によって指定できます。

  • 変位— 8、16、または 32 ビットの値。
  • Base — 汎用レジスターの値。
  • インデックス— 汎用レジスタの値。[ESP/RSP は不可]
  • 倍率— インデックス値で乗算される 2、4、または 8 の値。

これらの要素を加算したオフセットを実効アドレスと呼びます。

スケール係数は、1、2、4、または 8 のスケール係数に対して、2 ビットのシフト カウント (0,1,2,3) としてエンコードされ*1ます。書く(%edi, %edx); それはと同等です(%edi, %edx, 1)


AT&T の構文では、disp(base, index, scale)定数は括弧の外に出ます。一部の Intel 構文アセンブラでは、 のような構文も許可されますが、許可され1234[ebx]ないものもあります。しかし、AT&T の構文は厳格です。アドレッシング モードのすべてのコンポーネントは、適切な場所にしか配置できません。例えば:

movzwl  foo-0x10(,%edx,2), %eax

アドレス から、EAX へのゼロ拡張 16 ビット (「ワード」) ロードを行いますfoo-0x10 + edx*2。EDX は、スケール係数 2 のインデックス レジスタです。ベース レジスタはありません。 foo-0x10はどちらも変位の一部であり、どちらもリンク時定数です。 fooは、リンカが入力して 0x10 を減算するシンボル アドレスです (-0x10アセンブル時のオフセットのため)。

選択できる場合は、スケール 1 のインデックスの代わりにベースのみを使用します。インデックスは、エンコードするために SIB バイトを必要とするため、命令が長くなります。そのため、コンパイラは .NET8(%ebp)ではなく、スタック メモリにアクセスするようなアドレッシング モードを選択します8(,%ebp)

メモリ位置の内容の参照も参照してください。(x86 アドレッシング モード)を参照して、いつベース、および/またはインデックス、および/またはディスプレイスメントを使用するかについての詳細を確認してください。


16 ビット ディスプレースメントは、16 ビット アドレッシング モードでのみエンコード可能です。このモードは、スケール ファクターを含めることができない別の形式を使用し、ベースまたはインデックスにできるレジスタの選択肢が非常に限られています。

したがって、次のようなモードで1234(%edx)は、1234 をdisp3232 ビット マシン コードで 32 ビットとしてエンコードする必要があります。

-128 からのバイト オフセット .. +127 は、短い形式の 8 ビット エンコーディングを使用できます。アセンブラは、変位の最短の有効なエンコーディングを使用して、これを処理します。


これはすべて、64 ビット アドレッシング モードの 64 ビット モードでも同じであり、disp32 も disp8 と同様に 64 ビットに符号拡張されます。

于 2015-01-14T06:51:27.893 に答える