8

学校では、ブートストラッププログラムを使用して、オペレーティングシステムなしでスタンドアロンプ​​ログラムを実行しています。私はこのプログラムを研究してきましたが、プロテクトモードを有効にすると、プログラム内でオペコードとオペランドをデータとして直接アセンブルすることで、はるかに大きなジャンプが実行されます。これはGNUアセンブラ用でした:


         /* this code immediately follows the setting of the PE flag in CR0 */

.byte   0x66, 0xEA
.long   TARGET_ADDRESS
.word   0x0010          /* descriptor #2, GDT, RPL=0 */

まず第一に、なぜ(命令ニーモニックの代わりに)これを実行したいのでしょうか?

私はIntelのマニュアルを見てきましたが、それでもコードに少し混乱しています。具体的には、ボリューム2A、3-549ページに、オペコードの表があります。関連するエントリ:

EA * cp * JMP ptr16:32Inv。有効なジャンプファー、アブソリュート、アドレス
オペランド

実際のオペコードは明らかですが、最初のバイトである0x66は私を混乱させます。Intelマニュアルの表を参照すると、cpは明らかに6バイトのオペランドが続くことを意味します。そして明らかに次の2行に6バイトが続きます。0x66は、「オペランドサイズのオーバーライドプレフィックス」をエンコードします。これはテーブルのcpと何の関係がありますか?cpには16進値があると思っていましたが、代わりにこのオーバーライドプレフィックスがあります。誰かが私のためにこれを片付けてくれませんか?

これがodからのダンプです:

c022 ** ea66 0000 0001 0010 ** ba52 03f2 c030

TARGET_ADDRESSは0x00010000として定義されました。

また、最後の2バイトの重要性にも少し混乱しています。しかし、それはまったく別の質問のようです。かなり遅くなっていて、コードとIntelのマニュアルを何時間も見つめているので、自分の主張が理解できたと思います。

見てくれてありがとう!

4

3 に答える 3

12

0x66 は、JMP (0xEA) が 6 バイトを参照していることを示します。デフォルトは、リアル モードでは 64K (16 ビット)、プロテクト モードでは 32 ビットです (よく思い出せば)。増加すると、セグメント記述子、GDT または LDT のいずれかのセグメントのインデックスも含まれます。つまり、このコードは、伝統的に「ロング ジャンプ」と呼ばれるものを作成していることを意味します。 x86 アーキテクチャ。この場合、セグメントは GDT の 2 番目のエントリを指します。そのプログラムを前に見ると、セグメントの開始アドレスと長さに関して GDT がどのように定義されているかがわかります (インテルのマニュアルを参照して、GDT と LDT テーブル、各セグメントを説明する 32 ビット エントリを調べてください)。

于 2009-02-13T07:59:05.090 に答える
2

私はこれに少し遭遇します。一部のアセンブラは、LABELにのみジャンプします。この場合、人は特定のハードコードされたオフセットに絶対ジャンプしたいと考えています。jmp TARGET_ADDRESSは機能しないと私は推測しているので、この問題を回避するためにバイトとして配置するだけです。

于 2009-05-14T16:58:29.153 に答える
0

0x66 は、現在のコード セグメント サイズのオペランド サイズ オーバーライドを指定します。現在のコード サイズが 16 ビットであると仮定すると、新しい命令ポインタは 16 ビットではなく 32 ビットになります。現在のコード セグメント サイズが 32 ビットの場合、0x66 はターゲット命令ポインターを 16 ビットとしてレンダリングします。現在のコード サイズ属性は、使用中の CS セレクターと GDT/LDT テーブルからロードされたその属性によって異なります。リアル モードでは、「非リアル」モードの特殊なケースを除いて、コード セグメントのサイズは通常 16 ビットです。

于 2014-08-19T08:58:18.387 に答える