7

そこで、Visual Studio で C++ プログラムを実行してコンパイルすると、小さな EXE ファイルが生成されます。しかし、EXE は Windows でしか実行できず、C/C++ がアセンブリ言語にコンパイルされ、プロセッサ上で直接実行される方法についてよく耳にします。EXE は Windows の助けを借りて実行されます。または、Mac で実行される実行可能ファイルを作成するプログラムを作成することもできます。しかし、プロセッサ固有のアセンブリ言語に C++ コードをコンパイルしていませんか?

私の洞察:

  1. 私はおそらくそうではないと思います。Intel C++ コンパイラがあることは知っていますが、それはプロセッサ固有のアセンブリ コードを作成しますか? EXE は Windows 上で実行されるため、グラフィックス パッケージから大規模な .NET フレームワークまで、既にセットアップされている多数のものを利用できます。プロセッサ固有の実行可能ファイルは、プロセッサの命令セットのみを使用して、文字通りゼロから始めることになります。

  2. この実行可能ファイルはファイルタイプでしょうか? Windows を実行してそれを開くこともできますが、その場合、スイッチをプロセッサのみに制御しますか? この実行可能ファイルはオペレーティング システムのようなもので、他の何かを起動する前に実行する必要があり、プロセッサの命令のみが「使用」に設定されていると思います。

4

10 に答える 10

18

「走る」の意味を考えてみましょう...

何かがバイナリ コードをメモリにロードする必要があります。それはOSの機能です。.EXEまたはバイナリ実行可能ファイルまたはバンドルなどは、OSがメモリにロードできるように、OS固有の方法でフォーマットされています。

何かがそれらのバイナリ コードに制御を渡す必要があります。再びOSです。

I/O ルーチン (C++ の場合ですが、これはほとんどの場所で当てはまります) は、OS API をカプセル化する単なるライブラリです。そのOSを書き留めてください、それはどこにでもあります。

回想

昔は (はい、私はこの歳です)、OS のないマシンで作業していました。Cもありませんでした。

「アセンブラ」や「リンカ」などのツールを使用してマシン コードを記述し、マシンにロードできる大きなバイナリ イメージを作成しました。面倒なブートストラップ プロセスを通じて、これらのバイナリ イメージをロードする必要がありました。

フロント パネル キーを使用して十分なコードをメモリにロードし、パンチ紙テープ リーダーのような便利なデバイスを読み取っていました。これにより、かなり標準的なブート リンク ローダー ソフトウェアの小さな断片がロードされます。(磨耗しないようにマイラーテープを使用しました。)

そして、このリンキングローダがメモリ上にできたら、先ほど用意したテープをアセンブラでフィードすることができました。

独自のデバイス ドライバーを作成しました。または、紙テープにパンチされたソース形式のライブラリ ルーチンを使用しました。

「パッチ」とは、実際には紙テープにパッチを当てたものです。さらに、小さなバグもあったため、手書きの指示 (テープに書き込まれていないパッチ) に基づいてメモリ イメージを調整する必要がありました。

その後、単純な API、単純なデバイス ドライバ、および「ファイル システム」、「エディタ」、「コンパイラ」などのいくつかのユーティリティを備えた単純な OS ができました。Jovial という言語用でしたが、Fortran を使用することもありました。

デバイスを接続できるように、シリアル インターフェイス ボードをはんだ付けする必要がありました。デバイス ドライバーを作成する必要がありました。

ボトムライン

OS を必要としない C++ プログラムを簡単に作成できます。

  1. プロセッサのチップセットの一部であるハードウェア BIOS (または BIOS に似た) 機能について学びます。最近のほとんどのハードウェアには、電源投入時セルフテスト (POST) を実行し、いくつかの単純なドライバーをロードし、ブート ブロックを見つける ROM に接続された単純な OS があります。

  2. 独自のブート ブロックを作成する方法を学びます。これは、POST 後にロードされる最初の適切な「ソフトウェア」です。これはそれほど難しいことではありません。さまざまなパーティショニング ツールを使用して、ブート ブロック プログラムを強制的にディスクに配置すると、ハードウェアを完全に制御できます。OSなし。

  3. GRUB、LILO、または BootCamp が OS を起動する方法を学びます。複雑ではありません。彼らが起動すると、彼らはあなたのプログラムをロードすることができ、あなたはオフになって実行されます。ブートローダーがロードしたい種類のパーティションを作成するため、これは少し簡単です。Linux カーネルをベースにすれば、より満足できるでしょう。Windows の起動方法を理解しようとしないでください。複雑すぎるためです。

  4. ELFを読んでください。 http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

  5. デバイス ドライバーの作成方法を学習します。OS を使用しない場合は、デバイス ドライバーを作成する必要があります。

于 2009-08-28T02:07:19.907 に答える
6

