SSブログ
English Version

SuperSimpleController(その15)逆ポーランド記法 [OriginalCPU]

 前回の記事で書いたようにモニタプログラムができ、パソコン側で開発したアプリケーションのロードも容易になったので2バイト整数の演算処理を作ってみました。

 今回開発した8bit CPU(Simple8Z)はハードウェアを最小化(13チップ構成)するためにハードリソースも必要最小限に近い構成なので2バイト演算をレジスタのみではできず、Z-80等に比べるとコード効率が2倍以上悪くなります。

 今回作成した2バイト整数の四則演算処理のアセンブラソースを貼っておきます。
 乗算と除算の処理内容としては10進数の場合に筆算で行う処理と同様なロジックで作成しています。0除算の場合はキャリーフラグを立てるようにしました。

2バイト整数の四則演算処理(Simple8Z用アセンブリ言語)
; Addition ; Para1 <- Para1 + Para2 AddW: RD_R0 Para2 LD_R1_R0 RD_R0 Para1 ADD_R0_R1 WR_R0 Para1 RD_R0 <Para2 + 1> LD_R1_R0 RD_R0 <Para1 + 1> ADC_R0_R1 WR_R0 <Para1 + 1> RET ; subtraction ; Para1 <- Para1 - Para2 SubW: RD_R0 Para2 LD_R1_R0 RD_R0 Para1 SUB_R0_R1 WR_R0 Para1 RD_R0 <Para2 + 1> LD_R1_R0 RD_R0 <Para1 + 1> SBC_R0_R1 WR_R0 <Para1 + 1> RET ; Absolute value ; Para1 <- abs(Para1) AbsW: RD_R0 <Para1 + 1> ; get high byte CKMSBR0 ; check MSB of R0 JNC AbsW90 ; if plus NegW: RD_R0 Para1 LD_R1_R0 CLR_R0 SUB_R0_R1 WR_R0 Para1 RD_R0 <Para1 + 1> LD_R1_R0 CLR_R0 SBC_R0_R1 WR_R0 <Para1 + 1> AbsW90: RET ; multiplication ; Para1 <- Para1 x Para2 MulW: RD_R0 Para1 WR_R0 CalTmp RD_R0 <Para1 + 1> WR_R0 <CalTmp + 1> CLR_R0 WR_R0 Para1 WR_R0 <Para1 + 1> LD_R0 16 WR_R0 CalCnt ; set loop counter MulWLp: RD_R0 <CalTmp + 1> SHR_R0 WR_R0 <CalTmp + 1> RD_R0 CalTmp SHRC_R0 WR_R0 CalTmp JNC MulW10 CALL AddW MulW10: RD_R0 Para2 ; Para2 <- Para2 * 2 SHL_R0 WR_R0 Para2 RD_R0 <Para2 + 1> SHLC_R0 WR_R0 <Para2 + 1> RD_R0 CalCnt DEC_R0 WR_R0 CalCnt JNZ MulWLp RET ; division ; Para1 <- Para1 / Para2 ; Para1 -> division ; CalMod -> modulo ; Cy -> 1:error DivW: RD_R0 Para2 LD_R1_R0 RD_R0 <Para2 + 1> OR_R0_R1 JZ DivErr CLR_R0 WR_R0 CalMod WR_R0 <CalMod + 1> LD_R0 16 WR_R0 CalCnt DivWLp: RD_R0 Para1 ; (CalMod : Para1) << 1 SHL_R0 WR_R0 Para1 RD_R0 <Para1 + 1> SHLC_R0 WR_R0 <Para1 + 1> RD_R0 CalMod SHLC_R0 WR_R0 CalMod RD_R0 <CalMod + 1> SHLC_R0 WR_R0 <CalMod + 1> RD_R0 <Para2 + 1> LD_R1_R0 RD_R0 <CalMod + 1> CP_R0_R1 JC DivW20 JNZ DivW10 RD_R0 Para2 LD_R1_R0 RD_R0 CalMod CP_R0_R1 JC DivW20 DivW10: RD_R0 Para2 ; CalMod <- CalMod - Para2 LD_R1_R0 RD_R0 CalMod SUB_R0_R1 WR_R0 CalMod RD_R0 <Para2 + 1> LD_R1_R0 RD_R0 <CalMod + 1> SBC_R0_R1 WR_R0 <CalMod + 1> RD_R0 Para1 ; Para1 <- Para1 + 1 INC_R0 WR_R0 Para1 ; always no Cy DivW20: RD_R0 CalCnt DEC_R0 WR_R0 CalCnt JNZ DivWLp RET DivErr: CKZR1 ; set Cy RET

★追記 2021/04/30
 AbsWとNegWを追加
★追記 2021/04/28
 乗算処理内で加算処理をコールしているので加算と減算処理のソースを追加
★変更 2021/04/27
 除算処理で商を直接Para1に設定するようにしてコード短縮&高速化

 乗算処理ができるようになったのでこれを使って10進数の文字列のバイナリ変換が作れます。また、除算処理を使ってバイナリをアスキー文字に変換する処理も作れます。

 作成したバイナリと10進アスキー文字列の相互変換と演算処理の動作確認をするために電卓のように自由に演算対象の数値を変更して演算できる環境が欲しくなります。

 演算子を使った一般的な数式を評価する処理を作成するのは少々面倒なので、割合簡単に作成できるスタックを使用した逆ポーランド記法(RPN)の数式を処理する環境を作ってみました。

 下図が作成した整数型RPN電卓の操作例です。下記の操作を行っています。最後に実行しているRPN式はウィキペディアに記載されているものです。
  1. EEPROM内のHexローダーを起動
  2. モニタプログラムのHexファイルをロードし、自動起動
  3. モニタのヘルプ表示
  4. r(Hexリード)コマンド実行
  5. RPN電卓のHexファイルをロード
  6. RPN電卓を起動
  7. RPN電卓のヘルプ表示(dupはスタックトップを複製するコマンド)
  8. 1から10までの合計値を計算
  9. 111の二乗を計算
  10. 1000/6を計算
  11. サンプルのRPN式の評価結果を10進と16進で表示

RPN電卓操作例


★変更 2021/05/05
 マイナス値の乗算例を追加
★変更 2021/04/28
 除算例を追加


[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー