私の質問は次のとおりです。コードを 16、32、または 64 ビットにする正確な理由は何ですか?16 ビット アプリケーションに見られる非互換性の問題の原因は何ですか?
まあ: 明白な答えは: 8、16、32、または 64 ビット レジスタを使用するそのプログラムに依存します。明らかですが、そうではありません。MS DOS で実行されているプログラムは、プロセッサがサポートしている場合、8、16、または 32 ビットのレジスタを使用できます。別の方法として、Windows プログラムは、32 ビット レジスタと (プロセッサと OS がサポートしている場合) 64 ビット レジスタを使用する以外に、8 ビット レジスタと 16 ビット レジスタを使用できます (実際に使用します)。
私が思うに、問題は次のようなものであるべきだと思います: プログラムを正確に DOS や Windows 32 ビット、または Windows 64 ビットで実行できるようにするものは何か。
まず、実行ファイルの構造。32 ビットまたは 64 ビットの Windows 実行可能ファイルは、16 ビットの実行可能ファイルと同じではありません。Windows はいわゆる "Portable Executable" (PE の略) を使用します。MS DOS は、.COM ファイル (CP/M から継承) と .EXE ファイル (MZ 実行可能ファイルとも呼ばれます) の両方を使用します。
2番目:プログラムがメモリに格納されて実行を開始すると、プログラムがそこにあると予想される環境があります。たとえば、さまざまなタスクの実行を担当するINTなどの特別な命令によってアクセスされる一連の関数呼び出しです。コンソールに文字を出力したり、ファイルを開いて読んだり、その他多数。
3 番目: MS DOS アプリケーションは、メモリ内のいくつかの構造体が特定のメモリ アドレスにあることを想定しています。たとえば、画面メモリ。また、特定の I/O アドレスにいくつかの I/O デバイスが存在することも想定しています。いわゆる「動作の悪い」アプリケーションの多くは、BIOS や DOS を使用して画面に印刷するのではなく、画面メモリに直接書き込み、出力を高速化します。Turbo Pascal、Turbo Basic、またはおそらく Turbo C コンパイラーの設定を覚えています。これは、プログラマーがコンソール出力機能を選択して、BIOS を経由するか、ハードウェアに直接アクセスできるようにするためのものです。
4 つ目: プログラムは、プロセッサが特定の方法で動作することを期待しています。16 ビット DOS プログラムは、いわゆるx86 プロセッサのリアル モードを使用するように設計されています。このモードは、このモードの最も明確な機能を示すために、メモリ アドレスの特定のビジョンを課します。プロセッサをプロテクト モードにする 32 ビット OS の登場により、プロテクト モードでのメモリ アドレスの動作方法がリアル モードでの動作方法と大きく異なるため、リアル モード プログラムは動作しません。
MZ 実行可能ファイルを実行する OS には、これらのファイル用のある種のローダー(最初のポイントに準拠するため)と、アプリケーションが動作する環境を模倣する必要がある環境(残りのポイントに準拠するため) が必要です。Linux の世界では、これらのコンポーネントはパーソナリティと呼ばれるものの一部です(Linux が FreeBSD などの他の OS からコードを実行する方法であり、コードが両方のプラットフォームで同じプロセッサを対象としている場合)。Windows の世界では、これはサブシステムとして知られています。たとえば、Windows XP と Windows 7 には、Win32サブシステムとDOSサブシステムがあります。古いバージョンの Windows (おそらく Windows NT 3.5 または NT 4.0) にはOS/2がありました。OS/2 16 ビット テキスト モード アプリケーションを実行することもできます。
そのため、Windows OS には、MS DOS などの別の OS 用に設計されたコードを実行するための適切なサブシステムが必要です。しかし、プロセッサは可能な限り支援する必要があります。これは、x86 プラットフォームが 80386 に8086 仮想モードを導入したためです: プロセッサがリアル モード 8086 のように動作するタスクを作成できるようにするためです。
したがって、CPU 自体、適切なローダー、DOS 要求を Windows 要求に変換できる INT ハンドラー、メモリの特定のセクションへのアクセスをキャッチして画面上に文字を描画するための要求に変換できるインテリジェントなページ ハンドラーの支援を受けて、また、アプリケーションが使用していたデバイスを偽装できる I/O 障害ハンドラー、DOS 用に作成されたプログラムを Windows または Linux (DOSemu) で実行できます。
では、64 ビットではどうなるでしょうか。コードを 64 ビット レジスタにアクセスして実行できるようにするために、ロング モードと呼ばれる別の種類の保護モードが使用されます。このロング モードについてはよくわかりませんが、私が読んだ限りでは、このモードではプロセッサが 8086 仮想モードを使用してタスクを作成することはできません。互換モードなどと呼ばれる別のモードがあり、プロセッサは 64 ビットと 32 ビットのタスクを作成できますが、8086 仮想モードのタスクは作成できません。
CPU の支援がなければ、DOS サブシステムを実現するのは非常に困難です。メモリ マップを模倣し、特別なメモリ領域または I/O へのアクセスをトラップし、INT 命令をトラップすることはできますが、セグメント レジスタを更新しようとする試みをトラップする必要があります。リアルモードのアドレッシングを模倣しようとするため、実際にセグメントがロングモードで使用されているかどうかはわかりません。DOSBox のようなアプリケーションがそれを証明しているように、それは実行可能ですが、Microsoft はもはや DOS を必要としません (DOS は長い間必要ではありませんでしたが、おそらく Windows 2000/XP が導入されるまで、顧客はその点を共有していませんでした)。 . Windows 7 32 ビットでは、以前のバージョンの Windows で使用されていたものと同じ DOS サブシステムを使用できます (OS/2 サブシステムを Windows 2000 または Windows XP に戻すためのハックについて、以前に読みました)。しかし、Windows 7 64 ビットでは、
詳細はこちら:
http://www.codeproject.com/Articles/45788/The-Real-Protected-Long-mode-assembly-tutorial-for#Main