問題は、OS が実際にプログラムを起動するために多くのことを行うことです。EXE ファイル自体には、Windows が認識するヘッダー情報があり、自分自身を EXE ファイルとして識別します。アプリは、ファイル システムへのアクセスからメモリの割り当てまで、OS を介してすべてを行います。

しかし、はい、エミュレーションなしで他のプラットフォームで Windows/Intel 用にコンパイルされたアプリを実行できます。Mac または UNIX で EXE を実行したい場合は、プログラムを実行するために Windows が行う作業を行うために、もう少しソフトウェアをインストールする必要があります。"Wine" プロジェクトを見てください。

于 2009-08-28T01:53:40.420 に答える
6

あなたが話しているのは、組み込みの世界で「ベアメタル」アプリケーションとして知られているものです。これらは、(たとえば)デビットカード検証ボックスまたはインタラクティブなおもちゃに入るARM Cortex-M3のようなもので非常に一般的であり、完全なオペレーティングシステムを実行するのに十分なメモリまたは機能を備えていません. したがって、ARM プロセッサ上の Linux で実行するアプリケーションをコンパイルする「ARM/Linux」コンパイラを取得する代わりに、オペレーティング システムなしで ARM プロセッサで実行するようにコンパイルする「ARM ベアメタル」コンパイラを取得します。(例として、x86 ではなく ARM を使用しています。これは、最近では x86 ベアメタル アプリケーションが非常にまれであるためです。)

あなたの質問と他の回答で述べたように、アプリケーションは、そうでなければオペレーティング システムによって処理されるいくつかのことを行う必要があります。

まず、メモリ システム、割り込みベクトル、およびボード グーのその他のさまざまなビットを初期化する必要があります。通常、これはベアメタル コンパイラが行うことですが、奇妙なボードを使用している場合は、その方法を伝える必要があるかもしれません。これは、ボードがオンになった時点から main() 関数が開始する時点までのものを取得します。

次に、CPU と RAM の外側にあるものと対話する必要があります。オペレーティング システムには、これを行うためのあらゆる種類の機能が含まれています。ディスク I/O、画面出力、キーボードとマウスの入力、ネットワークなどです。オペレーティング システムがなければ、別の場所から入手する必要があります。ハードウェア製造元のライブラリからその一部を入手することができます。たとえば、私が最近遊んでいたボードには 40x200 ピクセルの LED スクリーンがあり、それをオンにして個々のピクセル値を設定するコードを含むライブラリが付属していました。また、TCP/IP スタックなどを実装するためのライブラリを販売している会社もいくつかあり、ネットワーキングなどを行うためのものです。

たとえば、これにより基本的な printf を実行することさえ困難になると考えてください。オペレーティング システムを使用している場合、printf はオペレーティング システムに「この文字列をコンソールに配置してください」というメッセージを送信するだけで、オペレーティング システムはコンソール上の現在のカーソル位置を検出し、すべての作業を行ってどのピクセルを計算するかを決定します。画面上で変更する方法、およびそれらのピクセルを変更するために使用する CPU 命令。

ああ、最初にプログラムを CPU に取り込む方法を理解する必要があると言いましたか? 典型的なコンピューターには、起動時に命令をロードするプログラム可能な ROM が少しあります。x86 では、これは BIOS であり、通常、CPU を起動し、ディスプレイをセットアップし、ディスクを探し、見つけたディスクからプログラムをロードする便利なプログラムが既に含まれています。組み込みシステムでは、通常、そこにプログラムを配置します。つまり、そこにプログラムを配置する方法が必要です。多くの場合、これは、プログラムをロードする組み込みボードに物理的に接続された「デバッガー」と呼ばれるデバイスがあることを意味します。また、プロセッサを一時停止してその状態を判断できるようにすることもできます。コンピューターのソフトウェア デバッガーでプログラムを実行しているかのように、プログラムをステップ実行できます。しかし、私は脱線します。

とにかく、2 番目の質問に答えるために、作成するこの実行可能ファイルは、組み込みボードのその ROM に保存されるものです。 small) 残りをフラッシュ ドライブに保存すると、ROM 内のビットにはフラッシュ ドライブから残りの部分を取得するための命令が含まれます。メイン コンピューター (つまり、作成している Linux または Windows コンピューター) にファイルとして保存される可能性がありますが、それは単なる保存用であり、そこでは実行されません。

これらのライブラリがたくさんある場合、それらはオペレーティング システムが行うことのかなりの部分を実行していることに気付くでしょう。ライブラリの山と実際のオペレーティング システムの間には、このようなスペースがあります。その領域には、RTOS と呼ばれるもの、つまり「リアルタイム オペレーティング システム」が登場します。これらの小さなものは、実際にはすべてのオペレーティングシステムのことを行うために連携して動作するライブラリのコレクションにすぎず、複数のスレッドを一度に実行できるようにするものも含まれている場合があります (そして、異なるスレッドを異なるプログラムのように動作させることができます) - -ただし、これらはすべて同じコンパイル済み「プログラム」にコンパイルされており、RTOS は実際には、インクルードしたライブラリにすぎません。より大きなものは、コードの一部を別々の場所に保存し始めます。Windows や Linux がプログラムを実行するときと同じように、ディスクからコードの断片を読み込むことさえできるものもあると思います。これは、どちらかまたは両方ではなく、一種の連続体です。

