プログラミングを学び始めたとき、「このプログラムはどうやってこのような動きを実現しているのか」と疑問に感じたことはないでしょうか。私は二進数に変換されているくらいの曖昧な認識しかなく、友人にこの疑問を投げかけられたとき何も応えられませんでした。
そこでプログラムが動く仕組みについて調べてみるとなるほど面白い。
プログラミングを学ぶ上で知っていて損はないと思える内容なので記事にしようと思います。
#はじめに
まずなにより私がプログラミング初心者であることを念頭に記事を読んでほしいです。記事の内容に間違い等があれば是非指摘してください。もう一つ大事なのはこの記事はコンパイラ型言語、特にC言語について扱っていきます。
#コンパイル
C言語の場合プログラムを実行前にコンパイルという作業があります。これはC言語が二進数で表される機械語を、人間が理解できる形にした高級言語だからです。なのでコンピュータが理解できる機械語に変換する必要があります。
ちなみに、コンピュータで直接処理できるように変換されたコードをオブジェクトコード、プログラミング言語で記述されたコードをソースコードといいます。そして、オブジェクトコードを解析しソースコードを作成することを逆コンパイルといいます。
#1と0
機械語は二進数で表されています。二進数で十進数の数を表したり、文字コードにより文字を二進数で表現できることはご存知の方も多いでしょう。もし知らない方がいたら少し調べてみるといいです。
また、論理演算が大事なものとなります。AとBのどちらか一方でも1のとき1を返す論理和(OR)、両方が1のときに1を返す論理積(AND)、1なら0・0なら1を返す否定(NOT)などがあります。これら論理演算を組み合わせて1と0の値を変更し、目的の動作を実現させます。
#少し長い機械の話
###トランジスタ
機械ではどのように1と0を判断しているのでしょうか。それは電圧で判断しており、多くの場合+5Vの直流電流が1を表し、0Vが0を表します。そしてこのスイッチの役割をしているのがトランジスタと呼ばれる半導体素子です。論理演算の話に戻ると、論理和は並列、論理積は直列に二つのスイッチを繋いだら良いことがわかりますね。
集積化は進み最新のマイクロプロセッサ-には10億個を軽く超える数のトランジスターが集積されているようです。10億個のスイッチがパソコンに内蔵されていると思うとすごいですね。
###CPU(Central Processing Unit)
機械語となったプログラムの内容を解釈して実行する装置はCPUです。主に「レジスタ」「制御装置」「演算装置」「クロック」の4つに分かれており、相互に電気的に接続されています。レジスタは処理対象となる命令やデータを格納する領域で一種のメモリーのようなものです。制御装置はメモリー上の命令やデータをレジスタに読み出し、命令の実行結果に応じてコンピュータを制御します。演算装置は、メモリーからレジスタに読み出されたデータを演算します。クロックはCPUが動作するタイミングとなるクロック信号を発生させます。
特に大事なのがレジスタであり、演算を行うデータおよび演算後のデータを格納する「アキュムレータ」や、次に実行する命令が格納されたメモリーのアドレスを格納する「プログラム・カウンタ」などいくつかの種類があり、ひとつのCPUの内部に20~100個のレジスタがあります。
###メインメモリー
メインメモリー命令とデータを格納するところで、読み書き可能なメモリー素子で構成されています。1バイト(8ビット)ずつにアドレスとよぶ番号がついています。CPUと制御用チップなどを介して繋がっており、CPUがアドレスを指定してメインメモリーに格納された命令やデータを読み出し・書き込みをおこないます。
#命令と対象
これまでの説明でプログラムが実行される仕組みが何となくわかってきたでしょうか。ここまでくるとC言語で書かれたプログラムと大差ない気もしてきませんか。C言語は原則ソースコードの上から下に読んでいきます。CPUも同じでプログラムカウンタは命令を一つ実行し終えるごとにアドレスの値を一つずつ増やします。基本、命令とその対象のアドレスは離れています。
例えばAという値が100番地に入っていて、Bという値が101番地に入っているとき、1番地の命令が「レジスタXに100番地の値を読み込みなさい」、2番地の命令が「レジスタXの値と101番地の値の和を102番地に入れなさい」とすれば、A+Bの値が102番地に格納されるという具合です。
C言語のアドレスやポインタと同じ考えですね。
ちなみに命令部分をオペコード、命令対象をオペラントということも覚えておくとよいでしょう。
#おわりに
以上で今回の説明は終わりです。図もなくわかりにくい説明になっていると思いますが、初投稿なのでどうかお許しください......。他の方の記事なども参考にしてくれたらと思います。
また、機械語に近いアセンブリ言語を学ぶと、より理解が深まるかもしれませんので、興味のある方は是非調べてみてください(私も学ぼうと思っています)。
#####余談
・コンピュータでの処理に適した形式のコード全般をオブジェクトコードといいますが、C言語コンパイラが生成するコードは、特定の機種のみで実行可能なので特にネイティブコードといいます。これはJavaなど機種に依存せず実行できるものと区別するためらしいです。
・逆コンパイルにより得られるソースコードが自分の意図したものであるとは限りません。これはある動作をさせるプログラムの書き方が何通りもあることを考えれば理解できると思います。
・トランジスタのオンオフ切り替えのタイミングは同時であり、1秒間あたりの切り替え回数をクロック周波数という。切り替えがはやいほどコンピュータの性能は高いです。
####参考文献
・図解雑学-コンピュータのしくみ 著:山田宏尚
・プログラムはなぜ動くのか 著:矢沢久雄
(twitter → @Programshi )