CPU実験室

誰も見向きもしない古いCPUをいじって動かしてみようというプロジェクトです

条件判断

これは実際にとっかえひっかえして動かすとすぐにわかるのですが意外にも「LT」(Less Than)が正解なのです。
R0レジスタと10を比べてR0の値が同じか大きければ分岐させたいので直感的には「GE」(Greater Than or Equal)なんですがそれをやると前回のダンプリストのバケバケ表示になってしまいます。

 

なぜ混乱するのか・・

これには二重のひっかけがあって先ずNS32000シリーズのオペランドの配置順です。
インテルx86ザイログニーモニック表記は
OPCODE destination,source でしたが

モトローラ68000やこのNS32000、またGNUAssemblerのAT&T形式では
OPCODE source,destination  の順となります。

したがってNS32000では cmp 10,r0 と書くことになりますが
比較命令CMPの結果はどちらの形式でもdestinationーsourceの値が評価されるので見た目、引算の方向が逆になり勘違いの元です。

しかもその上、マニュアルを見て気付いたのですが条件分岐でのフラグの見方がx86と32kではまるで逆なのです

f:id:O3I:20200122230538j:plain

たとえば32kでは「GE」(Greater Than or Equal)はZ or N flag set・・すなわち比較の結果が0または負で真になりますが
一方x86での「GE」はちょっと表現は変わりますが(S xor O)=0・・・つまり結果が正でオーバーフローしてないことで真です。何でわざわざ逆にしたのか。。謎ですね。

そのためx86で同じ動作をする処理はこう書くことになります。これは直感的に流れがわかります

f:id:O3I:20200122230840j:plain

ただ色々やっているうちにちょっとうまい抜け道に気付きました。逆の逆は正とも言えます。NS32000は命令の直交性が高くレジスタと即値をひっくり返して書いてもOKなので同じ「GE」条件を使って

f:id:O3I:20200122231202j:plain

これも正常動作します。見た目はx86のコーディングとほぼ同じになりました。

ところで’A’-10の値を55と直打ちしているのはアセンブラの仕様?で即値に数式は受け付けてくれないからです。アセンブラは’A’だけ評価してエラーも出さずにしれっと65(0x41)のコードを吐いて正常終了するのでだまされました。