main {}
OS を含むターゲット (Linux など) と OS を含まないターゲット (組み込み DSP ターゲットなど) の ac/c++ コンパイラを使用してコンパイルしたときの 2 つの空のプログラムの違いは何ですか? OSがある場合とそうでない場合のコンパイラの違いに特に興味があります。コンパイラ/言語ランタイムは 2 つのケースでどのように異なりますか?
4 に答える
オペレーティング システムで実行するプログラムをパッケージ化する場合と、ベア ハードウェアだけで実行するプログラムをビルドする場合とでは、実際に異なる仕事をするのはリンカです。コンパイラは、ホスト アーキテクチャを対象とする命令で構成されるオブジェクト ファイルを生成するだけであり、これらのチャンクは後で結合され、リンカーによってパッケージ化されます。
オペレーティング システム上で実行することを意図したプログラムは、特定のバイナリ構造を持っている必要があります。これが、実行可能な形式の出番です。このような形式では、たとえば、プログラムの最初にいくつかのヘッダー セクションがあり、その後にコードが続く必要があります。この構造を解釈し、コード セクションに含まれる一連の命令を CPU に供給するのは、OS ローダーの仕事です。
対照的に、裸のハードウェアで実行することを意図したプログラムは通常、特別な構造を持たず、CPU に直接供給することができます。
オペレーティング システムで実行するプログラムをパッケージ化する場合と、ベア ハードウェアだけで実行するプログラムをビルドする場合とでは、実際に異なる仕事をするのはリンカです。コンパイラは、ホスト アーキテクチャを対象とする命令で構成されるオブジェクト ファイルを生成するだけであり、これらのチャンクは後で結合され、リンカーによってパッケージ化されます。
オペレーティング システム上で実行することを意図したプログラムは、特定のバイナリ構造を持っている必要があります。これが、実行可能な形式の出番です。このような形式では、たとえば、プログラムの最初にいくつかのヘッダー セクションがあり、その後にコードが続く必要があります。この構造を解釈し、コード セクションに含まれる一連の命令を CPU に供給するのは、OS ローダーの仕事です。
対照的に、裸のハードウェアで実行することを意図したプログラムは通常、特別な構造を持たず、CPU に直接供給することができます。
Blagovestによるこの非常によく書かれた回答に基づいて構築したいと思います。実際、彼が示唆しているように、実行可能なコンテナ形式とバイナリ インターフェイスなどには違いがあります。ただし、おそらく最大の違いは、アプリケーション コードの実行への実際のメイン エントリ ポイントと、ランタイム ライブラリと共に起動コードが存在することです。ただし、自分が何をしているのかを知っていれば、本格的な OS でも後者へのリンクを避けることができます。
多くの場合、スタートアップ ルーチン、crt0 などのランタイム ライブラリが存在する場合、アプリケーションの実際のエントリ ポイントは別のmain
もの (通常は_start
) ではありません。この実際のエントリ ポイントがコントロールをユーザーに渡す前にmain
、通常は初期化に関連する一連の非常に特殊なタスクを実行する場合があります。
crt0 の詳細については、ウィキペディアが常にあります。
ただし、ベアメタル プラットフォームでは、コンパイラにバンドルされているルーチンが存在しない場合があります。その結果、コントロールが直接あなたに渡されmain
、プラットフォーム上で実行される最初のコードがあなたのものになる可能性があります。
ほら、これが 2 種類の の最も基本的な違いmain
です。ただし、スタックなどを自分で初期化する場合は、起動スクリプトなしで済ませることができ、これらすべてを実行するランタイム ライブラリを使用して実行することもできるため、質問は少し曖昧であると言わざるを得ません。 -金属プラットフォーム。実際、これはすべて、コンパイラスイート、ターゲットにしているプラットフォームなどに依存します.
違いはないと言いたくなる。コンパイラ (または翻訳システム) が行うことは、実装に大きく依存します。翻訳システムは、Windows と Linux の両方で OS としての資格があるにもかかわらず、異なることを行う可能性があります。
主な違いは、実装がホストされているかどうかです。ホストされていない場合は、 をサポートしていないか、サポートしている場合でも
、引数をmain
サポートしていない可能性があります。main
ホストされていない実装が起動のために行うこと、または必要とすることは、実装によって定義されます。ホストされた環境での起動に関しては多くの「定義された実装」もありますが、実装は、をサポート
し、少なくとも 2 つの署名をmain
返す必要があり、アプリケーションはそのような機能を提供する必要があります。int
過去も現在も、ホストされていると考えられる多くの実装は、実際にはさまざまな理由でそうではないことに注意してください。たとえば、過去には、g++ は自身を非ホストとして文書化していました (少なくとも gcc はそうしていました)。実装のライブラリ部分を制御できず、保証できなかったためです。そして今日でも、Microsoft の C++ は、コンソール アプリケーションを生成する場合にのみホストされていると見なすことができます。Windows アプリケーションにはmain
.
@BlagovestBuyukliev はよく書かれた回答を提供しています。
私はそれを少し拡張したいと思います.OSがないということは、実際にはソフトウェアによって実装されたOSがないことを意味します。バイナリ コードを実行できる HW の一部には、プログラムのロードを処理し、それを CPU とその他すべての低レベルの詳細に供給するプロトコルもあります。この場合、「OS」は実際には HW 実装されたものとして存在します。この時点から、バイナリ コードの実行を考慮する限り、標準 OS との違いは主要なものではなく技術的なものです。