まず始めに、CPUの構造をおさらいする。下図は、H8/300H CPUの構造を模式的に表したものである。
各部を簡単に説明すると、
(1) レジスタ
CPUが演算や処理を進めるために、内部に持っているメモリを「CPUの内部レジスタ」(以後、レジスタ)と呼ぶ。レジスタには、
などがある。
(2)ALU(演算器)
ALU((Arithmetic Logic
Unit)とは、算術演算(H8/300Hの場合は、加減乗除)や比較、bit演算などを行うハードウエア。レジスタやメモリに保管されたデータに対して演算処理を行い、その結果をレジスタやメモリに返す。
(3) コントロールロジック
CPUの状態に応じて制御バスの信号を制御したり読み取ったり(例えば割り込みなど)、CPU全体の制御をおこなうハードウエア。
(4) 命令デコーダ
メモリから読み取った機械語命令を解釈して、必要な操作を行う。例えば、加減乗除などの演算を行ったり、メモリにデータを書き込んだりする命令などを解釈して、ALU、各種のバスを制御する。
CPUは、(1)~(4)を順次制御しながら演算処理を行う。処理は、おおよそ以下の流れで実行される。
具体例: レジスタR0の値に1を加算する
機械語命令とは、どのようなものかと言うと、例えば、以下のC言語のソースをコンパイルする。
(内容については、説明するほどではないが、変数cの内容を1ずつ増やしてゆくというもの。変数cの宣言にvotatileが付加されているが、これはコンパイラの最適化を抑止するためのものである。)
#include "monitor.h" |
以下に示すような、機械語命令によるプログラムが作成される。
※アセンブリコードとは、機械語命令と一対一の対応がとれているプログラムの事。
機械語命令は、下図のように数値の羅列として表現されるため、人がコーディングするには向いていない。(というかはっきり言
って無理。でも、昔のプログラマは、機械語命令を諳んじていた人も少なからず存在していた。まさに、人間アセンブラである
が、現在では、そんな事が出来ても自己満足にしかならない。)少しでもプログラマの負担を軽減する目的で、アセンブリコード
(アセンブラ)が考案された。
※今時の人々にとっては、アセンブラでコーディングすることだって、十分、苦痛である。Cのソースで数百万行のプログラムをアセ
ンブラでコーディングしろって言われたら、気が遠くなる。Cなどの高級言語は、この様なシステムの大規模化に対応するため
に生まれたと言ってもよい。スクリプト言語など、ここ、最近は、その傾向が更に顕著であるが。
(アセンブラや機械語は低級言語と呼ばれる事もある。あまり、一般的な呼び方ではないかもしれないが)
※アセンブラとは、アセンブリコードで記述されたプログラムを、機械語に変換するソフトウエアのこと。
上の例で、
INC.W #1, R0 |
というアセンブリ・コードがある。これは、「レジスタR0に1を加算して、その結果をR0に保管せよ」、という意味になり、これを機械語命令に変換する(アセンブルする)と、機械語命令は 0B50 (16進)となる。
FFE244 0B50 // いずれも16進数で表現 |
となる。 また、この命令は、メモリアドレスFFE244に保管されている。
CPUはこのプログラムを、どのように実行するかと言うと、
① ER7レジスタの中身を-2する。(意味がわからん && もっと知りたいという勉強熱心な人はこちら)
②R0レジスタ=変数のc。
R0レジスタの内容からR0レジスタの内容を減算する。(結局、R0レジスタの値は0になる。R0に0を代入すればよさそうなものだが、この方が高速に処理できるため。
アセンブラでは、この様な記述が良く見られるので、意味を深読みしてハマらないように。)
③ R0の内容を、ER7が示しているメモリアドレスに保管する。(つまりER7がポインタとして動作しているということ)
④
メモリアドレスFFE242の命令(つまり⑤)にジャンプする。(これも、一見して無意味に見える。所詮、機械がやることなんて、こんなもんだ。...っ言うか、人がそういう風にコンパイラをプログラミングしたってことで、コンピュータには、何の責任もない。テンプレートを使って機械語に展開してるとこういうことになるんだろう。)
⑤
ER7が示しているメモリに保管されたデータを読み取って、R0にコピーする。(③との兼ね合いで、これも何だか無駄っぽい処理だが、コンパイラは、Cのソースを律儀に機械語に変換している事の現れである。機械には、人間の意図なんて読み取れないのである。
つまり、コンパイラの理解し易いようにコーディングを行うと、"より、高速な(またコンパクトな)プログラムが作成できる"、ということになる...と思う。 いまどきのコンパイラは人間様の我儘な命令に対応できるよう、相当賢くなってはいるが。)
⑥ R0の値を+1する。つまりc++。
⑦
R0の値をER7が示すメモリアドレスに保管する。CPUのレジスタは演算のための一時記憶装置なので、演算が終わったら、その内容をメモリに保管する必要がある。
⑧ メモリアドレスFFE242の命令(つまり⑤)にジャンプ。(whileによる無限ループ)
メモリアドレスFFE242とは、変数cの実体ということになる。(スタックに保管されているので、グローバル変数やstatic宣言された変数の様に、恒久的なものではないことに注意)