[Powered by Google Translate] ROBボーデン:レッツは、コンパイラの話。 この時点までは、あなただけにあなたのソースコードを入力した いくつかのファイルであり、この大きな黒いボックスを介してそれらを送信 Clangのは、出ない、実行可能ファイルを付属してい まさにあなたがソースコードに書いている。 てきていると魔法のように、我々は近づいていくつもりです 実際に何が起こっているかを見てみ 我々は、ファイルをコンパイルするとき。 それでは、それは何かをコンパイルするにはどういう意味ですか? まあ、最も一般的な意味では、それだけで意味 1で書かれたコード変換 別のプログラミング言語。 しかし、通常の人々は、彼らが何かをコンパイルすると言うとき、彼らは 彼らはより高いレベルのプログラミングから、それを取っているわけで 低レベルのプログラミング言語への言語。 これらは非常に主観的な用語のように見えるかもしれません。 たとえば、あなたはおそらく高いとしてCはないと思う レベルのプログラミング言語が、あなたはそれをコンパイルしてください。 しかし、それはすべて相対的です。 我々が見ていくように、アセンブリコードと最終的にはマシン 我々がダウンしてコンパイルされたコードは紛れもなく低いレベルである Cより 我々は今日のデモでClangのを使用することがありますが、 たくさんのアイデアはここで他のコンパイラに持ち越し。 Clangのは、全体の4つの主要なステップがあります。 コンパイル。 これらは、1、プリプロセッサによって行わ前処理です。2、 コンパイラによるコンパイル、3、組み立て と、4;アセンブラによって行わ リンクはリンカによって行われます。 これは、混乱を招くことがあり、その全体のサブステップの1 Clangのコンパイラは、コンパイラと呼ばれていますが、 我々はそれに得るでしょう。 私達は私達の例のような単純なHello Worldプログラムを使用することがあります このビデオを通して。 のは、見てみましょう。 最初のステップでは、前処理である。 プリプロセッサは何をしますか? あなたが今まで読んだか、書いてきたほとんどすべてのCプログラムでは、 あなたは、ハッシュで始まる行のコードを使用してきました。 私はそれをハッシュと呼ぶことにしますが、あなたもそれポンド呼び出すことができ、数 記号、または鋭い。 このような行はプリプロセッサディレクティブです。 おそらく、#defineや#前に含まれて見られるが、そこにしました プリプロセッサが認識していることをいくつかのより多くのです。 #私たちのHello Worldの例にdefineを追加してみましょう。 さて、このファイル上だけでプリプロセッサを実行してみましょう。 clage-Eフラグを渡すことで、あなたはそれを実行するよう指示している ただプリプロセッサ。 何が起こるか見てみましょう。 Clangのはただすべてを出してくれるみたいだな コマンドラインで。 という名前の新しいファイルに、この出力のすべてを保存するために hello2.cは、我々のコマンドに> hello2.cを追加します。 今度は、私たちのプリプロセスされたファイルを見てみましょう。 おっと、私たちの短い小さなプログラムに何が起こったのか? 我々は、このファイルの末尾にすべての道を行く場合は、我々が表示されます 私たちが実際に書いたコードの一部。 #定義がなくなっていることに注意してくださいと名のすべてのインスタンス 我々はに指定されたかを正確に置き換えられました #行を定義します。 だから、すべてのこれらのtypedefと関数宣言は何ですか ファイルの先頭にある? の#defineプリプロセッサだけではなかったことに注意してください 私たちが指定した指令。 また、#stdio.hをインクルードしています。 だから狂ったすべての行はただstdio.hにコピーされた実際には そしてこのファイルの先頭に貼り付ける。 ヘッダファイルは関数のように有用である理由です 宣言。 代わりに関数のすべてをコピーして貼り付ける必要がある あなたは、あなたのファイルの先頭に使用する予定の宣言 プリプロセッサは、ヘッダからそれらをコピーして貼り付けます あなたのためのファイル。 今、私たちは、前処理を行っていることを、我々は上に移動 コンパイル。 これがあるため、我々はこのステップのコンパイルを呼び出す理由は、 Clangのが実際にCからにコンパイルしないステップ アセンブリコード。 Clangのアセンブリにファイルをダウンしてコンパイルしていますが、するために、 それ以上、それを渡す-Sフラグを続行 コマンドラインで。 レッツは、アセンブリを見てみましょう 出力されたファイル。 それはかなり異なる言語のように見えます。 アセンブリコードは非常にプロセッサ固有のものです。 CS50アプライアンスが実行されているので、この場合、 仮想x86プロセッサ、これはx86アセンブリコードです。 非常に少数の人々は、これらの日のアセンブリコードに直接書き込む しかし、あなたが今まで書いて、全てのCプログラムは、ダウン変換される アセンブリに。 再び、我々はアセンブリにC言語をコンパイルし、このステップを呼び出す 私たちは、より高いレベルから低いレベルにしようとしているので、 プログラミング言語。 何がCよりも低いレベルのアセンブリを作る? まあ、アセンブリに、我々は非常に我々が何ができるかに制限されています。 だ、のための、または任意の種類のwhileループ、の場合全くありません。 しかし、あなたは同じことを成し遂げることができ、これらの制御 構造体は、その限られた操作を使用して提供 アセンブリが​​提供します。 しかし、低レベルのアセンブリが​​本当にどれだけ見て、行ってみよう 私たちのコンパイルで、さらに一歩、組み立てる。 これは、アセンブリ·コードを変換するためのアセンブラの仕事です オブジェクトまたは機械語コードに変換します。 アセンブラは出力アセンブリをしないことに注意してください。 むしろ、それはアセンブリと出力マシンコードを取り込む。 マシンコードは、CPUができる実際の1と0です 我々はまだ残って仕事のほんの少しを持っているが、理解 私達は私達のプログラムを実行する前に。 通過することによって私たちのアセンブリコードをアセンブルしてみましょう Clangの-cフラグ。 今すぐ組み立てファイルに何があるか見てみましょう。 まあ、それは非常に私たちを助けていません。 マシンコードは、その物およびゼロであることを忘れないでください コンピュータが理解することができます。 それは私たちが理解しやすいというわけではありません。 だからアセンブリが​​正確にどのように低レベルですか? これは、オブジェクトコードとほぼ同じです。 アセンブリからのオブジェクトコードに行くことのはるかです なぜ変態、より翻訳 一つにアセンブラを考慮していないかもしれません 実際のコンパイルを行います。 実際には、それは手動で翻訳することは非常に簡単です マシンコードにアセンブリ。 その最初の行は、main関数のアセンブリを見てみる 進0x55に対応することを起こる。 バイナリでは、それは1010101です。 二行目は進0x895に対応して発生します。 そして次回、0x56。 比較的簡単な表があると、あなたは翻訳できる マシンがあまりにも理解できるコードにアセンブリ。 そうで残りの1つのステップがあり リンクされているコンパイル、。 リンクとは、一つの大きなファイルにオブジェクトファイルの束を組み合わせ あなたが実際に実行できること。 リンクは非常にシステムに依存します。 単にオブジェクトをリンクするClangのを取得するので、最も簡単な方法 一緒にファイルには、そのファイルのすべてにClangのを呼び出すことです。 あなたは一緒にリンクしたい。 あなたはoファイルを指定した場合、それは再処理する必要はありません、 コンパイルして、ソースコードのすべてを組み立てる。 のは、我々のファイルに数学関数を投げるましょう、私たちは持っている インチにリンクするために何か 今度は、オブジェクトコードに戻ってそれをダウンしてコンパイルしてみましょうと その上でClangのを呼び出します。 おっと。 我々は数学関数が含まれていたので、我々はにリンクする必要があります -lmで数学ライブラリ。 我々は我々。oファイルの束を一緒にリンクしたい場合 自分たちで書いたが、我々だけでそれらすべてを指定したい コマンドライン。 制限により、これらのファイルの1つだけがしなければならないということです 実際にmain関数を指定するか、または他の 生成された実行可能ファイルは、どこから始めればいいのか分からないでしょう あなたのコードを実行する。 にリンクするファイルを指定するの違いは何ですか と-lとだけファイルを直接指定して? 何もない。 それだけではClangのは正確にどのファイルを知ってどうなるの -lmのようなものを参照するために起こります。 あなたは、そのファイルを自分で知っていた場合は、それを指定することができます 明示。 ただ、すべての-lフラグが終わりに来ていることを覚えておいてください あなたのクライアントの需要。 そして、それはこれだけです。 あなただけのいくつかのファイルにClangのを実行すると、これはそれが何である 実際にやって。 私の名前はロブ·ボーデンであり、これはCS50です。