コンパイラが実行可能ファイルを作るまで

コンパイル→実行可能ファイル

簡単な流れ

GCCを使用します。
C言語でソースコードを記述しコンパイルした時どんな風になっているのか。
「コンパイルしたら動くファイルができる!」
という理解でも問題はありませんが、もっと深く知ることでコンピューターについての理解が深まると思います。

そもそもなぜコンパイルが必要なのか。
コンピューターが理解する機械語は番号などの数値で記述されるため人間が機械語でプログラムを書こうとすると、まず命令を覚えるのに非常に手間がかかる上にミスも増えます。
なのでソースコードは人間にも分かりやすいように人間が理解しやすいC言語などの高級言語で記述します。
そのソースコードを機械にも分かる機械語に翻訳するのがコンパイラの役目となります。

私達がC言語で記述した最終的に電子回路、つまり電圧の高低に変換され計算が施されます。
コンピューターは与えられた入力を命令された回路に流し込んで得られた出力を返しているだけです。
つまりC言語の関数名や変数名は理解しませんしできません。
これをコンピューターに理解できる状態に加工するために数段階に分けて細かく分解しています。

つまりC言語をコンピューターが理解できるように翻訳するのがコンパイラの仕事です。
以下の流れで実行可能ファイルは作成されます。

プリプロセス
↓マクロなどの処理
コンパイル
↓アセンブリへの変換
アセンブル
↓機械語(数値の羅列)へ変換
リンク
↓断片化した機械語のファイルをまとめる処理
実行可能ファイル

以下細かく見ていきます。

プリプロセス

コンパイルを行うソフトウェアが処理を行う前の準備段階で行われる処理でソースコードに書かれたプログラムの本質的な処理にかかわらない処理を実行させます。

マクロによる文字列の置き換え処理やファイルの読み込みなどが主な処理でソースコードに記述でき、それらの命令は「プリプロセッサディレクティブ」と呼ばれます。

例)
#include、#define、//コメント、/*コメント*/

コンパイル

プリプロセスによる処理が終了すると今度はコンパイラによって高級言語をアセンブリ言語へ変換します。
アセンブリとは機械語命令とと一対一に対応したニーモニックで記述する言語でレジスターを直接操作したり、アドレスの番地を直接指定できるなどC言語といった高水準言語がプログラマーの代わりにやってくれていたことをプログラマー自ら行うことができ、より細かくコンピューターの操作を行うことができます。
ただし機械語と一対一に対応する文法を持っているだけで、まだ人間の為の言語なのでこれを機械語に変換する必要があります。
次のアセンブルに備えた準備段階です。

アセンブル

上記のコンパイルで得られたファイルを機械語に変換するのがアセンブルです。
この時点でソースコードは1と0のバイナリコードに変換され、これをオブジェクトファイルと呼びます。

しかしこの時点ではまだファイルを実行することはできません。

リンク

アセンブルの段階でコンピューターが理解することのできるオブジェクトファイルは出来上がりましたが、まだ実行することはできません。
普通ファイルは関数や変数、if分岐などの他のファイルと結び付けられているからです。
オブジェクトファイル同士を結び付ける作業がリンクになります。
これを行うソフトウェアのことをリンケージエディタやリンカーと呼んだりします。
関数名などはシンボルと呼ばれ、シンボルはシンボルテーブルにより実際のメモリアドレスと結び付けられます。
ここで晴れて実行可能ファイルが完成するわけです。

コンパイルすると言ってもこれだけの処理をコンパイラが代わりに行ってくれています。
gccは様々な命令をひとまとめにしたコマンドだったんです。

コメント