- ベストアンサー
コンパイルしたらマシン語になる?
基本的な質問かもしれないのですが: ●プログラミング言語をコンパイルしたらマシン語になるのでしょうか? ●マシン語になるとしたら、なぜ、Windowsのgccでコンパイルした実行ファイルはUnix上で動かないのでしょうか? C言語などのプログラミング言語は人間が理解できる言葉で書かれていて、これをマシン(例えばIntelのCPU)が理解できる言葉に変換するのが「コンパイル」だと今まで私は理解していました。だから、IntelのCPU上でコンパイルした場合、他のCPUでは動かないのだと納得していました。 しかし、IntelのCPUが理解する言葉になるのであれば、WindowsでコンパイルしてもUnixでコンパイルしても IntelのCPUの言葉になっている点で変わりがないような気がします。しかし、Windowsでコンパイルした実行ファイルはUnixでは動かないですよね。私は根本的な勘違いをしていると思うのですが、それが何かを教えて頂けると幸いです。
- みんなの回答 (10)
- 専門家の回答
質問者が選んだベストアンサー
#3です。 > コンパイルした実行ファイルは > (1)CPUに直接働きかける部分 > (2)OSの機能を使って、間接的にCPUに働きかける部分 > の両方を持っているのでしょうか? 他の方も書いていますが、実際のプログラムが動作する場合においては、両方が混じっています。 (2)の部分のイメージとしてですが、例えば void main() { printf("hello world"); } といったプログラムを実行した場合を考えます。 これを実際に実行した場合、Unixではコンソール、Windowsではコマンドプロンプトに文字が出力されるわけですが、このそれぞれの画面に文字を出力する、という処理は各OSの機能によるものになります。 こういった部分があるため、OS依存性がでることになります。 また、stdio.hなどの基本機能とOS機能のなかだちをする処理が、コンパイルの中でもリンクといわれる処理になります。(・・・で、よかったと思います。)
その他の回答 (9)
- sha-girl
- ベストアンサー率52% (430/816)
>OSとのリンクが文字通り「リンク」なのですね。 ちょっと違います。 リンクとは複数のオブジェクトファイルを一つの 実行ファイル(exe)にまとめる事です。それは標準ライブラリーかもしれませんし 複数のソースファイルがあるなら、それらをまとめる処理の事です。 「リンカ C言語」で検索してみてください。 http://www.cqpub.co.jp/try/kijidb/yougo/san.htm http://asfa.tokyo-u-fish.ac.jp/joho991/C-gen.htm
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
確かに、IntelのマシンでコンパイルしたらIntelのマシンの機械語が出力されますが、 実行ファイルの形式というのはそれぞれののOSによって違います。 WindowsでもCOM形式(今どきはあまりききませんが)とEXE形式がありますよね。 Unix系とかでもa.out形式とかelf形式とかあります。 それは、実行ファイルを各OSでどのようにメモリ上で実行できるように展開するかが違うからです。 もちろん、APIなどOS毎の機能を使っていても、動かないのは、他の方もおっしゃっているとおりです。 それは、たとえば、Windowsでも 95でしか動かないNTでしか動かない実行ファイルがあるのと同じことです。
補足
> WindowsでもCOM形式 > (今どきはあまりききませんが)とEXE形式がありますよね。 > Unix系とかでもa.out形式とか > elf形式とかあります。 > それは、実行ファイルを各OSでどのように > メモリ上で実行できるように展開するかが違うからです。 なるほど、たしかにそうですね。 分かりやすい例をありがとうございます。
- omi63
- ベストアンサー率54% (25/46)
#1、#4です。 特殊なものを除いて実行モジュールにはヘッダー(OS毎に形式が決まっている実行モジュールの最初の部分)が有ります。OSはこの部分を見ただけで実行できるかどうかを形式的に判断できます。ドライバもまた然りです。
- JaritenCat
- ベストアンサー率37% (122/322)
>gcc でC言語をコンパイルする時、たとえばライブラリとして stdio しか使わない場合、OSに依存する機能は使っていないような気がするのですがそういう問題ではないのでしょうか? たとえstdio.hを使わなくてもコンパイル後の実行ファイルはOSによって形式が違うので、OS依存だと思いますね。それはUnixであってもBSDとLinuxでは互換性ないでしょう。それに、プログラムの実行処理(main関数に行くまでの処理)はOSがやりますしメモリ管理もOSですからOSが違えば同じCPUでも互換にはならないと思います。 ちなみに、OSと実行ファイルの間にエミュレータを入れて、OS間の差を吸収してやれば、バイナリ互換になります。
- taka_tetsu
- ベストアンサー率65% (1020/1553)
>gcc でC言語をコンパイルする時、たとえばライブラリとして stdio しか使わない場合、 >OSに依存する機能は使っていないような気がするのですがそういう問題ではないのでしょうか? 標準ライブラリの実装そのものはOSに依存しますよね。 >コンパイルした実行ファイルは >(1)CPUに直接働きかける部分 >(2)OSの機能を使って、間接的にCPUに働きかける部分 >の両方を持っているのでしょうか? 両方ですね。 >つまり、、OS間のドライバの違いが機種依存を生み出している、と思って良いのでしょうか? だけではありません。 根本的なところで、そのOSが実行ファイルとして起動可能なフォーマットのファイルになっていることが大前提です。 Windows用のコンパイラでコンパイルしたならWindows用の実行ファイルのファイル形式に基づいてマシン語に翻訳されますし、UNIX用のコンパリラならUNIX用のファイル形式に基づいて翻訳されます。 つまり、 int main() { int a; a = 1 + 2; return 0; } なんてプログラムから生成されるマシン語がOSが異なっても同一なものが生成されるとしても、OSが実行ファイルと認識できなければ動かすことが出来ません。
補足
>両方ですね。 これは、言われてみれば確かに。OSが実行ファイルと認識する必要がありますね。 (1)CPUに直接働きかける部分 (2)OSの機能を使って、間接的にCPUに働きかける部分 の両方が exe ファイルに含まれているというのはなかなか驚きでした。
- omi63
- ベストアンサー率54% (25/46)
> すると、機能など呼び出しているだけで、直接CPUに命令しているわけではないのでしょうか? 機能などを呼び出している部分、直接CPUに命令している部分など混在していると思います。機能などを呼び出している部分があればそのOSに依存している つまり、他のOSでは実行できないものとなります。
- eitetsu
- ベストアンサー率64% (22/34)
コンパイル=マシン語に直接変換する形ではありません。 実際には、そのコンパイルを行なうソフトの実装によりますが、基本的にはそのOSなり、ソフトウェア上で直接動作できる形式への変換を行ないます。 Windowsにしろ、Linuxにしろ、OS上ではコンピュータ全体を管理する為のソフトウェアが既に動いており、これらを有効に活用しながら動作するよう、コンパイルを行ないます。 これらのソフトウェア(デバイスドライバ)がOSによって異なるので、ソースは同じでも、コンパイル後のファイルは、環境依存が発生することになります。
お礼
ちょっと根本的な疑問が出てきました。 コンパイルした実行ファイルは (1)CPUに直接働きかける部分 (2)OSの機能を使って、間接的にCPUに働きかける部分 の両方を持っているのでしょうか? それとも(2)だけなのでしょうか?
補足
ありがとうございます。ちょっと分かったような気がします。 つまり、、OS間のドライバの違いが機種依存を生み出している、と思って良いのでしょうか?
- foobar
- ベストアンサー率44% (1423/3185)
コンパイルしたら、「コンパイルした部分」のマシン語ができあがります。 が、このままではプログラムとしては動作しません。コンパイルした部分で使われている関数呼出などを外部のライブラリと結合してやる必要が有ります。(リンク) (もうひとつ、プログラムを動かすための前準備の部分、後準備の部分も場合によってはくっつけてやる必要が有ります。) この、コンパイルした後にくっつける、前準備、後準備や、関数等の呼出かた(どういう名前のライブラリをどういう手順で呼び出して使うか)が、OSによって異なります。 ということで、コンパイル(+リンク)する時に想定したOS上でしか、プログラムは動作しません。
補足
ありがとうございます。 >コンパイルした部分で使われている関数呼出などを >外部のライブラリと結合してやる必要が有ります gcc でC言語をコンパイルする時、たとえばライブラリとして stdio しか使わない場合、OSに依存する機能は使っていないような気がするのですがそういう問題ではないのでしょうか?
- omi63
- ベストアンサー率54% (25/46)
コンパイル後の実行モジュールが、他(OSの機能など)を直接又は間接にコールしているだけだと思います。
補足
ありがとうございます。 すると、機能など呼び出しているだけで、直接CPUに命令しているわけではないのでしょうか?
補足
分かりやすい例をありがとうございます。確かに、画面への出力はOSの機能ですね。 OSとのリンクが文字通り「リンク」なのですね。