のGASの動作を理解しようとしてい.code16
ます。
マニュアルによると、16 ビット セクションのようです。32 ビット オペランドまたは命令の場合、命令エンコーディング用に 66H オペランド オーバーライド プレフィックスが生成されます。それは〜を意味しますか
.code16
movw %eax, %ebx
そのようなモードでは合法ですか?その後、コードは 16 ビット プロセッサで実行できませんか?
のGASの動作を理解しようとしてい.code16
ます。
マニュアルによると、16 ビット セクションのようです。32 ビット オペランドまたは命令の場合、命令エンコーディング用に 66H オペランド オーバーライド プレフィックスが生成されます。それは〜を意味しますか
.code16
movw %eax, %ebx
そのようなモードでは合法ですか?その後、コードは 16 ビット プロセッサで実行できませんか?
これらは80386+の法的指示です。
80386以降、プレフィックスを使用
operandsize-
およびaddresssize-
オーバーライドできます。これらのプレフィックスは、16ビットアドレスモードおよび32ビットアドレスモードと組み合わせて使用できます。さらに、リアルアドレスモード、プロテクトモードおよび仮想86モードで使用できます。これらのプレフィックスは、コードセグメント内の1つの命令のデフォルトのオペランドサイズやアドレスサイズを逆にします。デフォルトのオペランドサイズとアドレスサイズは、コードセグメント記述子のDフラグで指定されます(または、GDT / LDTがない場合は、BIOSのPOSTプロセスが完了した後に16ビットアドレスモードになります)。
16ビットアドレスモードでは、32ビットオペランドや32ビットアドレスを使用する場合は、これらのプレフィックスを追加する必要があります。これらのプレフィックスがないと、16ビットアドレスモードでのみ16ビットアドレス/オペランドを使用できます。
32ビットアドレスモードでは、32ビットオペランドや32ビットアドレスを使用する場合は、コードからこれらのプレフィックスを除外する必要があります。そして、これらのプレフィックスをコードに追加すると、32ビットアドレスモードで16ビットアドレス/オペランドを使用できます。
Intel:
命令プレフィックスを使用して、コードセグメントのデフォルトのオペランドサイズとアドレスサイズを上書きできます。これらのプレフィックスは、リアルアドレスモードだけでなく、保護モードと仮想8086モードでも使用できます。オペランドサイズまたはアドレスサイズのプレフィックスは、命令の期間中のみサイズを変更します。
次の2つの命令プレフィックスにより、1つのセグメント内で32ビットと16ビットの演算を混在させることができます。
- オペランドサイズのプレフィックス(66H)
- アドレスサイズプレフィックス(67H)
これらのプレフィックスは、コードセグメント記述子のDフラグによって選択されたデフォルトサイズを逆にします。たとえば、プロセッサは(MOV mem、reg)命令を次の4つの方法のいずれかで解釈できます。
32ビットコードセグメントの場合:
- 32ビットの実効アドレスを使用して、32ビットを32ビットレジスタからメモリに移動します。
- オペランドサイズのプレフィックスが前に付いている場合、32ビットの実効アドレスを使用して16ビットを16ビットレジスタからメモリに移動します。
- アドレスサイズプレフィックスが前に付いている場合、16ビットの実効アドレスを使用して32ビットを32ビットレジスタからメモリに移動します。
- アドレスサイズプレフィックスとオペランドサイズプレフィックスの両方が前に付いている場合、16ビットの実効アドレスを使用して16ビットを16ビットレジスタからメモリに移動します。
16ビットコードセグメントの場合:
- 16ビットの実効アドレスを使用して16ビットを16ビットレジスタからメモリに移動します。
- オペランドサイズのプレフィックスが前に付いている場合、16ビットの実効アドレスを使用して32ビットを32ビットレジスタからメモリに移動します。
- アドレスサイズプレフィックスが前に付いている場合、32ビットの実効アドレスを使用して16ビットを16ビットレジスタからメモリに移動します。
- アドレスサイズのプレフィックスとオペランドサイズのプレフィックスの両方が前に付いている場合、32ビットの実効アドレスを使用して32ビットを32ビットレジスタからメモリに移動します。
前の例は、命令が16ビットまたは32ビットのセグメントにあるかどうかに関係なく、任意の命令がオペランドサイズとアドレスサイズの任意の組み合わせを生成できることを示しています。コードセグメントの16ビットまたは32ビットのデフォルトの選択は、通常、次の基準に基づいています。
- パフォーマンス—可能な場合は常に32ビットのコードセグメントを使用します。これらは、P6ファミリプロセッサでは16ビットコードセグメントよりもはるかに高速に実行され、以前のIA-32プロセッサではやや高速です。
- コードセグメントが実行されるオペレーティングシステム—オペレーティングシステムが16ビットオペレーティングシステムの場合、32ビットプログラムモジュールをサポートしていない可能性があります。
- 動作モード—コードセグメントがリアルアドレスモード、仮想8086モード、またはSMMで実行されるように設計されている場合は、16ビットのコードセグメントである必要があります。
- 以前のIA-32プロセッサとの下位互換性—コードセグメントをIntel8086またはIntel286プロセッサで実行できる必要がある場合は、16ビットのコードセグメントである必要があります。
コードセグメント記述子のDフラグは、コードセグメントの命令のデフォルトのオペランドサイズとアドレスサイズを決定します。(セグメント記述子を使用しないリアルアドレスモードと仮想8086モードでは、デフォルトは16ビットです。)Dフラグが設定されたコードセグメントは32ビットセグメントです。Dフラグがクリアされたコードセグメントは16ビットセグメントです。
実行可能コードセグメント。このフラグはDフラグと呼ばれ、セグメント内の命令によって参照される実効アドレスとオペランドのデフォルトの長さを示します。フラグが設定されている場合、32ビットアドレスと32ビットまたは8ビットのオペランドが想定されます。明確な場合は、16ビットアドレスと16ビットまたは8ビットのオペランドが想定されます。命令プレフィックス66Hは、デフォルト以外のオペランドサイズを選択するために使用でき、プレフィックス67Hは、デフォルト以外のアドレスサイズを選択するために使用できます。
32ビットのオペランドプレフィックスをリアルアドレスモードプログラムで使用して、32ビット形式の命令を実行できます。このプレフィックスにより、リアルアドレスモードプログラムでプロセッサの32ビット汎用レジスタを使用することもできます。32ビットアドレスプレフィックスはリアルアドレスモードプログラムで使用でき、32ビットオフセットを可能にします。
Intel386プロセッサで始まるIA-32プロセッサは、アドレスオーバーライドプレフィックスを使用して32ビットオフセットを生成できます。ただし、リアルアドレスモードでは、例外を発生させることなく、32ビットオフセットの値がFFFFHを超えることはできません。
アセンブラの使用法:
リアルアドレスモードで実行するコードセグメントを定義する場合は、USE16属性に設定する必要があります。このコードセグメントの命令(たとえば、MOV EAX、EBX)で32ビットのオペランドが使用されている場合、アセンブラは、プロセッサに32ビット操作を実行させる命令のオペランドプレフィックスを自動的に生成します。デフォルトのコードセグメント属性は16ビットです。
32ビットのオペランドプレフィックスにより、リアルアドレスモードプログラムは32ビットの汎用レジスタ(EAX、EBX、ECX、EDX、ESP、EBP、ESI、およびEDI)を使用できます。
32ビットモードでセグメントレジスタと32ビット汎用レジスタ間でデータを移動する場合、PentiumProプロセッサでは16ビットのオペランドサイズのプレフィックスを使用する必要はありません。ただし、一部のアセンブラはこのプレフィックスを必要とします。プロセッサは、汎用レジスタの最下位16ビットがデスティネーションオペランドまたはソースオペランドであると想定します。セグメントセレクタから32ビットレジスタに値を移動する場合、プロセッサはレジスタの上位2バイトをゼロで埋めます。
3.3.2。32ビットと16ビットのアドレスとオペランドのサイズ
プロセッサは、32ビットまたは16ビットのアドレスおよびオペランドサイズ用に構成できます。32ビットのアドレスおよびオペランドサイズの場合、最大線形アドレスまたはセグメントオフセットはFFFFFFFFH(2 ^ 32-1)であり、オペランドサイズは通常8ビットまたは32ビットです。16ビットのアドレスおよびオペランドサイズの場合、最大線形アドレスまたはセグメントオフセットはFFFFH(2 ^ 16-1)であり、オペランドサイズは通常8ビットまたは16ビットです。
32ビットアドレス指定を使用する場合、論理アドレス(またはファーポインター)は、16ビットセグメントセレクターと32ビットオフセットで構成されます。16ビットアドレス指定を使用する場合、16ビットセグメントセレクタと16ビットオフセットで構成されます。命令プレフィックスを使用すると、プログラム内からデフォルトのアドレスやオペランドサイズを一時的に上書きできます。
プロテクトモードで動作している場合、現在実行中のコードセグメントのセグメント記述子は、デフォルトのアドレスとオペランドサイズを定義します。セグメント記述子は、通常はアプリケーションコードからは見えないシステムデータ構造です。アセンブラディレクティブを使用すると、プログラムのデフォルトのアドレス指定とオペランドサイズを選択できます。次に、アセンブラおよびその他のツールは、コードセグメントのセグメント記述子を適切に設定します。
リアルアドレスモードで動作している場合、デフォルトのアドレス指定とオペランドサイズは16ビットです。アドレスサイズオーバーライドをリアルアドレスモードで使用して、32ビットアドレス指定を有効にすることができます。ただし、最大許容32ビット線形アドレスは000FFFFFH(2 ^ 20-1)のままです。
3.6。オペランドサイズとアドレスサイズの属性
プロセッサがプロテクトモードで実行されている場合、すべてのコードセグメントにはデフォルトのオペランドサイズ属性とアドレスサイズ属性があります。これらの属性は、コードセグメントのセグメント記述子でD(デフォルトサイズ)フラグを使用して選択されます( 『Intel Architecture Software Developer's Manual、Volume 3』の第3章「プロテクトモードメモリ管理」を参照)。Dフラグが設定されている場合、32ビットのオペランドサイズとアドレスサイズの属性が選択されます。フラグがクリアされると、16ビットサイズの属性が選択されます。プロセッサがリアルアドレスモード、仮想8086モード、またはSMM(システム管理モード)で実行されている場合、デフォルトのオペランドサイズとアドレスサイズの属性は常に16ビットです。
オペランドサイズ属性は、命令が動作するオペランドのサイズを選択します。16ビットのオペランドサイズ属性が有効な場合、オペランドは通常8ビットまたは16ビットのいずれかになり、32ビットのオペランドサイズ属性が有効な場合、オペランドは通常8ビットまたは32ビットになります。
address-size属性は、メモリのアドレス指定に使用されるアドレスのサイズ(16ビットまたは32ビット)を選択します。16ビットのアドレスサイズ属性が有効な場合、セグメントのオフセットと変位は16ビットです。この制限により、64Kバイトにアドレス指定できるセグメントのサイズが制限されます。32ビットのaddress-size属性が有効な場合、セグメントのオフセットと変位は32ビットであり、最大4Gバイトのセグメントをアドレス指定できます。
デフォルトのオペランドサイズ属性および/またはアドレスサイズ属性は、オペランドサイズおよび/またはアドレスサイズプレフィックスを命令に追加することにより、特定の命令に対してオーバーライドできます(Intelアーキテクチャソフトウェアの第2章の「命令プレフィックス」を参照)。開発者マニュアル、第3巻)。このプレフィックスの効果は、アタッチされている命令にのみ適用されます。
表3-1に、Dフラグの設定とオペランドサイズおよびアドレスサイズのプレフィックスに応じた実効オペランドサイズとアドレスサイズ(プロテクトモードで実行する場合)を示します。