ニッシー
1990年生まれ
血液型 O型

こんにちは。ITブログアルケーナム管理人のニッシーです。

詳細プロフィールへ

お問い合わせへ






2018-06-14

CASL2の比較命令と分岐命令の関係







今回は値を比較する命令を見てみたいと思います。値を比較というと、C言語では「if文」が頭を過ぎるでしょう。


人間にとって数と数を比較することは容易なことですが、機械的に比較を実現するにはどういう計算が必要なのか、と疑問を抱きますよね。


それでは、実際にどのように値と値を比較しているのか見てみたいと思います。
















比較命令



比較命令は、2つの異なる数値を比較し、大きい、小さい、そして同じかどうかを判定する命令です。


また、比較命令は「算術比較」と「論理比較」の2種類の命令が用意されていて、算術と論理で数値の扱いに違いがあります。



算術比較



名称オペコード第1オペランド第2オペランド第3オペランド
ComPare
Arithmetic
CPAレジスタ
アドレス
or
レジスタ
---
レジスタアドレスレジスタ

使用例1: CPA GR0, A

汎用レジスタGR0のデータとメモリA番地のデータを算術比較せよ。



使用例2: CPA GR0, 1

汎用レジスタGR0のデータとメモリ1番地のデータを算術比較せよ。



使用例3: CPA GR0, 1, GR1

汎用レジスタGR0のデータとメモリ汎用レジスタGR1のデータ+1番地のデータを算術比較せよ。



使用例4: CPA GR0, GR1

汎用レジスタGR0のデータと汎用レジスタGR1のデータを算術比較せよ。



論理比較



名称オペコード第1オペランド第2オペランド第3オペランド
ComPare
Logical
CPLレジスタ
アドレス
or
レジスタ名
---
レジスタアドレスレジスタ

使用例1: CPL GR0, A

汎用レジスタGR0のデータとメモリA番地のデータを論理比較せよ。



使用例2: CPL GR0, 1

汎用レジスタGR0のデータとメモリ1番地のデータを論理比較せよ。



使用例3: CPL GR0, 1, GR1

汎用レジスタGR0のデータとメモリ汎用レジスタGR1のデータ+1番地のデータを論理比較せよ。



使用例4: CPL GR0, GR1

汎用レジスタGR0のデータと汎用レジスタGR1のデータを論理比較せよ。





比較方法



比較は、比較する2値を引き算し、計算結果の符号の種類を見ることで実現しています。


例えば、AとBという値を比較する場合、まず、A - Bを実行します。その結果、AがBより小さければ答えはマイナス値になり、Bが大きければ答えはプラス値になり、そしてAとBが同じなら答えがゼロになります。


  • A > B ・・・A - B の結果、答えの符号はプラス
  • A < B ・・・A - B の結果、答えの符号はマイナス
  • A = B ・・・A - B の結果、答えがゼロ(ゼロは符号なし)


ここで、「A ≧ B」はどうするのか?という疑問が湧いてきますが、以下のように考えます。


「A > B または A = B」


このように考えることで解決できます。



比較時のオペランドの対応関係



オペランドの対応関係は、第2オペランドに対して第1オペランドがどのくらいの大きさであるか、と捉えます。


例えば、CPA GR0, GR1 のオペランドはどのような対応関係で比較しているのかというと...


GR1(後) に対して GR0(前) が、どのくらいの大きさの値かを見ています。


CPA GR0, GR1 ・・・GR1に対してGR0が、大きいのか小さいのか、または同じなのかを比較



算術比較・論理比較の違い



算術比較と論理比較の違いは、マイナスの数を考慮するか、しないかというところにあります。


算術比較・論理比較は、以下のような違いがあります。



例1: GR0の値が-1 、GR1の値が0のときの比較

① 算術比較の場合

1 CPA GR0, GR1

GR0 < GR1 --> SF = 1 になります


算術比較の場合、SFが1に変化します。



② 論理比較の場合

