アセンブリコード


さて、マクロはもうなくなったので、今度こそコンパイルの本体です。 C のソースコードから各機械語のアセンブリコードになるまでです。 とりあえず、結果から先にいきましょう。
kamada@cygwin% gcc -S hello.c 
とすると、hello.sというファイルができあがります。 この例では、Intel + Cygwin 用のコードが出力されています。 つまり Pentium 用のコードが出力されているわけです。

コードを良くみると、_main:というラベルからmain のコンパイル結果が並んでいるのが 分かるでしょう。 call _printf というのが関数呼出しでしょうし、 最後にretといっているのが return だろうなというのも想像できるでしょう。 これとは別に、LC0というところに、文字列定数もデータセグメントとして乗ることになっています。

最終的に、アセンブリコードはアセンブラによってオブジェクトファイルにまで変換されます。

kamada@cygwin% gcc -c hello.c 
とすると、hello.o というファイルができたはずです。
さて、さきほど Pentium 用のコードなどという話をしましたが、 例えば、Mac(CPU: PowerPC) の場合は PowerPC 用のコードがでるでしょうし、 Origin(CPU: MIPS)でやった場合は、MIPS 用のコードが出るでしょうし、 SUN WS なら、Sparc用のコードがでるでしょう。 つまり、コンパイル結果はアセンブリコードの段階で機種依存になっています。

タマに、誤解している人がいるので注意しておきます。 よく、計算機の差異は OS が解消してくれるという話を聞くことでしょう。 だからといって、OS が同じならば、同じ実行ファイルが複数の場所で走ると思っているのなら、 それは大きな大きな勘違いです。 OS は各計算機が持つ資源を管理し、そのアクセスについてインタフェイスを与えてくれます。 標準ライブラリも OS の上に構築されるものです。 しかし、 CPU に関する差異を吸収するのは、言語処理系/コンパイラの役目です。

ということで、Mac 側でコンパイルしたつくった実行ファイルを PC で動かそうとしたり、 shusaku (Origin)で動かそうとしても動いてくれません。 で、いったい、このオブジェクトファイルは、なんだっけ?といった場合は、fileコマンドを つかいましょう。以下のように答えてくれます。


Cygwin + Pentiumで作成したファイルの場合
kamada@cygwin% file hello.o                
hello.o: 80386 COFF executable not stripped - version 30821
Solaris + Sparcで作成したファイルの場合
kamada@cygwin% file fib_sparc              
fib_sparc: ELF 32-bit MSB executable, SPARC, version 1, dynamically linked (uses shared libs), not stripped
まあ、混乱しないように、普段使うマシンはどちらかにきめておくと良いでしょう。

2001.9.25/ Tomio KAMADA: kamada@cs.kobe-u.ac.jp