これは 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 をdisp32
32 ビット マシン コードで 32 ビットとしてエンコードする必要があります。
-128 からのバイト オフセット .. +127 は、短い形式の 8 ビット エンコーディングを使用できます。アセンブラは、変位の最短の有効なエンコーディングを使用して、これを処理します。
これはすべて、64 ビット アドレッシング モードの 64 ビット モードでも同じであり、disp32 も disp8 と同様に 64 ビットに符号拡張されます。