5

3 つの質問があります。

  1. C ソース コードをマシン コードにコンパイルするには、どのコンパイラを使用できますか? また、どのように使用できますか?
  2. どのアセンブラを使用できますか? また、それを使用して ASM を機械語にアセンブルするにはどうすればよいですか?
  3. (オプション) どのようにマシン コードを適切なアドレスに配置することをお勧めしますか (つまり、ブートローダーのマシン コードはブート セクタに配置する必要があります)?

私の目標: 基本的なオペレーティング システムを作成しようとしています。これは、個人的に作成されたブートローダーとカーネルを使用します。また、Linux カーネル (つまりドライバー) から少しずつ取り出して、カーネルに統合することも試みました。私は、最近のほとんどのコンピューターでメモリをいじるための 32 ビット DOS ライクなオペレーティング システムを作成したいと考えています。私のオペレーティング システムはそれを必要とするほど動的ではないので、私は自分のオペレーティング システム用の実行形式を作成するつもりはないと思います。

私の状況: Intel Celeron CPU を搭載した x86-64 Windows 8 ラップトップで実行しています。セキュアブートを使用していると思います。Intel Core I3 CPU を搭載した x86-64 デスクトップでオペレーティング システムをテストします。私は、オペレーティング システムとその技術について平均的な理解を持っています。私は、このプロジェクトに必要な C、ASM、およびコンピューター理論を知っています。また、私が 16 歳で、コンピューター サイエンスに関する正式な教育を受けていないことも注目に値すると思います。

私の調査: C が通常何にコンパイルされるかを Google で検索した後、マシン コード、バイナリ、プレーン バイナリ、生のバイナリ、アセンブリ、および再配置可能なオブジェクト コードに及ぶ答えを見つけました。私が理解しているアセンブリは、通常、PE 形式の実行可能ファイルにアセンブルします。Cygwin、GCC C、および MingW C コンパイラについて聞いたことがあります。アセンブラーに関しては、FASM、MASM、および NASM について聞いたことがあります。OSDevOSDeverなどの Web サイトを検索しました。

私が試したこと: GCC をセットアップし (悪夢)、クロスコンパイラーを作成しようとしました (別の悪夢)。

結論: おわかりのように、私はコンパイラ、アセンブラ、および実行形式についてさまざまな混乱を抱えています。私の質問に答えて、私の無知を払拭してください。これらはおそらく、履歴書に OS を載せることを妨げている唯一の理由です。申し訳ありませんが、もっと多くのリンクを含めることができましたが、stackoverflow では 2 つ以上作成することはできませんでした。ありがとうございます!

4

4 に答える 4

5

まず、3 つの質問に対する簡単な回答をいくつか示します。

  1. ほとんどのコンパイラは、C コードをアセンブリ コードに変換します。それがコンパイラのすることです。GCC と clang は人気があり、無料です。

    clang -S -o example.s example.c
    
  2. どちらのコンパイラを選択しても、同じコンパイラ ドライバを使用するだけで、おそらくアセンブリもサポートされます。

    clang -o example.o example.s
    
  3. リンカーのドキュメントには、特定のコードを特定のアドレスに配置する方法などが記載されています。上記のように GCC または clang を使用する場合は、おそらくld(1). その場合は、「リンカー スクリプト」に読み込みます。

次に、いくつかの注意事項:

  • クロス コンパイラや自分で GCC をセットアップする必要はありません。Intel マシンで作業し、Intel マシン用のコードを生成しています。Linux ディストリビューションに付属している clang または GCC のバイナリ ディストリビューションは、正常に動作するはずです。

  • C コンパイラは通常、コードをアセンブリにコンパイルし、結果のアセンブリをシステム アセンブラに渡して最終的にマシン コードにします。マシン コード、バイナリ、プレーン バイナリ、生のバイナリはすべて基本的に同義です。

  • 生成されたマシン コードは、ホスト オペレーティング システムにコードをロードして実行する方法を伝えるために、ある種の実行可能ファイル形式にパッケージ化されます。Windows では PE、Linux では ELF、Mac OS X では Mach-O です。

  • お使いの OS 用に実行形式を作成する必要はありませんが、おそらく使用したくなるでしょう。ELF は非常に単純な (そして十分に文書化された) オプションです。

少し個人的な注意がありますが、あまり気を落とさないでください -コンパイラ、アセンブラ、リンカ、およびこれらすべてのツールがどのように機能するかについてよく知らない場合、プロジェクトは非常に困難で混乱するでしょ。いわば「海の足」を得るために、いくつかの小さなプロジェクトから始めたいと思うかもしれません。

