4

私は最近、64 ビット Windows には 16 ビット サブシステムがない (またはインターネットがそう言っている) ため、64 ビット ウィンドウでは 16 ビット アプリケーション (この場合は .com) が実行されないことを発見しました。EDITを呼び出す.batファイルを実行しようとしたときに、これに遭遇しました。

x86 アセンブリの経験はかなりありますが、windows (またはその他の OS) で実行するプログラムを作成したことはありません。x86 ファミリには下位互換性があるため、プログラムのビット数にあまり注意を払ったことはありませんでした。プログラムを実行する必要がある CPU に導入されていない命令を使用しない限り、問題はありませんでした。

私の質問は次のとおりです。コードを 16、32、または 64 ビットにする正確な理由は何ですか?16 ビット アプリケーションに見られる非互換性の問題の原因は何ですか?

小さな 16 ビット アプリケーションを逆アセンブルし、少し変更して動作させることは可能ですか?

更新:この種のアプリケーションをそのまま実行する方法、つまりエミュレーターや他のプログラムを介して自分で解決できる方法を探しているわけではありません。ウィンドウがプログラムを受け入れたり拒否したりする根本的なメカニズムを理解したいだけです。

4

6 に答える 6

1

私の質問は次のとおりです。コードを 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

于 2013-12-14T03:45:54.277 に答える
0

一般的なアプローチは、DosBoxなどのエミュレーターを使用することです。バイナリに関する何かを変更して、別の命令セットを使用して実行する方法はありません。これは、ソース コードから開始する必要があります。

于 2013-09-27T17:11:07.353 に答える
0

DOSBox をインストールして楽しんでください。http://www.dosbox.com/で無料です。

編集:

コードのビット数は、レジスタ/オペランドのサイズに関する仮定を意味します。一方、CPU の現在の「ビット数」は、リアル モードでは 16 であり、プロテクト モードでは、現在実行中のコード (セグメント記述子および/またはページ エントリ) を記述するインメモリ構造のフラグです。 、正確には)。OS は、前述のメモリ メタデータを設定し、ビット数を維持します。後者によっては、同じコマンド ビットが意味する場合があります。

add ax, bx

また

add eax, ebx

また

add rax, rbx

CPU のビット数とコードの想定がより一致します。そうしないと、アプリケーションがクラッシュしたり誤動作したりするまでにそれほど時間はかかりません。たとえば、コードがメモリからレジスタを読み込もうとしたときに、CPU レベルのレジスタ サイズがコードが想定しているものと異なるとすぐに、CPU はガベージをロードします (またはレジスタの一部のロードに失敗します)。32ビットモードで以下がどうなるか想像してみてください:

MyData dw 0x17 ;2 bytes of data
SomeOtherData dw 0x200 ;2 more
...
mov ax, [MyData] ;We think we mean AX, but the CPU thinks it's EAX

EAX は 0x2000017 の値をロードします。間違いなく、プログラムが期待するものではありません。次に、プログラムが値を 0x17 と比較し、それに基づいて条件付きジャンプを行うと想像してください。

16 ビット リアル モード アセンブリを手動で 32 ビット プロテクト モードに変換することは可能ですが、レジスタ名を変換するだけではありません。DOS プログラムから Windows プログラムに移動する必要がありますが、それらは別のものです。単純な翻訳ではなく、移植に似ています。

于 2013-09-27T17:11:43.870 に答える
-1

それは純粋に商業的な決定です - あなたのマシン自体がwindows7の64ビットまたは32ビットバージョンを実行できるという事実によって証明されるように、単に技術的な理由はありません.ファイルを実行し.COMます。

Microsoft は明らかに利用可能なテクノロジを持っています。ここで説明されHome*いますが、エディションでの実行は許可されていません。

于 2013-12-14T02:38:51.343 に答える