2012-11-01 11 views
7

GASの.code16の動作を理解しようとしています。 マニュアルからは、32ビットのオペランドまたは命令の場合は16ビットセクションで、66Hのオペランドのオーバーライドプレフィックスが命令エンコーディングのために生成されます。その意味ですか16ビットモードのオペランドサイズ接頭辞

.code16 
movw %eax, %ebx 

はこのようなモードで有効ですか?その後、コードは16ビットプロセッサでは実行できませんか?

+0

「w」サフィックスは2バイトの移動を示すため、これは合法ではありません。しかし、 'movl%eax、%eax'は合法です。 – fuz

答えて

10

これらは80386+の法的な指示です。 80386からは、operandsizeおよびaddresssize-override接頭辞を使用できます。 これらの接頭辞は、16ビットアドレスモードおよび32ビットアドレスモードと組み合わせて使用​​できます。さらに、実際のアドレスモード、プロテクトモード、バーチャル86モードでも使用できます。これらの接頭辞は、コードセグメント内の1つの命令のデフォルトのオペランドサイズおよび/またはアドレスサイズを反転します。デフォルトのoperandizeとaddresssizeは、コードセグメント記述子のDフラグで指定されます(GDT/LDTがない場合は、BIOSのPOSTプロセスが完了した後、16ビットのアドレスモードになります)。

16ビットのアドレスモードでは、32ビットのオペランドおよび/または32ビットのアドレスを使用する場合は、これらのプレフィックスを追加する必要があります。これらの接頭辞がなければ、16ビットのアドレスモードでのみ16ビットのアドレス/オペランドを使用できます。

32ビットのアドレスモードでは、32ビットのオペランドまたは32ビットのアドレスを使用する場合は、コードからこれらのプレフィックスを除外する必要があります。これらの接頭辞をコードに追加すると、32ビットのアドレスモードで16ビットのアドレス/オペランドを使用できます。

BLOCKQUOTE インテル:

命令プレフィックスは、コードセグメントのデフォルトオペランドサイズおよびアドレスサイズを上書きするために使用することができます。これらのプレフィックスは、保護モードと仮想8086モードのほか、実アドレスモードでも使用できます。オペランドサイズまたはアドレスサイズプレフィックスは、命令の持続時間だけサイズを変更します。

次の2つの命令プレフィックスが一つのセグメント内の32ビットおよび16ビット演算の混合可能:アドレスサイズプレフィックス(67H)•オペランドサイズプレフィックス(66H) ます

これらのプレフィックスをコードセグメント記述子のDフラグによって選択されたデフォルトサイズを反転します。たとえば、プロセッサは(MOV mem、reg)命令を次の4つの方法のいずれかで解釈することができます。 •32ビットコードセグメント内: - 32ビットレジスタからメモリに32ビット有効住所。 - オペランドサイズのプレフィックスが先行する場合、32ビットの実効アドレスを使用して16ビットレジスタからメモリに16ビットを移動します。 - アドレス・サイズ・プレフィックスが先行する場合は、32ビット・レジスタから16ビット実効アドレスを使用してメモリに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プロセッサとの下位互換性 - コードセグメントがIntel 8086またはIntel 286プロセッサで実行可能でなければならない場合は、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を超えることはできません。

アセンブラ使用法: 実アドレスモードで実行されるコードセグメントが定義されている場合は、USE 16属性に設定する必要があります。このコードセグメント内の命令(たとえばMOV EAX、EBX)で32ビットオペランドが使用されている場合、アセンブラは自動的に命令のオペランドプレフィックスを生成し、プロセッサに32ビット演算を実行させます。デフォルトのコードセグメント属性は16ビットです。

32ビットのオペランドプレフィックスを使用すると、実アドレスモードのプログラムで32ビットの汎用レジスタ(EAX、EBX、ECX、EDX、ESP、EBP、ESI、およびEDI)を使用できます。

セグメントレジスタと32ビット汎用レジスタ レジスタの間で32ビットモードでデータを移動する場合、Pentium Proプロセッサでは16ビットのオペランドサイズの接頭辞を使用する必要はありません。ただし、一部のアセンブラではこのプレフィックスが必要です。プロセッサは、汎用レジスタの最下位16ビット( )がデスティネーションオペランドまたはソースオペランドであるとみなします。 の値をセグメントセレクタから32ビットレジスタに移動すると、プロセッサは の2つの上位バイトを0で埋めます。

