山本ワールド
乗算による除算 16bit/10=16bit アセンブラプログラム
概要
PIC18には割り算命令はありません。引き戻し法で除算すると非常に時間が掛かります。
定数であれば乗算により高速に計算できます。
ここでは16bitを10で割ってみます。除算は逆数を乗ずることで求められます。例えば65536/10=6554倍にして16bit右へずらせば近い商が計算できます。
若干の誤差が生じますので仮の商に除数を乗じて非除数との差が10以上であれば商に1加算し、先ほどの差に10を加算します。
35命令サイクル+30命令サイクル(16bit*16bit)+14命令サイクル(16bit*8bit)=79命令サイクル(64MHz 4.94μs)となります。
汎用の16bit/8bitで計算する場合、最悪336命令サイクルですので、4.2倍ほど高速となります。1秒間に約202000回の除算ができることになります。
被除数はDIV_A16、除数は10固定です。商はMUL_A16,余りはDIV_A16に格納されます。
データの並び順はリトルエンディアンです。
答えを表示するプログラムは記載していないのでエミュレーター上で実行してください。
12345÷10の実行例を示します。商の1234と余りの5が得られています。

使用メモリは以下のとおりです。
プログラムサイズ 175byte
アクセスバンク 17byte
定数であれば乗算により高速に計算できます。
ここでは16bitを10で割ってみます。除算は逆数を乗ずることで求められます。例えば65536/10=6554倍にして16bit右へずらせば近い商が計算できます。
若干の誤差が生じますので仮の商に除数を乗じて非除数との差が10以上であれば商に1加算し、先ほどの差に10を加算します。
35命令サイクル+30命令サイクル(16bit*16bit)+14命令サイクル(16bit*8bit)=79命令サイクル(64MHz 4.94μs)となります。
汎用の16bit/8bitで計算する場合、最悪336命令サイクルですので、4.2倍ほど高速となります。1秒間に約202000回の除算ができることになります。
被除数はDIV_A16、除数は10固定です。商はMUL_A16,余りはDIV_A16に格納されます。
データの並び順はリトルエンディアンです。
答えを表示するプログラムは記載していないのでエミュレーター上で実行してください。
12345÷10の実行例を示します。商の1234と余りの5が得られています。

使用メモリは以下のとおりです。
プログラムサイズ 175byte
アクセスバンク 17byte
プログラムの説明
ソースファイル
以下のファイルで構成されているdiv16_10da.asm ・・・ メインプログラム
ソースファイルのダウンロード div16_10da.zip
; 乗算による除算 16bit/10=16bit Version 1.00
; 2017/01/09
; PIC18
; MPLAB X IDE v3.45 Microchip MPASM(v5.70)
#INCLUDE <p18f46k22.inc>
; 水晶発振(16MHz) クロック分周無 PLL有効(*4) プライマリクロック有効 ウォッチドッグタイマ無効 低電圧プログラム書き込みモード無効
CONFIG FOSC = HSHP,PLLCFG=ON,PRICLKEN=ON,WDTEN=OFF,LVP=OFF
bank0 UDATA_ACS
DIV_A16 RES 2 ; 除算の被除数を指定 サブルーチンコール後答えが返る
DIV_M16 RES 2 ; サブルーチンコール後余りが返る
DIV_B RES 1 ; 除算の除数を指定
DIV_A16T RES 2 ;
DIV_A16T2 RES 2 ;
MUL16A RES 2 ; 乗算引数1
MUL8B ; 乗算引数2
MUL16B RES 2 ; 乗算引数2
MUL16DTC ; 乗算結果
MUL32DTC RES 4 ; 乗算結果
CODE
ORG 0
goto start ; リセット時
DIV1 EQU d'12345' ; 被除数
DIV2 EQU d'10' ; 除数
start
movlw LOW DIV1
movwf DIV_A16
movlw HIGH DIV1
movwf DIV_A16+1
call div16_d10
bra $
; 除算 DIV_A16 / 10 MUL16A:商 DIV_A16:余
; 2017/01/09
div16_d10 ; 16bit/10
movff DIV_A16,MUL16A
movff DIV_A16+1,MUL16A+1
movlw LOW ((d'65536')/(DIV2))
movwf MUL16B
movlw HIGH ((d'65536')/(DIV2))
movwf MUL16B+1
call mul16_16
movff MUL32DTC+2,MUL16A
movff MUL32DTC+3,MUL16A+1
movlw DIV2
movwf MUL8B
call mul16_8
movf MUL16DTC,w
subwf DIV_A16
movf MUL16DTC+1
subwfb DIV_A16+1
movf DIV_A16,w
cpfsgt MUL8B ; 10>wregのとき次の命令をスキップ
bra div16_d10_mod
bra div16_d10_exit
div16_d10_mod
incf MUL16A
clrf WREG
addwfc MUL16A+1
movlw DIV2
subwf DIV_A16
clrf WREG
subwfb DIV_A16+1
div16_d10_exit
return
; 乗算サブルーチン(16bit * 8bit -> 24bit)
; MUL16DTC=MUL16A*MUL8B
; 2017/01/08
mul16_8
; 下位8bit*8bit
movf MUL16A,W
mulwf MUL8B
movff PRODL,MUL16DTC
movff PRODH,MUL16DTC+1
; 上位8bit*8bit
movf MUL16A+1,W
mulwf MUL8B
movf PRODL,W
addwf MUL16DTC+1
btfsc STATUS,C
incf PRODH
movf PRODH,w
movwf MUL16DTC+2
return
; 乗算サブルーチン(16bit * 16bit -> 32bit)
; MUL32DTC=MUL16A*MUL16B
; 2017/01/09
mul16_16
; 下位8bit*8bit
movf MUL16A,W
mulwf MUL16B
movff PRODL,MUL32DTC
movff PRODH,MUL32DTC+1
; 上位8bit*8bit
movf MUL16A+1,W
mulwf MUL16B
movf PRODL,W
addwf MUL32DTC+1
btfsc STATUS,C
incf PRODH
movf PRODH,w
movwf MUL32DTC+2
; 下位8bit*8bitH
movf MUL16A,w
mulwf MUL16B+1
movf PRODL,w
addwf MUL32DTC+1
movf PRODH,w
addwfc MUL32DTC+2
; 上位8bit*8bitH
movf MUL16A+1,w
mulwf MUL16B+1
movf PRODL,w
addwf MUL32DTC+2
btfsc STATUS,C
incf PRODH
movf PRODH,w
movwf MUL32DTC+3
return
END
Copyright (C) 2012 山本ワールド All Rights Reserved.