AOBA's Information Processing Education
1998/03/22
注意1:このページは、回線を切断した後でゆっくりご覧になってください(テキストを印刷する場合は、その取り扱いに注意してくださるようお願いします)。
注意2:背景が白地の画面を長時間見つめていると頭が痛くなってしまいますので、ここは背景をグレーにしています。
先週は、条件付き分岐命令について説明しました。これは、ある条件を判定して、その条件を満たした場合に、任意の命令に分岐する命令でした。
例えば以下のプログラムは、「もしGR0が0以外ならばGR1に1を加算するプログラム」です。「GR0が0以外ならばGR1に1を加算するプログラム(一部)」
EX START
....(途中省略)
SUB GR0,C0 ; 条件付き分岐命令の前に演算命令が必要
JZE NEXT ; GR0が0ならばNEXTへ分岐
ADD GR1,C1 ; GR0が0以外ならばGR1に1を加算
NEXT(ここに分岐先の何らかの命令が入る)
....(途中省略)
C0 DC 0
C1 DC 1
END分岐命令以前(直前でなくてもよいですが、普通は直前)に、必ず演算命令が必要です。だからJZE命令の前にSUB命令(ADD命令や論理演算命令でもOK)があるのです。
ではなぜ分岐命令以前に演算命令が必要なのでしょうか。
実は(正確には)、条件付き分岐命令における条件判定は、汎用レジスタと定数0の比較を行うのではないからです。
この説明は混乱するでしょうね。だって、先週も今週も「汎用レジスタと0の比較を行う」と説明したし、例にあるプログラムを見ても、汎用レジスタと0の比較を行うように思えます。
これを理解するためにはフラグレジスタについて知らなければなりません。フラグレジスタ(FR)は、CPUの中にあるレジスタの一つです。そしてフラグレジスタは、何らかの演算命令を実行すると、その演算結果(GRに設定された値)に従ってCPUが自動的(とういか強制的)に、ある値を設定します。そこで設定する値は以下の通りです。
表 FRのとる値
GRに設定された値 負 零 正 FRの値 10 01 00 (注)FRは一度セットされると、次の演算命令に出会うまで元の値を保持します。
この表は、演算を行った結果GRxが負の場合にフラグレジスタに(10)2が設定され、零の場合に(01)2が設定され、正の場合に(00)2が設定されることを意味します(FRはたった2ビットのレジスタです)。
そして条件付き分岐命令は(正確には)、フラグレジスタと定数(2ビット値)との比較を行い、その条件を満たした場合に、指定された分岐先ラベルへ分岐する命令なのです。「条件付き分岐命令の(正確な)定義」
JPZ 分岐先ラベル ; FRが(00)2か(01)2ならば分岐先ラベルへ分岐する
JMI 分岐先ラベル ; FRが(10)2ならば分岐先ラベルへ分岐する
JNZ 分岐先ラベル ; FRが(10)2か(00)2ならば分岐先ラベルへ分岐する
JZE 分岐先ラベル ; FRが(01)2ならば分岐先ラベルへ分岐する
ここまでくれば、分岐命令以前に演算命令が必要な訳が分かったでしょう。
つまり条件付き分岐命令における比較は、本当は、フラグレジスタと(2ビットの)定数の間で行われるので、分岐条件を判定する前に、フラグレジスタをセットしておくのです。そしてフラグレジスタのセットは演算命令で行われるため、結局のところ、条件付き分岐命令以前に演算命令が必要なのです。でもこれでは面倒ですよね。CASLで(分岐や繰り返しの)プログラムを作る際に、いちいちフラグレジスタを意識するのは大変です。
でも大丈夫。現実にはフラグレジスタの値なんて、ほとんど意識する必要はありません。以下の表を見てください。
命令コード フルスペル 分岐する条件 JPZ (Jump on Plus or Zero) FRが(00)2か(01)2つまり、正か零(GRx>=0) JMI (Jump on MInus) FRが(10)2つまり、負(GRx<0) JNZ (Jump on Non Zero) FRが(10)2か(00)2つまり、負か正(GRx<>0) JZE (Jump on ZEro) FRが(01)2つまり、零(GRx=0) (CASLに限らず)アセンブラ言語における命令コードは、表意コード(ニーモニックコード)と言って、その動作(動作だけとは限りませんが)を表す略語になっています。だから、英語のフルスペルで覚えてしまえば、いちいちフラグレジスタを意識する必要はありませんので、必ず上記の表のフルスペルの部分を覚えておきましょう。
「演習」
GR0が負の場合はGR1に1を加算し、GR0が0の場合はGR1に2を加算し、GR0が正の場合はGR1に3を加算するプログラムを作成する。
以下のプログラムの空欄aを埋めて、プログラムを完成させよ。「プログラム」
01:EX19 START
......(途中省略)
10: ADD GR0,C0 ; フラグレジスタセット
11: JMI MNS ; GR0<0か?
12: (空欄a) ; ???????
13: ADD GR1,C1 ; GR1+1→GR1
14:ZERO ADD GR1,C1 ; GR1+1→GR1
15:MNS ADD GR1,C1 ; GR1+1→GR1
......(途中省略)
20:C0 DC 0
21:C1 DC 1
22: END
(注)行番号は解説のために付けたもので、プログラムではありません。
演習の解答 空欄部分: JZE ZERO
ケース1:GR0が負(<0)の場合に実行するステップ(10,11,15)
ケース2:GR0が0(=0)の場合に実行するステップ(10,11,12,14,15)
ケース3:GR0が正(>0)の場合に実行するステップ(10,11,12,13,14,15)行番号12を実行するのはGR0が0か正の時です。GR0が0の場合はGR1に2を加算するのですが、ZEROへ分岐すれば行番号14と15でそれぞれ1が加算されて題意と一致します。
もしこの時点でGR0が正ならば行番号13と14と15でそれぞれ1を加算しますので、最終的には3が加算されるでしょう。なお、行番号12の命令の直前の命令は演算命令ではありませんが、これはこれで問題ありません。なぜなら、フラグレジスタは演算命令に出会わない限り、元の値を保持し続けるからです。
つまり、直前の命令(JMI命令)ではフラグレジスタはセットされませんので、結局、行番号12のJZE命令は行番号10のADDの結果を判定していることになります。この問題は簡単すぎたでしょうかね?。 ではまた来週。