sub命令とcmp命令は内部的な計算は同じで、減算を行いその結果を
ファミコンのステータス
レジスタに書き込みます(キャリーだったり、オバーフローだったりの結果を保存する
レジスタ)。 sub命令で変換されるフラッグは、キャリー、オバーフロー、ゼロ、ネガティブの四つです。cmp命令ではオーバーフローは更新されません。 sub命令は計算の結果を保存しますが、cmp命令は結果は虚無へ捨てます。まぁ、それだけの大したことないよくある命令です。
ファミコンではsub,cmpでの減算をおこなう際、
- Aレジスタからメモリまたは即値を減算する
- キャリーフラッグを反転したものを減算する
といった手順で計算する。
これら手順が終了した際に四つのフラッグを変更するものだと思ってました。
勘違いしていた間違っている仕様
- Aレジスタからメモリまたは即値を減算する
- キャリーフラッグを反転したものを減算する
- 計算結果に応じて4つの各フラッグを書き換える
しかし、実際の仕様は以下でした。
実際の仕様
- Aレジスタからメモリまたは即値を減算する
- キャリー/オバーフローフラッグを更新する
- キャリーフラッグを反転したものを減算する
- 計算結果に応じてゼロ/ネガティブフラッグを更新する
まさかのタイミングが違う。これが違うと
スーパーマリオブラザースでは正しいタイミングで敵が現れてくれない。
これに関してはsub命令、cmp命令が間違っていることさえわかってしまえば気づくことができる。
ファミコンにはnestestromという便利なものがあり、それで簡単にわかる。 逆に言えばnestestromの存在を知らないとかなりきつい。