FreeRTOS システムはオープンソースの RTOS であり、RTOS スペースの小さな端に向かっています。あなたがもっと興味を持っているなら、彼らはこれのいくつかを見るのに良い場所かもしれません. x86 アプリケーションの例がいくつかあります。これにより、ベアメタルまたは RTOS ベースのプログラムを実行する x86 システムの種類と、x86 システムで実行するために何かをコンパイルする方法についてのアイデアが得られます。リンクはこちら: http://www.freertos.org/a00090.html#186 .

于 2009-08-28T02:59:44.003 に答える
3

コンピュータはCPUではありません。有用なことを行うには、CPU をメモリ、IO コントローラ、およびその他のデバイスに接続する必要があります。OS は、実行中のプログラムからすべてを抽象化します。そのため、OS なしで実行するプログラムを作成する場合、プログラムは少なくとも OS のいくつかの機能を複製する必要があります: ブート プロセス中に BIOS から引き継ぐ、デバイスを初期化する、ディスク コントローラと通信してコードをロードするデータ、ディスプレイコントローラーと通信してユーザーに情報を表示する、キーボードコントローラーおよびマウスコントローラーと通信してユーザー入力などを読み取るなど。

特殊なハードウェアを使用して組み込みシステムを構築しない限り、これを行う意味はありません。さらに、あなたのプログラムを実行すると、ユーザーは他のプログラムの実行をあきらめなければならなくなります。これは、今日の ATM や 1984 年の WordStar では許容されるかもしれませんが、最近では、音楽を聴きながら電子メールをチェックできないことに人々は眉をひそめています。

于 2009-08-28T02:06:41.107 に答える
1

確かに、それらは存在します。それらはクロスコンパイラと呼ばれます。たとえば、Xcode を使用して iPhone プラットフォーム用にプログラミングする方法です。

関連するタイプのコンパイラは、仮想プラットフォーム用にコンパイルするものです。それがJavaの仕組みです。

于 2009-08-28T01:56:13.130 に答える
1

特定のコンパイラ/ツールセットは、特定のプロセッサ/OS の組み合わせ用のコードを生成します。Visual Studio のコンパイル例では、x86/Windows 用のコードが生成されます。その .EXE は x86/Windows でのみ実行され、(たとえば) ARM/Windows (一部の携帯電話で使用される) では実行されません。

コンパイラを実行しているプロセッサと OS の組み合わせ以外のコードを生成するには、一般にクロスコンパイラと呼ばれるものが必要です。完全なプロフェッショナル Visual Studio サブスクリプションをお持ちの場合は、ARM クロス コンパイラを入手できます。これにより、デスクトップ マシンでは実行されないが、ARM/Windows ベースの携帯電話では実行される ARM/Windows .EXE ファイルを生成できます。またはパームトップ。

于 2009-08-28T02:06:14.323 に答える
0

Windowsライブラリも忘れないでください。QTとGTK+を調べてください

于 2010-12-27T20:49:31.957 に答える
0

はい、プロセッサの「ベア メタル」上で動作する実行可能ファイルを作成できます。明らかに、それがオペレーティング システムのカーネルのしくみです。主に行う必要があるのは、ライブラリをまったく使用しない実行可能ファイルを作成することです。ただし、「ライブラリなし」の制限には、C 標準ライブラリが含まれています。つまり、malloc や printf などはありません。基本的には独自の OS であり、メモリと I/O を自分で管理する必要があります。これには必然的に、ある段階でアセンブリに直接かなりの作業が必要になります。

また、main() は OS と C ランタイム環境によって呼び出されるものであるため、プログラムの開始点にならない main() など、他のいくつかの贅沢も失います。

于 2009-08-28T01:58:21.757 に答える
0

主な問題はファイル形式です。PE は ELF (UNIX ライクなシステムで使用される) とは大きく異なります。有効な PE プログラムを有効な ELF にすることはできません。したがって、バイナリを異なるスターターで動的にロードするか、あきらめる必要があります。

それ以外に、OS サービス、起動時のレジスタの値などの知識があれば、コードはおそらく、実行している OS を簡単かつ確実に検出し、それに応じて動作することができます (一部のマルウェアはそれを行います)。もう 1 つの課題は、同じバイナリに 2 つ以上の異なるプログラムを含めるのではなく、コードを再利用することです。基本的に、少なくとも必要なサービスのために、エミュレーターを作成する必要があります。

于 2009-08-28T06:49:18.170 に答える