今回は予定を変更して、以前から先送りにしていた コンディション・コード・レジスタ(CCR) について説明します。
HC08マイコンの CPUレジスタの図
アキュムレータ(A) , インデックス・レジスタ(H:X) ,
プログラム・カウンタ(PC) は 第12回 で説明済み
コンディション・コード・レジスタは CPUの動作状況を示す 「フラグ」 が集まって構成されています。 ほかのマイコンでは、 ステータス・レジスタ、フラグ・レジスタ、プログラム・ステータス・ワード などと呼ばれることもあります。
一般にこれらのフラグは、プログラムを行うユーザの立場と、プログラムを実行する CPU自身の立場の両方によって利用されます。 つまりユーザ (プログラム) がフラグを使って CPUに対して指示を出す場合もあり、逆にユーザ (プログラム) が CPUからの情報を受け取る場合もあります。 また、フラグに対して CPU 自身が次の動作のための情報を一時的に保存する場合もあり、CPUにとっては局所的ですがいろいろな使い方をするアイテムであると考えてよいでしょう。
フラグというのは重要な要素であるにも関わらず、これまでまったく意識せずに済んでいたのはなぜでしょう? それは、原則としてこの連載ではC言語を使ってプログラムを書いてきたからです。 Cコンパイラがそこのところをうまく処理してくれるので、ユーザはフラグを気にする必要がないのです。 ただし、I フラグ(割り込みマスク) だけは特別で、Cコンパイラに管理を任せるわけにはいきません。 割り込みの説明のときに詳しく述べます。
一方アセンブリ言語を使うときは、多くの場面でフラグを意識しなくても済みますが、条件付き分岐命令をデバッグするときなどは意味をきちんと理解しておく必要があります。
コンディション・コード・レジスタは、割り込みマスク および命令の実行直後の結果を表す 5個のフラグ を収める 8ビット・レジスタです。 ビット6 とビット5 は常に1 です。
以降では、コンディション・コード・レジスタの機能について説明します。 それぞれのフラグについて解説を行いますが、今の時点ではすべてを完全に理解する必要はありません。 ざっと目を通すだけでも充分でしょう。
V — オーバフロー・フラグ
CPU は、2 の補数(後述) のオーバフローが発生するとオーバフロー・フラグをセットします。 オーバフロー・フラグを使用する命令は、符号付き分岐命令のBGT、BGE、BLE、およびBLT です。
1 = オーバフローあり
0 = オーバフローなし
H — ハーフキャリ・フラグ
CPU は、キャリなし加算命令(ADD)またはキャリ付き加算命令(ADC)の実行時にアキュムレータのビット3 とビット4 の間でキャリ(繰り上げ) が発生すると、ハーフキャリ・フラグをセットします。 ハーフキャリ・フラグは、2 進化10 進数(BCD)の算術演算で必要です。 DAA 命令は、H フラグとC フラグの状態に基づいて目的の補正係数を決定します。
1 = ビット3 とビット4 の間でキャリあり
0 = ビット3 とビット4 の間でキャリなし
I — 割り込みマスク
割り込みはまだ説明していないので、後でまた読み返していただければ結構です。
割り込みマスクを 1 にすると、マスク可能なすべてのCPU 割り込みは禁止(Disable)されます。 CPU 割り込みは、割り込みマスクを 0 にすると許可(Enable)されます。 CPU 割り込みが発生すると、CPU レジスタがスタックに待避された後で割り込みベクタが取り込まれる前に、割り込みマスクが自動的に 1 になります。
1 = 割り込み禁止
0 = 割り込み許可
《 注意 》
M6805 ファミリとの互換性を維持するため、インデックス・レジスタの上位バイト(H)は自
動的にはスタックに格納されません。 割り込みサービス・ルーチンでH を変更する場合は、ユーザはPSHH 命令とPULH 命令を使用してH のスタックへの格納およびスタックからの復元を行う必要があります。 なお、C言語を使用する場合はこれらの格納・復帰コードが自動的に生成されます。
I ビットがクリアされた後は、最上位の優先順位をもつ割り込み要求が最初に処理されます。割り込みからの復帰(RTI)命令は CPU レジスタをスタックから読み出して、割り込みマスクをスタックから復元します。 マイコンのリセットでは割り込みマスクが 1 にセットされ、割り込みマスク・クリア(CLI)命令によってのみ 0 にすることができます。
N — 負数フラグ
CPU は、算術演算、論理演算、またはデータ操作の結果が負数(8ビットのうち最上位ビットが 1) なら、負数フラグをセットします。
1 = 結果は負数
0 = 結果は負数ではない
Z — ゼロ・フラグ
CPU は、算術演算、論理演算、またはデータ操作の結果が 0x00 ($00) なら、ゼロ・フラグをセットします
1 = 結果はゼロ
0 = 結果はゼロではない
C — キャリ/ ボロー・フラグ
CPU は、加算でアキュムレータのビット7 からキャリ(繰り上げ)が発生するか、減算でボロー(繰り下げ)が必要なときは、キャリ/ ボロー・フラグをセットします。 このフラグは、ビット・テストと分岐、シフト、およびローテイトなどの一部の命令でも、クリアまたはセットされます。
1 = ビット7 からキャリあり、または ビット7 へのボローあり
0 = ビット7 からキャリなし、または ビット7 へのボローなし
【 2の補数 について 】
2の補数というのは、決まったビット幅の数値において負の数を表す方法の一つで、コンピュータにおける二進数でよく使われる表現です。 具体的には、8ビット変数または 8ビットのレジスタを例にとると、 -128 ~ +127 の 256 通りの値を次のように表します。
0 ~ 127 は、そのまま二進数の 00000000 ~ 01111111 とする。
-127 ~ -1 は、 その数の絶対値を足したとき 0 になる数とする。
-128 は -127 より 1 小さい数である。
ピンと来ないかもしれませんが、これはとても理に適(かな)っているのです。
(例1) -1 であれば -1 + 1 = 0 と考えて、
11111111 + 00000001 = 00000000 (9ビット目は存在しない)
と計算できるので、 11111111 と表します。
(例2) -127 であれば -127 + 127 = 0 と考えて、
10000001 + 01111111 = 00000000 (9ビット目は存在しない)
と計算できるので、 10000001 と表します。
このように、最上位ビットが 1 のときに負の数を表していることがわかります。
この表現方法の利点は、足し算・引き算がそのまま行えるという点です。
-1 - 126 = -127 を試してみましょう。
11111111 - 01111110 = 10000001 で合っていますね!
もちろん、 -127 - 1 = -128 も成立するので -128 は、
10000001 - 00000001 = 10000000 と表されます。
理屈は以上です。 10進数の負数を与えられたとき、簡単に 2の補数表現を求める方法を書いておきます。 まず、全部のビットを反転します(これを 1の補数という)。 次に、それをインクリメント(+1)すれば求められます。 簡単ですね。
(例3) -3 を 2の補数表現にする。
まず、3 を 2進数で表すと 00000011
全ビットを反転すると 11111100
+1 すると 11111101 これが -3 の 2の補数表現。
C言語を使っている場合はとくに、普段のプログラミングで 2の補数表現を気にする機会はあまりないかもしれません。 しかし理屈を知っておくことは大切で、後々になって強みになるのは間違いありません。 何か困ってからでもかまわないので、一度納得するまで調べてみるとよいでしょう。
8ビットの 2進数(2の補数表現) と 10進数の対応
次回は CodeWarrior を使った簡単な実習を行う予定です。
『参考文献』
「試しながら学ぶHC08マイコン入門」 (CQ出版)
第1章 マイコン電子工作を始めよう
第10章 統合開発環境CodeWarriorを使ってみる
筆者のホームページ 『マイコン工作の実験室』
組み込みエンジニア KAWANO