1 CPL GR0, GR1

GR0 > GR1 --> SF = 0 のままです


算術比較の場合、SFが1に変化しません。


それでは、なぜ、このように結果が異なるのか見てみましょう。



なぜ算術比較・論理比較の結果フラグに違いがあるのか



算術比較・論理比較においてフラグに違いがある理由は、算術と論理では16進数の扱いに違いがあることが関係しているためです。


ここで、10進数「-1」は16進数「FFFF」ですが、この16進数「FFFF」は10進数「65535」でもあります。


  • -1 = (FFFF)16
  • 65535 = (FFFF)16


CPAは、(FFFF)16-1としてCPLは、(FFFF)1665535として扱います。


つまり、CPAとCPLでは以下のような違いがあります。



例2: GR0の値が(FFFF)16 、GR1の値が0のときの比較

① 算術比較の場合

1 CPA GR0, GR1

大小関係が GR0 < GR1(-1 < 0) ・・・SF = 1


(FFFF)16は、10進数で-1であるため、SFが1に変化します。



② 論理比較の場合

1 CPL GR0, GR1

大小関係が GR0 > GR1(65535 > 0) ・・・SF = 0


(FFFF)16は、10進数で65535であるため、SFが0のまま変化しません。


以上のように、似たような比較命令でも真逆の結果になってしまうのですね。


その前に、なぜ、-1と65535が同じになってしまうのか?それについては「16進数のマイナスの数」の記事も参考にしてみてください。





比較の仕組み



コンピュータにおいて比較とは、比較する値と値の減算をハードウェア上で行うことによって実現しています。


すなわち、「第1オペランド - 第2オペランド」 を行いフラグレジスタがどう変化したのかを見て判断しています。


【比較の方法】
第1オペランド ― 第2オペランド



ここで、「CPA GR0, GR1」 のニーモニックを例に比較してみましょう。


まず、COMET2は、比較のために減算(GR0 - GR1 )を行います。


その結果...以下①~③のようになります。



① GR0 < GR1になった場合

GR0 < GR1ということは、GR0がGR1より小さいということであり、減算の結果はマイナスのため SF = 1 になります。


【フラグレジスタ】
ZFSFOF
010



② GR0 = GR1になった場合

GR0 = GR1ということは、GR0とGR1が同じということであり、減算の結果はゼロのため ZF = 1 になります。


【フラグレジスタ】
ZFSFOF
100



③ GR0 > GR1になった場合

GR0 > GR1ということは、GR0がGR1より大きいということであり、減算の結果はプラスのため SF = 0、ZF = 0 になります。


【フラグレジスタ】
ZFSFOF
000


このように、大小の比較は、減算によって変化するフラグレジスタの状態を参照することで実現しています。尚、比較命令を使う場合は、OF(オーバーフローフラグ)は気にしなくても問題ありません。











分岐命令






分岐命令は、通常、フラグレジスタを変化させる命令の後に使用する命令です。


分岐命令は、フラグレジスタの内容を参照し、ラベルで指定されら行に移動する機能を持っていて、フラグレジスタを変化させる命令の後に記述します。


実は、CASL2にはフラグレジスタを変化させる命令と変化させない命令の2種類が存在します。通常、分岐命令は、フラグレジスタを変化させる命令の後の行に記述して使用します。


どの命令がフラグレジスタを変化させ、どの命令がフラグレジスタを変化させないのか、については「CASL2でフラグレジスタを変化させる命令の種類」の記事を参考にしてみてください。




分岐命令の使用に慣れない内は、比較命令とセットで考えることで、解りやすいでしょう。



正分岐



名称オペコード第1オペランド第2オペランド
Jump
on
PLus
JPLラベル---
アドレスレジスタ

使用例1: JPL LOOP

フラグレジスタの ZF = 0 かつ SF = 0 のとき、ラベルLOOPの行に移動せよ。



使用例2: JPL 1, GR1

