山本ワールド
除算(引き戻し法) 16bit/8bit=16bit アセンブラプログラム
概要
PIC18には割り算命令はありません。引き戻し法で除算プログラム(16bit/8bit=16bit)を作成しました。
筆算と同じ方法で被除数の上位から除数を引き結果がマイナスになれば除数を足してもとに戻します。引き算結果がプラスの場合はビットに1を立てます。
以上の処理をビットをずらしながら16回実行すると商と余りを求めることができます。
計算時間は非常に時間がかかり、大雑把な計算では最悪21命令サイクル*16回=336命令サイクル(クロック64MHzで21μs)かかります。1秒間に約47000回程度しか計算できないことになります。
8086のDIV命令でAX/reg8 -> AH:ALの場合、80~90クロック要します。10MHzの場合最悪9μsとなります。
H8 3048のDIVXU命令の場合14クロックです。(16MHz 0.875μs) 例えば12345/67を2進数での筆算による計算例を以下に示します。
データの並び順はリトルエンディアンです。
答えを表示するプログラムは記載していないのでエミュレーター上で実行してください。以下に実行例を示します。
使用メモリは以下のとおりです。
プログラムサイズ 77byte
アクセスバンク 9byte(スタック4byte)
筆算と同じ方法で被除数の上位から除数を引き結果がマイナスになれば除数を足してもとに戻します。引き算結果がプラスの場合はビットに1を立てます。
以上の処理をビットをずらしながら16回実行すると商と余りを求めることができます。
計算時間は非常に時間がかかり、大雑把な計算では最悪21命令サイクル*16回=336命令サイクル(クロック64MHzで21μs)かかります。1秒間に約47000回程度しか計算できないことになります。
8086のDIV命令でAX/reg8 -> AH:ALの場合、80~90クロック要します。10MHzの場合最悪9μsとなります。
H8 3048のDIVXU命令の場合14クロックです。(16MHz 0.875μs) 例えば12345/67を2進数での筆算による計算例を以下に示します。
0000 0000 1011 1000 -->商 184 --------------------- 除数 67 --> 0100 0011 ) 0011 0000 0011 1001 <--被除数 12345 010 0001 1 --------------- 0 1110 1011 0 1000 0110 ------------ 0110 0101 0100 0011 ------------ 0010 0010 1 0010 0001 1 --------------- 0000 0001 0001 -->余 17被除数はDIV_A16、除数はDIVL_Bに格納してからdiv16_8をコールします。商はDIV_A16,余りはDIV_M16に格納されます。
データの並び順はリトルエンディアンです。
答えを表示するプログラムは記載していないのでエミュレーター上で実行してください。以下に実行例を示します。
使用メモリは以下のとおりです。
プログラムサイズ 77byte
アクセスバンク 9byte(スタック4byte)
プログラムの説明
ソースファイル
以下のファイルで構成されているdiv16_8.asm ・・・ メインプログラム
ソースファイルのダウンロード div16_8.zip
; 除算(引き戻し法) 16bit/8bit=16bit Version 1.00
; 2017/01/08
; 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
STACK_MAX EQU d'4'
bank0 UDATA_ACS
DIV_A16 RES 2 ; 除算の被除数を指定 サブルーチンコール後答えが返る
DIV_M16 RES 2 ; サブルーチンコール後余りが返る
DIV_B RES 1 ; 除算の除数を指定
stack1 RES STACK_MAX ; スタックエリア
CODE
ORG 0
goto start ; リセット時
DIV1 EQU d'12345' ; 被除数
DIV2 EQU d'67' ; 除数
start
BANKSEL ANSELC
lfsr 2,stack1+(STACK_MAX-1) ; スタックの設定
movlw LOW DIV1
movwf DIV_A16
movlw HIGH DIV1
movwf DIV_A16+1
movlw DIV2
movwf DIV_B
call div16_8
bra $
; 除算 DIV_A16 / DIV_B 商はDIV_A16 余りはDIV_M16に返される
; 2017/01/08 FSR2で示されるスタックを1byte使用
div16_8 ; 16bit/8bit=16bit
clrf DIV_M16
clrf DIV_M16+1
movlw d'16'
div16_8_loop
movwf POSTDEC2
bcf STATUS,C
rlcf DIV_A16
rlcf DIV_A16+1
rlcf DIV_M16
rlcf DIV_M16+1
movf DIV_B,W
subwf DIV_M16
clrf WREG
subwfb DIV_M16+1
bnc div16_8_non_sub
bsf DIV_A16,0
bra div16_8_shift
div16_8_non_sub
movf DIV_B,W
addwf DIV_M16
btfsc STATUS,C
incf DIV_M16+1
div16_8_shift
movf PREINC2,W
decfsz WREG
bra div16_8_loop
return
END
Copyright (C) 2012 山本ワールド All Rights Reserved.