于 2013-02-02T21:06:00.947 に答える
2

あなたの質問の最初の部分は答えられたと思うので、残りの 2 つを取り上げます。

どのアセンブラを使用できますか? また、それを使用して ASM をマシン コードにアセンブルするにはどうすればよいですか?

、(基本的に非常に似ているnasm) 、「masm」、すなわちのいずれかで、Microsoft ツールの一部として自由に利用できます。yasmnasmfasmml64.exeml.exe

これらのうち、おそらく または のいずれnasmかをお勧めしますyasm。この推奨事項は完全に個人的な好みに基づいていますが、サポートするプラットフォームの幅が広いことに加えて、デフォルトで Intel 構文を使用していることが私の理由です。私はいくつか試してみて、あなたが好きなものを見ていきます.

(オプション) どのようにマシン コードを適切なアドレスに配置することをお勧めしますか (つまり、ブートローダーのマシン コードはブート セクタに配置する必要があります)?

MBR の正しいアドレスにブートローダーを配置する方法は 1 つしかありません。LBA 0 のディスクを開き、そこに正確に 512 バイトを書き込み、0x55AA. フラッシュしてから閉じます。通常、MBR にはパーティション テーブルも含まれています。これは、コードとデータの両方です。このようなものに対する科学用語はフォン ノイマン アーキテクチャであり、「プログラムとデータは同じ場所に保存される」と簡単に要約できます。ディスクから起動したい場合の BIOS のアクションは、最初の 512 バイトをメモリに読み込み、署名をチェックし、一致する場合はそのメモリを実行します (バイト 0 から開始)。

わかりました、それは邪魔にならないそれらの質問です。ここで、さらにいくつかの注意事項を示します。

  • ブートローダーの 512 バイトは、実際には誰の使用にも十分ではありません。そのため、一部のファイル システムにはブート セクタが含まれており、ブートローダ自体はこれらにあるコード/データをロードするだけです。これにより、大量のコードをロードできるようになり、カーネルを動作させるのに十分な量になります。たとえば、旧バージョンの grub には、stage1、stage1_5、および stage2 コンポーネントが含まれています。
  • ほとんどのオペレーティング システムでは、実行可能形式のコンテナーを使用する必要がありますが、必要ありません。ディスク上およびメモリ内の実行可能コードは、オペコードと呼ばれる 1、2、または 3 バイトの文字列です。オペコード リファレンスまたは Intel/AMD のマニュアルを読んで、どの 16 進値が何に変換されるかを確認できます。とにかく、次のように nasm を使用して、アセンブラーからバイナリーへの直接変換を実行できます。

     nasm -f bin input.asm -o output.asm
    

    結果は実行されない可能性がありますが、これは 16、32、または 64 ビットのアセンブラーで非常にうまく機能します。[bits 16]コードでディレクティブを とともに明示的に使用するとorg 100h、MSDOS .com プログラムが作成されます。残念ながら、これは現存するバイナリ形式の中で最も単純なものです。コードとデータは 1 つの大きな塊でしかなく、これは 1 つのセグメントのサイズを超えてはなりません。

    これでこの点を処理できると思います:

    答えは、マシン コード、バイナリ、プレーン バイナリ、生のバイナリ、アセンブリ、および再配置可能なオブジェクト コードにまで及びました。

    どのアセンブリにアセンブルするかについての答え - アセンブラに応じて、オペコードとメモリ アドレスにアセンブルします。これはバイト単位で表され、それ自体がすべてデータです。これが厳密に必要な場合はほとんどありませんが、16 進エディタでそのまま読むことができます。一部のオペコードはメモリアドレスの解釈方法を制御するため、メモリアドレスについて言及します。たとえば、再配置可能なオブジェクトコードでは、アドレスがハードコーディングされていないことが必要です (代わりに、現在の場所からのオフセットとして解釈されます)。

    私が理解しているアセンブリは、通常、PE 形式の実行可能ファイルにアセンブルします。

    C/C++ の派生元であるアセンブラーはオペコードにコンパイルされ、プログラムに含まれるその他のもの (データ、リソース) と共に、PE などの実行可能形式で格納されると言っても過言ではありません。通常、OS に依存します。

  • OSDev Wiki をよく読んだ場合は、セグメント化されたアドレス指定が非常に面倒であることに気付くでしょう。最新のオペレーティング システムでのセグメントの標準的かつ唯一の使用法は、アドレス空間全体にまたがる 4 つのセグメント (リング 0 と 3 の 2 つのデータ セグメント) を定義することです。 、リング 0 と 3 の 2 つのコード セグメント。

  • OSDEV Wikiを完全に読んでいない場合は、読む必要があります。また、C でカーネルを構築するための実践的なアドバイスが含まれているJamesM のカーネル チュートリアルもお勧めします。

  • 単純に DOS カーネルに悪いことをしたいだけなら、完全なカーネルを自分で書かなくても実際に実行できます。また、DOS から CPU をプロテクト モードに切り替えることもできるはずです。FreeDOSと任意のアセンブラが必要です。The Rootkit Arsenalには、終了して常駐するという優れたチュートリアルがあります。これは基本的に、割り込みルーチンをフックし、アクティブなプロセス リストから自分自身を編集することを意味します。これについては、おそらくインターネット上にもチュートリアルがあります。

    この種の低レベルのものに慣れるために、これを最初に行うことをお勧めしたくなるかもしれません。

  • OS を突っ込みたいだけなら、Windows でカーネル デバッグをセットアップできます。WinDbg は少し...難解ですが、慣れてしまえば理にかなっています。
  • あなたのラップトップはセキュアブートを使用していると述べています。この場合、ラップトップは UEFI を使用します。これを読みたい場合、UEFI 仕様は数学の宿題よりも退屈であることが 100% 保証されていますが、目的と基本的な環境を理解するためだけにざっと読むことをお勧めします。重要なことは、 EFI互換アプリケーション (PE フォーマットで、ディスクの FAT32 パーティションに存在する) をビルドできるようにするEFI SDKを用意することです。率直な推奨をしなければならない場合、今のところ MBR に固執します。これを書いている時点では、MBR を使用した OS のエミュレートは EFI よりもはるかに簡単であり、今のところ何らかの形の VM でこれを実行したいからです。. また、ブートローダーはそれほどエキサイティングではないので、grub のような既存のものを使用します。
  • 他の人も言っていますが、私もそう言います。何らかの形のエミュレーターまたは仮想マシンの下で、このようなことを絶対にやりたいと思うでしょう。確実に間違いを犯し、理解できないことに直面するでしょう。エミュレーターと VM ソフトウェアは最近無料で、BOCHS などのいくつかは、特定の障害、トラップなどの理由が何であるかを教えてくれます。これは非常に役立ちます!
