あなたCPUなんか創ってどうするのかしら?! 第4章 第8節
~あんたCPUなんか創ってどうするのよ?! Vol.4~
2018/10/8
技術書典5 け39
第4章 第8節 二桁電卓
CALC2: | ; 2桁電卓 | |||||
200: | 6F | MOV | A | 0xF | ; AC | |
201: | A1 | MOV | [1] | A | ; 最後のキー | |
202: | A2 | MOV | [2] | A | ; 直前のキー | |
203: | A3 | MOV | [3] | A | ; 現在の演算 | |
204: | 60 | MOV | A | 0 | ||
205: | A4 | MOV | [4] | A | ; X | |
206: | A5 | MOV | [5] | A | ||
207: | A6 | MOV | [6] | A | ||
208: | A7 | MOV | [7] | A | ; Y | |
209: | A8 | MOV | [8] | A | ||
20A: | A9 | MOV | [9] | A | ||
CALC2A: | ||||||
20B: | 44 | MOV | A | [4] | ; X表示 | |
20C: | AE | MOV | [0xE] | A | ||
20D: | 70 | MOV | B | 0 | ||
20E: | BF | MOV | [0xF] | B | ||
20F: | 6F | MOV | A | 0xF | ; 10の位消灯 | |
210: | 55 | MOV | B | [5] | ; 0か? | |
211: | 3F | SUB | B | 1 | ||
212: | E5 | JNC | CALC2B | |||
213: | 21 | |||||
214: | 45 | MOV | A | [5] | ||
CALC2B: | ||||||
215: | AE | MOV | [0xE] | A | ||
216: | 71 | MOV | B | 1 | ||
217: | BF | MOV | [0xF] | B | ||
218: | 46 | MOV | A | [6] | ; 符号 | |
219: | AE | MOV | [0xE] | A | ||
21A: | 72 | MOV | B | 2 | ||
21B: | BF | MOV | [0xF] | B | ||
CALC2C: | ||||||
21C: | 41 | MOV | A | [1] | ; 最後キー | |
21D: | A2 | MOV | [2] | A | ||
21E: | 63 | MOV | A | 3 | ; CALC2D | |
21F: | A0 | MOV | [0] | A | ||
220: | F0 | JMP | KBDIN | ; キー入力 | ||
221: | 08 | |||||
CALC2D: | ||||||
222: | A1 | MOV | [1] | A | ; 最後のキー | |
223: | 26 | SUB | A | 0xA | ; 数値X分岐 | |
224: | EE | JNC | CALC2E | |||
225: | 22 | |||||
226: | 2C | SUB | A | 4 | ; +-×÷か? | |
227: | E0 | JNC | CALC2G | |||
228: | 24 | |||||
229: | 2F | SUB | A | 1 | ; =か? | |
22A: | EF | JNC | CALC2H | |||
22B: | 24 | |||||
22C: | F0 | JMP | CALC2 | ; AC処理 | ||
22D: | 20 | |||||
CALC2E: | ; X入力 | |||||
22E: | 70 | MOV | B | 0 | ; 10の位 | |
22F: | B5 | MOV | [5] | B | ||
230: | 69 | MOV | A | 9 | ; 2桁か? | |
231: | 82 | SUB | A | [2] | ||
232: | E6 | JNC | CALC2F | |||
233: | 23 | |||||
234: | 44 | MOV | A | [4] | ; 桁シフト | |
235: | A5 | MOV | [5] | A | ||
CALC2F: | ||||||
236: | 41 | MOV | A | [1] | ; Xに格納 | |
237: | A4 | MOV | [4] | A | ||
238: | 42 | MOV | A | [2] | ; =直後か? | |
239: | 22 | SUB | A | 0xE | ||
23A: | EB | JNC | CALC2A | |||
23B: | 20 | |||||
23C: | 6F | MOV | A | 0xF | ; 演算クリア | |
23D: | A3 | MOV | [3] | A | ; +-×÷ | |
23E: | FB | JMP | CALC2A | |||
23F: | 20 | |||||
CALC2G: | ; +-×÷キー | |||||
240: | 43 | MOV | A | [3] | ; 演算確認 | |
241: | 2C | SUB | A | 4 | ||
242: | E5 | JNC | CALC2I | ; 演算実行 | ||
243: | 25 | |||||
244: | 44 | MOV | A | [4] | ; 演算未入力 | |
245: | A7 | MOV | [7] | A | ; X→Y移動 | |
246: | 45 | MOV | A | [5] | ||
247: | A8 | MOV | [8] | A | ||
248: | 46 | MOV | A | [6] | ||
249: | A9 | MOV | [9] | A | ||
24A: | 41 | MOV | A | [1] | ; 演算確定 | |
24B: | 26 | SUB | A | 0xA | ||
24C: | A3 | MOV | [3] | A | ||
24D: | FC | JMP | CALC2C | ; X入力 | ||
24E: | 21 | |||||
CALC2H: | ; =キー処理 | |||||
24F: | 43 | MOV | A | [3] | ; 演算確認 | |
250: | 2C | SUB | A | 4 | ||
251: | E9 | JNC | CALC2J | ; 演算実行 | ||
252: | 25 | |||||
253: | FC | JMP | CALC2C | ; X入力 | ||
254: | 21 | |||||
CALC2I: | ; 演算入力済 | |||||
255: | 6D | MOV | A | 0xD | ; =か? | |
256: | 82 | SUB | A | [2] | ||
257: | EA | JNC | CALC2K | ; =の直後 | ||
258: | 26 | |||||
CALC2J: | ; 演算判定 | |||||
259: | 56 | MOV | B | [6] | ; Xの符号 | |
25A: | 43 | MOV | A | [3] | ; +-×÷ | |
25B: | 2F | SUB | A | 1 | ||
25C: | EF | JNC | CALC2L | ; 加減算 | ||
25D: | 26 | |||||
25E: | 38 | ADD | B | 8 | ; X符号反転 | |
25F: | 2F | SUB | A | 1 | ||
260: | EF | JNC | CALC2L | ; 加減算 | ||
261: | 26 | |||||
262: | 2F | SUB | A | 1 | ||
263: | E0 | JNC | MUL2 | ; 乗算 | ||
264: | 31 | |||||
265: | 2F | SUB | A | 1 | ||
266: | E0 | JNC | DIV2 | ; 除算 | ||
267: | 36 | |||||
268: | F0 | JMP | CALC2 | ; エラー | ||
269: | 20 | |||||
CALC2K: | ; =直後 | |||||
26A: | 41 | MOV | A | [1] | ; 演算確定 | |
26B: | 26 | SUB | A | 0xA | ||
26C: | A3 | MOV | [3] | A | ||
26D: | FC | JMP | CALC2C | ; 戻る | ||
26E: | 21 | |||||
CALC2L: | ; 加減算 | |||||
26F: | 19 | ADD | B | [9] | ; Yの符号 | |
270: | 64 | MOV | A | 4 | ; CALC2M | |
271: | A0 | MOV | [0] | A | ||
272: | 38 | ADD | B | 8 | ; 符号確認 | |
273: | E0 | JNC | ADD2 | ; 加算へ | ||
274: | 28 | |||||
275: | F0 | JMP | SUB2 | ; 減算へ | ||
276: | 2B | |||||
ADD2: | ; 無符号加算 | |||||
280: | 47 | MOV | A | [7] | ; 1の位 | |
281: | 04 | ADD | A | [4] | ||
282: | A7 | MOV | [7] | A | ||
283: | 70 | MOV | B | 0 | ; 繰り上げ無 | |
284: | E7 | JNC | ADD2A | |||
285: | 28 | |||||
286: | 71 | MOV | B | 1 | ; 繰り上げ有 | |
ADD2A: | ||||||
287: | 26 | ADD | A | 6 | ; 10進補正 | |
288: | EB | JNC | ADD2B | |||
289: | 28 | |||||
28A: | 71 | MOV | B | 1 | ; 繰り上げ有 | |
ADD2B: | ||||||
28B: | 3F | SUB | B | 1 | ||
28C: | E2 | JNC | ADD2C | ; 補正不要 | ||
28D: | 29 | |||||
28E: | A7 | MOV | [7] | A | ; 補正済 | |
28F: | 58 | MOV | B | [8] | ; 繰り上げ | |
290: | 31 | ADD | B | 1 | ||
291: | B8 | MOV | [8] | B | ||
ADD2C: | ||||||
292: | 58 | MOV | B | [8] | ; 10の位 | |
293: | 15 | ADD | B | [5] | ||
294: | B8 | MOV | [8] | B | ||
295: | 60 | MOV | A | 0 | ; 繰り上げ無 | |
296: | E9 | JNC | ADD2D | |||
297: | 29 | |||||
298: | 61 | MOV | A | 1 | ; 繰り上げ有 | |
ADD2D: | ||||||
299: | 36 | ADD | B | 6 | ; 10進補正 | |
29A: | ED | JNC | ADD2E | |||
29B: | 29 | |||||
29C: | 61 | MOV | A | 1 | ; 繰り上げ有 | |
ADD2E: | ||||||
29D: | 2F | SUB | A | 1 | ||
29E: | E4 | JNC | ADD2F | ; 補正不要 | ||
29F: | 2A | |||||
2A0: | B8 | MOV | [8] | B | ; 補正済 | |
2A1: | 49 | MOV | A | [9] | ; 符号 | |
2A2: | 21 | ADD | A | 1 | ||
2A3: | A9 | MOV | [9] | A | ||
ADD2F: | ||||||
2A4: | FC | JMP | RET | ; RETURN | ||
2A5: | 0F | |||||
SUB2: | ; 無符号減算 | |||||
2B0: | 47 | MOV | A | [7] | ; 1の位 | |
2B1: | 84 | SUB | A | [4] | ||
2B2: | A7 | MOV | [7] | A | ||
2B3: | E7 | JNC | SUB2A | ; マイナス | ||
2B4: | 2B | |||||
2B5: | FE | JMP | SUB2B | ; 10の位へ | ||
2B6: | 2B | |||||
SUB2A: | ; 繰下げ処理 | |||||
2B7: | 2A | ADD | A | 10 | ; 10進補正 | |
2B8: | A7 | MOV | [7] | A | ||
2B9: | 58 | MOV | B | [8] | ; 借り | |
2BA: | 3F | SUB | B | 1 | ||
2BB: | B8 | MOV | [8] | B | ||
2BC: | E5 | JNC | SUB2C | ; マイナス | ||
2BD: | 2C | |||||
SUB2B: | ||||||
2BE: | 58 | MOV | B | [8] | ; 10の位 | |
2BF: | 95 | SUB | B | [5] | ||
2C0: | B8 | MOV | [8] | B | ||
2C1: | E8 | JNC | SUB2D | ; マイナス | ||
2C2: | 2C | |||||
2C3: | FC | JMP | RET | ; RETURN | ||
2C4: | 0F | |||||
SUB2C: | ||||||
2C5: | 58 | MOV | B | [8] | ; 10の位 | |
2C6: | 95 | SUB | B | [5] | ||
2C7: | B8 | MOV | [8] | B | ||
SUB2D: | ; 補正 | |||||
2C8: | 6A | MOV | A | 10 | ||
2C9: | 87 | SUB | A | [7] | ||
2CA: | A7 | MOV | [7] | A | ||
2CB: | 7F | MOV | B | 0xF | ||
2CC: | 26 | SUB | A | 10 | ||
2CD: | E1 | JNC | SUB2E | |||
2CE: | 2D | |||||
2CF: | 70 | MOV | B | 0 | ||
2D0: | B7 | MOV | [7] | B | ||
SUB2E: | ||||||
2D1: | 98 | SUB | B | [8] | ||
2D2: | B8 | MOV | [8] | B | ||
2D3: | 49 | MOV | A | [9] | ; 符号反転 | |
2D4: | 28 | ADD | A | 8 | ||
2D5: | A9 | MOV | [9] | A | ||
2D6: | FC | JMP | RET | ; RETURN | ||
2D7: | 0F | |||||
CALC2M: | ; 結果表示 | |||||
2E0: | 47 | MOV | A | [7] | ; Y表示 | |
2E1: | AE | MOV | [0xE] | A | ||
2E2: | 70 | MOV | B | 0 | ||
2E3: | BF | MOV | [0xF] | B | ||
2E4: | 6F | MOV | A | 0xF | ||
2E5: | 59 | MOV | B | [9] | ; 10の位消灯 | |
2E6: | 19 | ADD | B | [9] | ||
2E7: | 18 | ADD | B | [8] | ||
2E8: | 3F | SUB | B | 1 | ||
2E9: | EC | JNC | CALC2N | |||
2EA: | 2E | |||||
2EB: | 48 | MOV | A | [8] | ||
CALC2N: | ||||||
2EC: | AE | MOV | [0xE] | A | ||
2ED: | 71 | MOV | B | 1 | ||
2EE: | BF | MOV | [0xF] | B | ||
2EF: | 49 | MOV | A | [9] | ||
2F0: | AE | MOV | [0xE] | A | ||
2F1: | 72 | MOV | B | 2 | ||
2F2: | BF | MOV | [0xF] | B | ||
2F3: | 09 | ADD | A | [9] | ; エラーか? | |
2F4: | 2E | ADD | A | 0xE | ||
2F5: | E0 | JNC | CALC2P | ; 正常 | ||
2F6: | 30 | |||||
CALC2O: | ; エラー | |||||
2F7: | 6B | MOV | A | 0xB | ; AC待機 | |
2F8: | AE | MOV | [0xE] | A | ||
2F9: | 4E | MOV | A | [0xE] | ||
2FA: | 22 | ADD | A | 0x2 | ||
2FB: | 2F | ADD | A | 0xF | ||
2FC: | EC | JNC | CALC2C | ; AC処理へ | ||
2FD: | 21 | |||||
2FE: | F7 | JMP | CALC2O | |||
2FF: | 2F | |||||
CALC2P: | ||||||
300: | 6D | MOV | A | 0xD | ; 演算確定 | |
301: | 81 | SUB | A | [1] | ||
302: | EC | JNC | CALC2C | ; =キーか? | ||
303: | 21 | |||||
304: | 41 | MOV | A | [1] | ; 演算確定 | |
305: | 26 | SUB | A | 0xA | ||
306: | EC | JNC | CALC2C | ; 数字キー | ||
307: | 21 | |||||
308: | A3 | MOV | [3] | A | ; 演算確定 | |
309: | FC | JMP | CALC2C | ; 入力に戻る | ||
30A: | 21 | ; 終了 |
本プロジェクトの本命である2桁電卓です。整数2桁による四則演算が可能です。
入力はテンキー、出力は7セグメントLEDです。
1 + 2 + 3 = という具合に連続して計算を行うことができます。
1 + 1 = = = のように = キーを連打して同じ計算を繰り返し実行することもできます。
2桁の整数である点を除けば普通の電卓です。
プログラムの中身は1桁電卓とほぼ同じですが、腰を据えてじっくり作りましたので分かり易いと思います。少なくともスパゲティ状態にはなっていません。
以下、注意点。
イミディエイトデータによる減算命令を使っていますが、これは2の補数による加算に置き換えて考えてください。
逆に、イミディエイトデータを先にアキュムレーターに読み込んでから減算をしている箇所がありますが、これは条件分岐命令がJNCしかない不便さを回避するための苦肉の策です。
JNC命令はキャリーが発生しない場合に分岐しますが、シチュエーションによってはキャリーが発生した場合に分岐したい場合もあります。そのような時は減算対象を入れ替えることでキャリー発生条件を逆転させている訳です。
プログラム内にはADD2とSUB2という2つの疑似サブルーチンがあります。KBDINと同様に、これらもRAMの0番地に戻り先番号を格納してから呼び出します。KBDINの末尾にある疑似RETURN命令を利用しているため、戻り先番号は全ての疑似サブルーチンで共通です。
この電卓プログラムは10進数で計算を行っていますので、それぞれの桁毎に計算結果が10以上になったかどうかを確認し、もし10以上ならば繰り上がり補正を行う必要があります。
一般的なCPUの場合、この処理は専用の命令によって行うのが普通です。これは4004の開発者の一人である嶋正利氏によって発明されたと言われている由緒正しい命令なのですが、残念ながらTD4EX4にはありません。
仕方ないので本プログラムでは、演算結果に6を加算し、キャリーが発生したら補正する、という強引な方法を使っています。