BLOCKQUOTE AMD:

3.3.2。 32ビットと16ビットのアドレスとオペランドのサイズ プロセッサは、32ビットまたは16ビットのアドレスとオペランドのサイズに設定できます。 32ビットの アドレスとオペランドサイズの場合、最大リニアアドレスまたはセグメントオフセットはFFFFFFFFH (2^32-1)であり、オペランドサイズは通常8ビットまたは32ビットです。 16ビットのアドレスとオペランドサイズの場合、 最大リニアアドレスまたはセグメントオフセットはFFFFH(2^16-1)で、オペランドサイズは通常 8ビットまたは16ビットです。 32ビットアドレッシングを使用する場合、論理アドレス(またはfarポインタ)は16ビットのセグメント セレクタと32ビットオフセットで構成されます。 16ビットアドレッシングを使用する場合は、16ビットのセグメントセレクタ と16ビットのオフセットで構成されています。 命令プレフィックスを使用すると、プログラム内のデフォルトアドレスおよび/またはオペランドサイズを から一時的にオーバーライドできます。 プロテクトモードで動作している場合、現在実行中のコード セグメントのセグメント記述子が、デフォルトアドレスとオペランドサイズを定義します。セグメント記述子は、システムコード の構造体で、アプリケーションコードから通常は見えません。アセンブラディレクティブを使用すると、デフォルトの アドレッシングとオペランドサイズをプログラムに選択できます。次に、アセンブラおよび他のツールは、 をコードセグメントのセグメント記述子を適切に設定します。 実アドレスモードで動作する場合、デフォルトのアドレッシングとオペランドサイズは16ビットです。 アドレスサイズオーバーライドは、32ビットアドレッシングを有効にするために実アドレスモードで使用できます。ただし、最大許容32ビットのリニアアドレス は、まだ000FFFFFH(2^20-1)です。

3.6。オペランドサイズとアドレスサイズの属性 プロセッサが保護モードで実行されている場合、すべてのコードセグメントには、デフォルトのオペランドサイズの 属性とアドレスサイズ属性があります。これらの属性は、コードセグメントのセグメント記述子のD(デフォルトサイズ) フラグで選択されます(Intelアーキテクチャソフトウェア開発者マニュアル第3巻、第3章、保護モードメモリ の管理を参照)。 D フラグが設定されると、32ビットのオペランドサイズとアドレスサイズの属性が選択されます。フラグがクリアされている場合は、 16ビットサイズの属性が選択されます。プロセッサが実アドレスモード、 仮想8086モード、またはSMM(システム管理モード)で実行されている場合、デフォルトのオペランドサイズおよびアドレスサイズ属性は常に16 ビットです。 operand-size属性は、命令が動作するオペランドのサイズを選択します。 16ビットオペランドサイズ属性が有効な場合、オペランドは一般に8ビットまたは16ビットのいずれかになり、 は32ビットオペランドサイズ属性が有効な場合、オペランドは通常8ビットまたは32ビットです。 address-size属性は、メモリをアドレス指定するために使用されるアドレスのサイズを選択します(16ビットまたは32 ビット)。 16ビットのアドレスサイズ属性が有効な場合、セグメントのオフセットと変位は16 ビットです。この制限により、64 KBにアドレス可能なセグメントのサイズが制限されます。 32ビットのアドレスサイズ属性が有効な場合、セグメントオフセットと変位は32ビットであり、 セグメントの最大4 GByteをアドレス指定できます。 命令にオペランドサイズまたはアドレスサイズプレフィックスを追加することで、特定の 命令に対して、デフォルトのオペランドサイズ属性および/またはアドレスサイズ属性を上書きすることができます(詳細は、 「命令プレフィックス」を参照)。 Intelアーキテクチャソフトウェア開発者マニュアル、 第3巻)。このプレフィックスの効果は、それがアタッチされている命令にのみ適用されます。 表3-1に、Dフラグの設定とオペランドサイズおよびアドレスサイズ接頭辞によって有効なオペランドサイズとアドレスサイズ(保護モードで実行する場合) を示します。

Dirk