1

リアル モードまたはビッグ リアル モードでのみ動作するシステムから API を呼び出すとします。私の API は、現在のシステム モードを表示することになっています。では、現在のモードがリアル モードかビッグ リアル モードかをどのように知ることができますか?

ノート:

  1. ビッグ リアル モードでは、プロテクト モードの有効化ビットCR0が無効になっているため、チェックしても違いはありません。
  2. A20 アドレス ラインが有効になっていても、それがビッグ リアル モードであることを意味するわけではありません。
4

3 に答える 3

1

これを実行すると:

mov ebx, 0x10000
mov al, [ebx]

を取得する#GPと、 のセグメント記述子DSの元の制限は 0xFFFF になります。これは、通常の実アドレス モードと仮想 8086 モードの場合です。

#GPfromが得られない場合mov al, [ebx]、元の制限は 0xFFFF を超えて拡張されています (通常は 0xFFFFFFFF ですが、必ずしもそうとは限りません)。

ところで、v86 モードのチェックは、上記を試す前に行うことができ、おそらく行う必要があります (ホスト OS がハンドラーへの例外を適切に反映しない場合)。を実行smswして取得しcr0.peます。v86 モードでは 1、リアルアドレスモードでは 0 になります。cr0で直接読み取ると、 v86モードでmovが生成されるため、 が推奨される方法です。#GPsmsw

于 2013-03-11T22:19:36.130 に答える
0

ビッグ リアル モードでは、リアル モード アドレスのエイリアシングが失敗していました。ビッグ リアル モードで、DS の値が 0x6000 であるとします。DS のディスクリプタ キャッシュがリロードされているため (ビッグ リアル モードの定義そのもの)、DS:0 の物理アドレスは 0x60000 ではありません。別のセグメント レジスタで 0x60000 にヒットした場合、それは同じメモリ位置にはなりません。

それではレシピをどうぞ。データ セグメントにスクラッチ変数を作成します。offsetDS との相対関係に注意してください。ES に DS-1 の値をロードし、変数の値を変更して、ES:( offset+0x10) で同じ値が得られるかどうかを確認します。偽陰性を防ぐために、2 回行います。

これは、仮想 86 モードを検出しません。また、ES がキャッシュされた記述子を介してハイ メモリを指していた場合も、ES をリロードすると失われます。呼び出し元のコードが、ES がそのままであることに依存しないことを確認してください。

ビッグ リアル モードは、それ自体は CPU モードではありません。「現在ビッグ リアルにいる」というレジスタ ビットはありません。これは、バニラ リアル モードの i386 固有のロジックを使用してハイ メモリにアクセスする方法にすぎません。上記の手順は、DS がそのように処理されているかどうかのみを確認します。実装によっては、DOS エクステンダは、DS をバニラのままにしながら、ES 記述子のリロードを介して大きな実数を実装している可能性があります。ウィキペディアによると、CS でさえこのようにエイリアス化されることがありますが、これは割り込みのためにトリッキーな提案です。

于 2013-03-11T14:24:04.793 に答える