Add、Sub、Neg、And、Or【NandGame編】
目次
はじめに
いつもブログをご覧いただきありがとうございます。
コーストFIRE中のIPUSIRONです😀
スタックを演算に利用する
スタックを使えば、特定のレジスターに依存しないマクロ演算(加算や減算など)を実現できます。
代わりに、演算はオペランドをスタックからPOPし、演算結果をスタックにPUSHし直します。
この方法だと、利用可能なレジスターの数に制限されないので、任意の複雑な計算ができます。
Addレベル
Addレベルのゴールは、スタックで加算を実現することです。
スタックに2つの値をPOPして、それらを加算してから、その合計値をスタックにPUSHします。
Addレベルを解く
POP_D
POP_A
D = D + A
PUSH_D
スタックからPOPした値を2つのレジスターにセットします。
※1~2行目は逆でも構いません。
レジスターの値を加算したら、PUSHでスタックに戻します。
その際、マクロPUSH_Aは存在しませんので、計算結果はレジスターDに入れてから、PUSH_Dを呼び出します。
Subレベル
Subレベルのゴールは、スタックで減算を実現することです。
スタックから2つの値をPOPし、2つ目の値から1つ目の値を引きます(最初にPOPした値が引く値、後にPOPした値が引かれる値になる)。計算結果はスタックに戻します。
Subレベルを解く
Addレベルのアセンブリーコードでは加算でしたが、代わりに減算すればよいだけです。
ただし、1点だけ注意が必要です。加算では足す側と足される側を区別しなくても計算結果は変わりませんが、減算はそういきません。Subレベルに要求されていたのは、後からPOPされる側が引かれる数ということです。
POP_D
POP_A
D = A - D
PUSH_D
初回のPOPはレジスターD、次のPOPはレジスターAにセットしていているため、3行目のように「D = A – D」とする必要があります。
Negレベル
Negレベルのゴールは、スタックを使って算術否定を実現することです。算術否定とは、符号を逆転することを意味します。例えば、2の(算術)否定は-2になります。
Negレベルを解く
POP_D
D = - D
PUSH_D
Andレベル
Andレベルのゴールは、スタックでAND演算を実現することです。
スタックから2つ値をPOPして、ビットごとのAND演算(ここでは16ビットなので16ビットAND演算)を実行し、計算結果をスタックに戻します。
Andレベルを解く
NandGameのアセンブリー言語では、AND演算のために&演算子を使います。
POP_D
POP_A
D = D & A
PUSH_D
Orレベル
Orレベルのゴールは、スタックでOR演算を実現することです。
スタックから2つ値をPOPして、ビットごとのOR演算(ここでは16ビットなので16ビットOR演算)を実行し、計算結果をスタックに戻します。
Orレベルを解く
NandGameのアセンブリー言語では、AND演算のために|演算子を使います。
POP_D
POP_A
D = D | A
PUSH_D