; ------------------------------------------------------------------- ; 16ビットバイナリ→10進変換サブルーチン ; 1997 by M.Ochiai ; ------------------------------------------------------------------- ; in src1 16ビットデータ ; (src1+1:src1+0) ; out dec ; (dec+4:dec+3:...:dec+0) ; dec+0が最下位桁でdec+4が最上位桁です。 ; ; 変換後src1は破壊されます。(必要なら、コールする前に待避して下さい) ; ; sample: ; src1 = 00:00:04:D2 h ; dec = 00:00:00:00:00:00:01:02:03:04 bin16tobcd movlw dec_top ; 格納場所初期値 movwf FSR call devideby10 ; 最下位変換 call devideby10 call devideby10 call devideby10 call devideby10 ; 最上位変換 movlw '0' addwf dec+0,F addwf dec+1,F addwf dec+2,F addwf dec+3,F addwf dec+4,F return ; ; ÷10サブルーチン ; 10で除算します ; devideby10 movlw D'16' ; 16ビットくり返し movwf calc_cn clrf result+2 devideby10_0 bcf STATUS,C rlf result+0,F rlf result+1,F rlf result+2,F movlw D'10' subwf result+2,W btfsc STATUS,C movwf result+2 btfsc STATUS,C incf result+0,F decfsz calc_cn,F goto devideby10_0 decf FSR,F movf result+2,W ; 余り movwf INDF return ;--------------------------------------------------------------------- mul10_24 ; 24bit 10倍ルーチン ; 呼び出し側の都合により、src2 が入力で、src1 が出力です。 movf src2+2,W movwf src1+2 movf src2+1,W movwf src1+1 movf src2+0,W ; src2 => src1 movwf src1+0 bcf STATUS,C ; src1 を 2倍 rlf src1+0,F rlf src1+1,F rlf src1+2,F bcf STATUS,C ; src1 を さらに2倍 で4倍 rlf src1+0,F rlf src1+1,F rlf src1+2,F ; src1 に src2 を足して 5倍 movf src2+0,W ;下位バイトの加算 addwf src1+0,F movlw 1 btfsc STATUS,C addwf src1+1,F btfsc STATUS,C addwf src1+2,F movf src2+1,W ;中位バイトの加算 addwf src1+1,F btfsc STATUS,C incf src1+2,F movf src2+2,W ;上位バイトの加算 addwf src1+2,F bcf STATUS,C ; src1 を さらに2倍 で10倍 rlf src1+0,F rlf src1+1,F rlf src1+2,F return ;********************************************************************* ;--------------------------------------------------------------------- mul161632 ;16×16ビット=32ビットの乗算 ;参考 http://www.sikasenbey.or.jp/~enaga/pic/mul1322.txt ;被乗数、乗数とも保存される ;ルーチン名 : mul161632 ;-------------------- mul161632 での使用変数 ;src1 2 ;被乗数 (変化せず戻る) ;src2 2 ;乗数 (変化せず戻る) ;result 4 ;答え  (答えが返る)(1バイト分 mod を借りていることに注意) ;calc_cn 1 ;内部ループ用 ;diverr 1 ;割る数が0であった場合に1をセットして戻る ;-------------------- mul161632 の主ルーチン movf src2+0,W ;乗数を答え下位(ワーク)にコピーする movwf result+0 movf src2+1,W movwf result+1 clrf result+2 ;答用変数をクリアしておく clrf result+3 ;〃 movlw 10h ;10h=16 movwf calc_cn ;calc_cn に 16 を代入 mul161632_1 bcf 3,0 ;キャリフラグのクリア btfss result+0,0 ;最下位ビットが 0 なら goto mul161632_2 ; →足さない movf src1+0,w ;src1(下位) を w にコピー addwf result+2,1 ;答(下位)に加える btfsc 3,0 ;キャリフラグが 0 なら次の命令をスキップ incf result+3,1 ;繰り上がりの処理 movf src1+1,0 ;src1(上位) を w にコピー addwf result+3,1 ;答に加える(キャリフラグが次のシフトに必要) mul161632_2 rrf result+3,1 ;答を1ビット右に送る(被乗数を倍する) rrf result+2,1 ; 〜 rrf result+1,1 ; 〜 rrf result+0,1 ; 〜 下位 decfsz calc_cn,1 ;ビット数分の繰り返し goto mul161632_1 return ;--------------------------------------------------------------------- ;********************************************************************* ;********************************************************************* ;--------------------------------------------------------------------- div16 ;16ビットの割り算ルーチン ;参考 http://www.sikasenbey.or.jp/~enaga/pic/pic.html ;-------------------- div16 での使用変数 ;src1 2 ;割られる数 (終了時には0になって戻る) ;src2 2 ;割る数 (変化せず戻る) ;result 2 ;答え    (答えが返る) ;mod 2 ;余り    (余りが返る、内部ワークにも使用) ;calc_cn 1 ;内部ループ用 ;calc_cn2 1 ;内部ループ用 ;diverr 1 ;割る数が0であった場合に1をセットして戻る ;-------------------- 主ルーチン movlw D'16' movwf calc_cn movf src2+0,W ;割る数下位をワークにコピー movwf mod+0 movf src2+1,W ;割る数上位をワークにコピー movwf mod+1 clrf result+0 ;答え用変数のクリア clrf result+1 bcf STATUS,C di1601 rlf mod+0,F ;左シフトする rlf mod+1,F btfsc STATUS,C ;キャリフラグを見る goto di1602 ;割る数の上位ビット位置検索 decfsz calc_cn,F goto di1601 bsf flag,3 ;割る数が0である。エラーコードをセット clrf mod+0 ;ワーク用変数のクリア clrf mod+1 return ;戻る di1602 clrf mod+0 ;ワーク用変数のクリア clrf mod+1 movlw D'16' movwf calc_cn2 movf calc_cn,W subwf calc_cn2,F ;残り、実ループの回数 di1603 bcf STATUS,C ;キャリフラグを0に rlf src1+0,F rlf src1+1,F rlf mod+0,F rlf mod+1,F decfsz calc_cn,F ;割られる数を初期位置までシフト goto di1603 di1604 ;現位置での減算が可能かチェック movf src2+1,W subwf mod+1,W btfss STATUS,C goto di1606 movf mod+1,W subwf src2+1,W btfss STATUS,C goto di1605 movf src2+0,W subwf mod+0,W btfss STATUS,C goto di1606 di1605 movf src2+0,W subwf mod+0,F ;ワークから下位を引く btfss STATUS,C ;キャリフラグが 1(正)なら次をスキップ decf mod+1,F ;上位 -1 movf src2+1,W subwf mod+1,F ;ワークから上位を引く bsf STATUS,C ;キャリフラグを1に goto di1607 di1606 bcf STATUS,C ;キャリフラグを0に di1607 rlf result+0,F ;キャリフラグの内容を答えにシフト rlf result+1,F movf calc_cn2,F ;calc_cn2 が 0 か検査 btfsc STATUS,Z goto di1608 ;最下位まで処理したなら終了 decf calc_cn2,F ;ビット位置を1つ下げる(右へ) bcf STATUS,C ;キャリフラグを0に rlf src1+0,F ;ワークへ1ビット左シフト rlf src1+1,F rlf mod+0,F rlf mod+1,F goto di1604 di1608 bcf flag,3 ;正常終了 return ;--------------------------------------------------------------------- ;********************************************************************* ;--------------------------------------------------------------------- div24 ;24÷24ビット=24ビットの割り算ルーチン ;秋月 PA (PICアセンブラ) 用 ;src1+3 ÷ src1+3 = 結果 result+3 余り mod+3 ;演算後、式の左項(割られる数)は壊れる ;割る数が0(エラー)なら diverr に1を代入して戻る ;エラーの場合、引き数は変化しない ;正常終了の場合は diverr=0 で戻る ;24ビットで扱える数の最大は 16777216 (1677万7216) ;-------------------- div24 での使用変数 ;src1 ds 3 ;割られる数 (終了時には0になって戻る) ;src2 ds 3 ;割る数 (変化せず戻る) ;result ds 3 ;答え    (答えが返る) ;mod ds 3 ;余り    (余りが返る、内部ワークにも使用) ;calc_cn ds 1 ;内部ループ用 ;calc_cn2 ds 1 ;内部ループ用 ;diverr ds 1 ;割る数が0であった場合に1をセットして戻る ;-------------------- 主ルーチン movlw D'24' movwf calc_cn movf src2+0,W ;割る数をワークにコピー movwf mod+0 movf src2+1,W movwf mod+1 movf src2+2,W movwf mod+2 bcf STATUS,C clrf result+0 ;答えのクリア clrf result+1 clrf result+2 di2401 rlf mod+0,F ;左シフトする rlf mod+1,F rlf mod+2,F btfsc STATUS,C goto di2402 ;割る数の上位ビットが見付かったなら di3202 へ decfsz calc_cn,F goto di2401 bsf flag,3 ;割る数が0である、エラーコードをセット clrf mod+0 ;ワークのクリア(ワークには余りが残る) clrf mod+1 clrf mod+2 return ;戻る di2402 clrf mod+0 ;ワークのクリア(ワークには余りが残る) clrf mod+1 clrf mod+2 movlw D'24' movwf calc_cn2 movf calc_cn,W subwf calc_cn2,F ;残り、実ループの回数 di2403 bcf STATUS,C ;キャリフラグを0に rlf src1+0,F ;有効位置までシフトする rlf src1+1,F rlf src1+2,F rlf mod+0,F ;押し出されたビットをワークに rlf mod+1,F rlf mod+2,F decfsz calc_cn,F ;割られる数を初期位置までシフト goto di2403 di2404 movf src2+2,W subwf mod+2,W btfsc STATUS,Z goto di2406 btfsc STATUS,C goto di2410 ;btfss STATUS,C goto di2411 di2406 movf src2+1,0 subwf mod+1,0 btfsc STATUS,Z goto di2407 btfsc STATUS,C goto di2410 ;btfss STATUS,C goto di2411 di2407 movf src2+0,W subwf mod+0,W btfsc STATUS,Z goto di2410 btfss STATUS,C goto di2411 di2410 movf src2+0,W subwf mod+0,F ;ワークから下位を引く movlw 1 ;ワークには余りが残る btfss STATUS,C subwf mod+1,F btfss STATUS,C subwf mod+2,F movf src2+1,W subwf mod+1,F ;ワークから2位を引く btfss STATUS,C decf mod+2,F ;上位 -1 movf src2+2,W subwf mod+2,F ;ワークから上位を引く bsf STATUS,C ;キャリフラグを1に goto di2412 di2411 bcf STATUS,C ;キャリフラグを0に di2412 rlf result+0,F ;キャリフラグの内容を答えにシフトしてゆく rlf result+1,F rlf result+2,F movf calc_cn2,F ;calc_cn2 が 0 か検査 btfsc STATUS,Z goto di2413 ;最下位まで処理したなら終了 decf calc_cn2,F ;ビット位置を1つ下げる(右へ) bcf STATUS,C ;キャリフラグを0に rlf src1+0,F ;ワークへ1ビット左シフト rlf src1+1,F rlf src1+2,F rlf mod+0,F rlf mod+1,F rlf mod+2,F goto di2404 di2413 bcf flag,3 ;正常終了 return ;--------------------------------------------------------------------- ;*********************************************************************