于 2013-02-02T22:45:49.043 に答える
2

まず、「マシンコード」と「バイナリ」は同義語です。「オブジェクトコード」は、リンカーが最後にバイナリに変換するある種の中間形式です。一部の C/C++ コンパイラは、バイナリを直接生成するのではなく、アセンブラ ソース コードを生成します。このソース コードは、オブジェクト コードを生成するアセンブラに供給され、最終的なバイナリを作成するリンカに供給されます。ほとんどの場合、これらのプロセスはユーザーに対して透過的です。コンパイラに C/C++/Pascal などのソース コードを入力し、出力でバイナリ ファイルを取得します。

FASM アセンブラー、別名フラット アセンブラーは、OS 開発に最適なアセンブラーです。FASM には、すでにいくつかの OS が作成されています。

これは、FASM が自己コンパイル可能であり、非常に簡単に移植できるためです。このようにして、2..3 日間、それを OS に移植することができます。その後、OS は自己完結型になります。つまり、OS 内からプログラムをコンパイルできるようになります。

FASM のもう 1 つの優れた機能は、リンカを必要としないことです。複数の形式のバイナリ ファイルを直接生成できます。

大きなアクティブなコミュニティも非常に重要です。OS 開発を含め、FASM で利用できるソースはたくさんあります。

掲示板はとても活発で、多くのことを学べる場所です。

于 2013-02-02T22:02:23.243 に答える
0

まず、テストにVirtualBoxのようなものを使用します

私はあなたがいくつかの小さなステップを踏むことを望むかもしれないと思います、Cコードを書くことに慣れてください。

次に、ディスク上のブートセクターがどのように機能するか(インターネットで十分に文書化されています)を調べ、他のオープンソースブートローダーのコードも調べます。

次に、タスク切り替えを行う方法を見てください。書くのはそれほど難しくありません。自分のOSに埋め込む前に、通常のOSで実行しながらそのほとんどを書き込むこともできます。

Cコンパイラを使用すると、通常、asmをインラインでミックスできます。asm { /* assembly code */ }

于 2013-02-02T21:09:11.477 に答える