フラグレジスタの ZF = 0 かつ SF = 0 のとき、メモリ汎用レジスタGR1のデータ+1番地の行に移動せよ。



通常、使用例1のような使い方をします。


SF = 0 かつ ZF = 0。つまり、0以外でプラスのとき指定した行(アドレス)に分岐、という意味です。


※ 数値がプラスのときに分岐するため、値が0の時には分岐しません。しかし、ゼロという数字も符号が有りません。そこで、ゼロとマイナス数を区別するために ZF = 0 (比較結果がゼロでないとき)という条件も含んで判定されます。



負分岐



名称オペコード第1オペランド第2オペランド
Jump
on
MInus
JMIラベル---
アドレスレジスタ

使用例1: JMI LOOP

フラグレジスタのSF = 1のとき、ラベルLOOPの行に移動せよ。



使用例2: JMI 1, GR1

フラグレジスタのSF = 1のとき、メモリ汎用レジスタGR1のデータ+1番地の行に移動せよ。



通常、使用例1のような使い方をします。

SF = 1。つまり、符号が付いたとき(マイナスのとき)に、指定した行(アドレス)に分、という意味です。



零分岐



名称オペコード第1オペランド第2オペランド
Jump
on
ZEro
JZEラベル---
アドレスレジスタ

使用例1: JZE LOOP

フラグレジスタのZF = 1のとき、ラベルLOOPの行に移動せよ。



使用例2: JZE 1, GR1

フラグレジスタのZF = 1のとき、メモリ汎用レジスタGR1のデータ+1番地の行に移動せよ。



通常、使用例1のような使い方をします。

ZF = 1。つまり、0のときに、指定した行(アドレス)に分岐、という意味です。



非零分岐



名称オペコード第1オペランド第2オペランド
Jump
on
Non Zero
JNZラベル---
アドレスレジスタ

使用例1: JNZ LOOP

フラグレジスタのZF = 0のとき、ラベルLOOPの行に移動せよ。



使用例2: JNZ 1, GR1

フラグレジスタのZF = 0のとき、メモリ汎用レジスタGR1のデータ+1番地の行に移動せよ。



通常、使用例1のような使い方をします。


ZF = 0。つまり、0でないのときに、指定した行(アドレス)に分岐、という意味です。



オーバーフロー分岐



名称オペコード第1オペランド第2オペランド
Jump
on
OVerflow
JOVラベル---
アドレスレジスタ

使用例1: JOV LOOP

フラグレジスタのOF = 1のとき、ラベルLOOPの行に移動せよ。



使用例2: JOV 1, GR1

フラグレジスタのOF = 1のとき、メモリ汎用レジスタGR1のデータ+1番地の行に移動せよ。



通常、使用例1のような使い方をします。


OF = 1。つまり、数値がオーバーフローしたとき、指定した行(アドレス)に分岐、という意味です。



無条件分岐



名称オペコード第1オペランド第2オペランド
unconditional
JUMP
JUMPラベル---
アドレスレジスタ

使用例1: JUMP LOOP

ラベルLOOPの行(アドレス)に移動せよ。



使用例2: JUMP 1, GR1

メモリ汎用レジスタGR1のデータ+1番地の行に移動せよ。



通常、使用例1のような使い方をします。

フラグレジスタは関係なしに、指定した行(アドレス)に分岐、という意味ですね。



分岐命令は、CPA・CPL命令とセットで使用したり、フラグレジスタを変化させる命令の直前に記述されていることが多いです。





最後に



今回は、比較命令・分岐命令ということで紹介いたしました。


分岐命令の動作に慣れていない内は解り難いと感じますが、実際に手を動かしている内に理解できるようになってきますから、頑張ってシミュレータでプログラムを組んでみてください。


続きはまた次回にご期待を!














プロフィール

ニッシー
1990年生まれ
血液型 O型

こんにちは。ITブログアルケーナム管理人のニッシーです。

詳細プロフィールへ

お問い合わせへ