コードがCPUに固有である場合、OSにも固有である必要がある理由について説明します。これは実際、ここでの回答の多くが想定している興味深い質問です。
CPUセキュリティモデル
ほとんどのCPUアーキテクチャで実行される最初のプログラムは、内部リングまたはリング0と呼ばれる内部で実行されます。特定のCPUアーチがリングを実装する方法は異なりますが、ほとんどすべての最新のCPUには少なくとも2つの動作モードがあり、1つは特権があり、CPUが実行できる正当な操作を実行できる「ベアメタル」コードを実行し、もう1つは定義された安全な機能セットのみを実行できる、保護されていないコードを実行します。ただし、一部のCPUの粒度ははるかに高く、VMを安全に使用するには少なくとも1つまたは2つの追加のリングが必要です(多くの場合、負の番号のラベルが付いています)が、これはこの答えの範囲外です。
OSの出番
初期のシングルタスクOS
非常に初期のDOSおよび他の初期のシングルタスクベースのシステムでは、すべてのコードが内側のリングで実行され、実行したすべてのプログラムはコンピューター全体でフルパワーを発揮し、すべてのデータの消去やハードウェアの損傷を含む誤動作があれば文字通り何でもできる非常に古いディスプレイ画面で無効なディスプレイモードを設定するなどのいくつかの極端なケースでは、さらに悪いことに、これは単に悪意のないバグのあるコードによって引き起こされる可能性があります。
このコードは、プログラムをメモリにロードできるローダー(初期のバイナリ形式では非常に簡単)があり、コードがドライバーに依存せず、すべてのハードウェアアクセス自体を実装する限り、実際にはOSに依存しません。リング0で実行される限り、任意のOS。注:このような非常に単純なOSは、他のプログラムを実行するためだけに使用され、追加機能を提供しない場合、通常モニターと呼ばれます。
最新のマルチタスクOS
UNIX、NTで始まるWindowsのバージョン、その他のさまざまなOS を含む最新のオペレーティングシステムは、この状況を改善することを決定しました。ユーザーは、マルチタスクなどの追加機能が必要でした。または悪意のあるコード)がアプリケーションやマシンに無制限に損害を与えることはなくなりました。
これは上記のリングを使用して行われ、OSはリング0で実行される唯一の場所を取り、アプリケーションは外部の信頼できないリングで実行され、OSが許可した制限された操作セットのみを実行できます。
ただし、このユーティリティと保護の強化にはコストがかかり、プログラムはOSと連携して自分で実行することを許可されていないタスクを実行する必要があり、メモリにアクセスしてハードディスクを直接制御したり、任意に変更したりすることができなくなりましたデータではなく、OSにこれらのタスクを実行するように依頼して、操作の実行が許可されていることを確認し、それらに属していないファイルを変更せずに、操作が実際に有効であることも確認し、ハードウェアが未定義の状態のままになることはありません。
各OSは、OSが設計されたアーキテクチャに部分的に基づいて、部分的に問題のOSの設計と原則に基づいて、これらの保護の異なる実装を決定しました。たとえば、UNIXはマルチユーザー使用に適したマシンに焦点を当てますこのために利用できる機能は、Windowsがよりシンプルで、1人のユーザーでより遅いハードウェアで実行できるように設計されていました。ユーザースペースプログラムがOSと通信する方法は、X86ではARMまたはMIPSなどとまったく異なるため、対象となるハードウェアで作業する必要性に基づいてマルチプラットフォームOSに決定を行わせます。
これらのOS固有の対話は通常「システムコール」と呼ばれ、ユーザー空間プログラムがOSを介してハードウェアと完全に対話する方法を包含し、OSの機能に基づいて根本的に異なるため、システムコールを介して作業を行うプログラムはOS固有です。
プログラムローダー
システムコールに加えて、各OSは、プログラムを二次記憶媒体からメモリにロードするための異なるメソッドを提供します。特定のOSによってロードできるようにするには、プログラムはOSにその方法を説明する特別なヘッダーを含まなければなりませんロードして実行します。
このヘッダーは以前は非常にシンプルで、異なる形式のローダーを書くのはほとんど簡単でしたが、動的リンクや弱い宣言などの高度な機能をサポートするelfなどの最新の形式では、OSがバイナリをロードしようとすることはほぼ不可能ですつまり、システムコールの非互換性がなくても、プログラムを実行可能な方法でramに配置することは非常に困難です。
図書館
プログラムがシステムコールを直接使用することはめったにありませんが、システムコールをプログラミング言語用のやや使いやすい形式でラップするライブラリを介してほぼ例外なく機能を獲得します。たとえば、CにはC標準ライブラリとLinuxおよび類似のwin32 lib Windows NT以上では、他のほとんどのプログラミング言語にも、システム機能を適切にラップする同様のライブラリがあります。
これらのライブラリは、上記のクロスプラットフォームの問題をある程度克服することもできます。SDL などの幅広いOSへの呼び出しを内部で管理しながら、アプリケーションに均一なプラットフォームを提供することを目的に設計されたライブラリがあります。プログラムはバイナリ互換ではなく、これらのライブラリを使用するプログラムはプラットフォーム間で共通のソースを持つことができるため、再コンパイルと同じくらい簡単に移植できます。
上記の例外
ここで述べたことすべてにもかかわらず、複数のオペレーティングシステムでプログラムを実行できないという制限を克服する試みがありました。いくつかの良い例は、win32プログラムローダー、バイナリ形式、およびWindowsプログラムをさまざまなUNIXで実行できるシステムライブラリの両方を正常にエミュレートしたWineプロジェクトです。いくつかのBSD UNIXオペレーティングシステムがLinuxソフトウェアを実行できるようにする互換性レイヤーもあります。もちろん、MacOS Xで古いMacOSソフトウェアを実行できるApple独自のシムもあります。
ただし、これらのプロジェクトは、膨大なレベルの手動開発努力によって機能します。2つのOSの違いに応じて、難易度はかなり小さいシムから他のOSのほぼ完全なエミュレーションにまで及ぶことがあります。