除算(引き戻し法) 24bit/8bit=24bit アセンブラプログラム

icon 項目のみ表示/展開表示の切り替え

概要

PIC18には割り算命令はありません。引き戻し法で除算プログラム(24bit/8bit=24bit)を作成しました。
筆算と同じ方法で被除数の上位から除数を引き結果がマイナスになれば除数を足してもとに戻します。引き算結果がプラスの場合はビットに1を立てます。
以上の処理をビットをずらしながら16回実行すると商と余りを求めることができます。
計算時間は非常に時間がかかり、大雑把な計算では最悪26命令サイクル*24回=624命令サイクル(クロック64MHzで39μs)かかります。1秒間に約25000回程度しか計算できないことになります。
8086のDIV命令でDX:AX / reg16 -> DX:AXの場合、144~162クロック要します。10MHzの場合最悪16.2μsとなります。
H8 3048のDIVXU命令の場合22クロックです。(16MHz 1.375μs) 被除数はDIV_A24、除数はDIVL_Bに格納してからdiv24_8をコールします。商はDIV_A24,余りはDIV_M24に格納されます。
データの並び順はリトルエンディアンです。
答えを表示するプログラムは記載していないのでエミュレーター上で実行してください。以下に8338503/255=32700 余り 3の実行例を示します。

使用メモリは以下のとおりです。
プログラムサイズ 93byte
アクセスバンク 11byte(スタック4byte)

プログラムの説明

ソースファイル

以下のファイルで構成されている
div24_8.asm ・・・ メインプログラム

ソースファイルのダウンロード div24_8.zip

; 除算(引き戻し法) 24bit/8bit=24bit  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_A24     RES 3   ; 除算の被除数を指定 サブルーチンコール後答えが返る
DIV_M24     RES 3   ; サブルーチンコール後余りが返る
DIV_B       RES 1   ; 除算の除数を指定
   
stack1      RES     STACK_MAX ; スタックエリア


        CODE
        ORG 0
        goto   start    ;   リセット時


DIV1    EQU d'8338503'
DIV2    EQU d'255'
        
start
        BANKSEL ANSELC
        lfsr    2,stack1+(STACK_MAX-1)  ;   スタックの設定
        movlw   LOW DIV1
        movwf   DIV_A24
        movlw   HIGH DIV1
        movwf   DIV_A24+1
        movlw   UPPER DIV1
        movwf   DIV_A24+2

        movlw   DIV2
        movwf   DIV_B
        call    div24_8
        bra    $

;       除算    DIV_A24 / DIV_B  商はDIV_A24   余りはDIV_M24に返される
;       2017/01/08 FSR2で示されるスタックを1byte使用
div24_8      ;   24bit/8bit=24bit
        clrf    DIV_M24
        clrf    DIV_M24+1
        clrf    DIV_M24+2
        movlw   d'24'
div24_8_loop
        movwf   POSTDEC2
        bcf     STATUS,C
        rlcf    DIV_A24
        rlcf    DIV_A24+1
        rlcf    DIV_A24+2
        rlcf    DIV_M24
        rlcf    DIV_M24+1
        rlcf    DIV_M24+2

        movf    DIV_B,W
        subwf   DIV_M24   ; DIV_M24 < DIV_B -> C=0
        clrf    WREG
        subwfb  DIV_M24+1       
        subwfb  DIV_M24+2
        btfss   STATUS,C
        bra     div24_8_non_sub
        bsf     DIV_A24,0
        bra     div24_8_shift
div24_8_non_sub
        movf    DIV_B,W
        addwf   DIV_M24
        clrf    WREG
        addwfc  DIV_M24+1,f
        addwfc  DIV_M24+2,f
div24_8_shift
        movf    PREINC2,W
        decfsz  WREG
        bra     div24_8_loop
        return

        END