Assembler program【NandGame編】
はじめに
いつもブログをご覧いただきありがとうございます。
コーストFIRE中のIPUSIRONです😀
Assembler programレベル
Assembler programレベルのゴールは、コンピュータの緑ランプを少なくとも3回点滅させるプログラムをアセンブリー言語で書くことです。
外部デバイスであるランプはアドレス7FFFhにメモリーマップされています。このアドレスの16ビットのうち、0ビット目と1ビット目がランプに接続されています。それぞれOn端子、Off端子につながっています。
※ランプを含む外部デバイスが影響を受けるのは、ビットが0から1に変わるときだけです。
そしてビット0と1にメモリーマップされています。
ビットを1にする
0 ランプが点灯
1 ランプが消灯
外部デバイスが影響を受けるのは、ビットが0から1に変わるときだけです。
アセンブリー言語の仕様
本CPUにおけるアセンブリー言語の仕様
[Show Assembler Help]ボタンを押すと右側にアセンブリー言語の各命令が表示されます。
Assembler programレベルを解く
ランプを「点灯⇒消灯⇒点灯⇒・・・」としたければ、「0ビット目をON⇒1ビット目をON⇒・・・」とすればよいのです。やり方はいろいろありますが、アドレス7FFFhのメモリー値を0からインクリメントしていくのがもっとも簡単な方法です。
インクリメントということは「0000 0000 0000 0000b⇒0000 0000 0000 0001b⇒0000 0000 0000 0010b⇒・・・」となります。これは先ほどの流れである「0ビット目をON⇒1ビット目をON⇒・・・」を満たしています。
ただし、「0000 0000 0000 0010b⇒0000 0000 0000 0011b」では消灯したままです。ランプの仕様的にOff端子が優先されてしまうためです。
そこで、0000 0000 0000 0000bにするリセット処理が必要になります。
以上を踏まえてプログラムを実装すると次のようになります。
# Assembler code
A = 0x7FFF
# 1回目の「(消灯⇒)点灯⇒消灯」
*A = *A + 1
*A = *A + 1
# 初期状態にリセット.
*A = 0
# 2回目の「点灯⇒消灯」
*A = *A + 1
*A = *A + 1
*A = 0
# 3回目の「点灯⇒消灯」
*A = *A + 1
*A = *A + 1
*A = 0
computerの[Tick]ボタンや[Reset]ボタンを押して、1命令ずつ実行して、内部状態の変化を確認してください。
最終手金[Check solution]ボタンを押すと、レベルクリアとなります。
共通処理をまとめる【別解】
先ほどの解答には冗長なコードがあります。「点灯⇒消灯」の処理を共通化し、ループで繰り返せばよいだけです。
ゴールの条件は3回以上なので、無限ループでもクリアになるわけです。
プログラムのアドレスを直接数値で指定してもよいですが、アセンブリー言語の仕様を見るとラベルという概念があります。これを使うと、アドレス値を意識する必要はありません。
以上を踏まえてプログラムを実装すると次のようになります。
# Assembler code
LOOP:
A = 0x7FFF
# 「(消灯⇒)点灯⇒消灯」
*A = *A + 1
*A = *A + 1
# 初期状態にリセット.
*A = 0
A = LOOP
JMP
コード量が減ってすっきりしました。