算術演算

算術演算は四則演算、加減乗除のことです。対象となるのは原則アキュムレータ(A)だけです。

DeMは小数は扱えません。扱えるのはすべてゼロ以上の整数のみ、0~99999999の範囲です。これだけでも大体のことができてしまいます。負の数だって工夫次第です。小数を扱いたいときはプログラムを作って扱えるようにしましょう。ハードワークかもしれませんがとてもいい勉強になります。目からうろこ、数学が楽しくなること請け合いです。

Operation Mnemonic inCode Opr2 Opr3 Opr4 Opr5 #bytes Opcode Ie Cy Cd
A <- A + 1 INC 1 70 Y Y
A <- A – 1 DEC 1 71 Y Y
A <- 0 – A NEG 1 72 Y Y
A <- 99999999 – A COM 1 73 0 Y
A <- A + Val(2d, Signed) ADDI Val 2 74 vv Y Y
A – Val(2d) CMPI Val 2 75 vv Y Y
A <- A + R ADD R 2 76 0R Y Y
A <- A – R SUB R 2 76 1R Y Y
A – R CMP R 2 76 2R Y Y
A <- A * R MPY R 2 76 3R 0 Y
A <- A / R ; R0 <- A mod R DIV R 2 76 4R 0 Y

INCとDECは1の加算と減算ですから簡単です。演算の結果に応じてステータスレジスタ(SR)のCyフラグとCdフラグが変化します。条件分岐に使えます。

ADDIは定数を加算します。Opcode欄の「vv」に00~99の値を指定するのですが、この定数だけは少し変わった使い方をします。00~49は正の数として扱い、50~99は負の数として扱います。99は-1、98は-2とし、50は-50になります。つまり加算命令で減算ができるのです。このような数の扱い方を「補数」と呼び、このADDIでは「10進2桁における10の補数を定数とする」となります。この補数については後述します。

ADD、SUB、MPYは汎用レジスタを1つ指定して、Aに加算、Aから減算、Aに乗算します。Opcode欄の「R」にレジスタ番号0~9を入れてください。加算と減算では桁上げ、桁借り(繰り上がり、繰り下がり)が生じるとCyを1にセットします。乗算では桁あふれは無視され、Cyは必ず0になります。

DIVは汎用レジスタを1つ指定してAを除算します。整数演算ですから商と余りがでます。商がAに残り、余りはR0に入ります。除算もCyは必ず0になります。また、0での割り算は数学的に禁止行為ですから、そのようなことが起こると演算は行われず代わりにCdがエラーを示す「3」になります。

CMPIとCMPは比較演算といい、演算自体は減算と同じですが演算結果をAに残さない(Aは演算前と変わらない)というのがほかの演算と異なるところです。SR内のフラグCyとCdのみを変化させるのに使います。CMPIは定数との比較、CMPは汎用レジスタとの比較です。

x 0 1 2 3 4 5 6 7 8 9
COM(x) 9 8 7 6 5 4 3 2 1 0

COMとNEGは似たような動作をします。COMは99999999からAの値を引いてAに戻します。何が起こるかというと、Aのすべての桁が「反転」します。この「反転」は右図のように起こります。

次にNEGですが、0からAの値を引いてAに戻します。正の整数のみ扱うので0からは引けないと考えてしまいますが、無理やり引くことができます。つまり最上位の桁のさらに上に「1」があると仮定して引き算するのです。すなわち100000000-Aを行います。すると結果はCOMの結果に1を加えたものになります。結果論になりますが、これが「10の補数」をとったことになり、Aの符号を反転させたことになるのです。実際にDeMで負の数を作って加算し、これが減算となること*1をぜひ試してみてください。

Aの符号を反転させて負の数を作れました。補数であれば最上位の桁が5~9であれば負の数とわかります。とはいえマイナス符号があるわけではなく、入れ物は8桁の数字だけです。補数であるかどうかの区別は見ただけではわかりません。そのデータを補数で扱うか正の整数で扱うかはプログラムを組む人が覚えておかなければならないのです。

*1 2進数でもまったく同様で、どのようなCPUでも加算回路はあるが減算回路はありません。減算するには減数を反転して加算し、結果に1を加えればいいのですから。

コーディング例

Addr Data Label Opcode Operand Comment
0000 21 start: LDI 1 Aに1を代入
0001 75 10 loop: CMPI 10 Aと10を比較(Aは変化しない)
0003 42 06 JFGT end A>10ならendにジャンプ
0005 74 01 ADDI 1 Aに1を加える
0007 61 08 JB loop loopにジャンプ
0009 99 end: HALT 停止

補足

  • “INC”は”Increment”(インクリメント、増やす)の略です。
  • “DEC”は”Decrement”(デクリメント、減らす)の略です。
  • “NEG”は”Negate”(ネゲート、符号反転する)の略です。
  • “COM”は”Complement”(コンプリメント、補数をとる)の略です。
  • “ADDI”は”Add Immediate”(アッド・イミディエート、即値を加算する)の略です。
  • “CMP”は”Compare”(コンペア、比較する)の略です。
  • “SUB”は”Subtract”(サブトラクト、減算する)の略です。
  • “MPY”は”Multiply”(マルチプライ、乗算する)の略です。
  • “DIV”は”Divide”(ディバイド、除算する)の略です。