Hello all,
I haven't been experimenting with microcontrollers very long (<1 year).
I have attached a snippet of code (assembly) for dividing a 16 bit number
by an 8 bit number. Details are in the comments.
I would appreciate it greatly if anyone, more experienced, would look/test for errors.
All comments (good and bad) welcome.
Thanks.
I haven't been experimenting with microcontrollers very long (<1 year).
I have attached a snippet of code (assembly) for dividing a 16 bit number
by an 8 bit number. Details are in the comments.
I would appreciate it greatly if anyone, more experienced, would look/test for errors.
All comments (good and bad) welcome.
Thanks.
Rich (BB code):
;**********************************************************************
;TEST FOR PIC16F690 *
;DIVISION ROUTINE (MULTIPLICATION OF INVERSE OF DIVISOR) *
; *
;16 BIT DIVIDEND (XXXXXXXX XXXXXXXX) *
;8 BIT INVERSE OF DIVISOR (1/DIVISOR)(.XXXXXXXX) *
; *
;RESULT IS 16 BITS TO THE LEFT OF DECIMAL POINT, 8 BITS TO RIGHT *
;OF THE DECIMAL POINT *
; *
;RESULT FORMAT XXXXXXXX XXXXXXXX .XXXXXXXX *
; HIGH BYTE LOW BYTE DECIMAL BYTE *
; *
;INPUTS: *
;DVDHI=HIGH BYTE OF DIVIDEND *
;DVDLO=LOW BYTE OF DIVIDEND *
;DVSR=1/DIVISOR *
; *
;OUTPUTS: *
;HIRSLT=HIGH BYTE OF RESULT *
;LORSLT=LOW BYTE OF RESULT *
;HIDEC=DECIMAL HIGH BYTE OF RESULT *
; *
;PRESERVES ORIGINAL VALUES OF DIVIDEND AND DIVISOR *
; *
; *
; *
;**********************************************************************
; *
; Filename: xxx.asm *
; Date: *
; File Version: *
; *
; Author: *
; Company: *
; *
; *
;**********************************************************************
; *
; Files Required: P16F690.INC *
; *
;**********************************************************************
; *
; Notes: *
; *
;**********************************************************************
list p=16f690 ; list directive to define processor
#include <P16F690.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _CPD_OFF & _BOR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _FCMEN_OFF & _IESO_OFF
; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
main
;GENERAL PURPOSE VARIABLE ADDRESSES
;*************DIVISION ROUTINE VARIABLES*************
CNTR1 EQU 0x34 ;GENERAL PURPOSE COUNTER
CNTR2 EQU 0x35 ;GENERAL PURPOSE COUNTER
DVDHI EQU 0x41 ;DIVIDEND HIGH BYTE XXXXXXXX xxxxxxxx
DVDLO EQU 0x42 ;DIVIDEND LOW BYTE xxxxxxxx XXXXXXXX
DVSR EQU 0x43 ;DIVISOR (1/DIVISOR) .XXXXXXXX
HIRSLT EQU 0x44 ;RESULT HIGH BYTE XXXXXXXX xxxxxxxx
LORSLT EQU 0x45 ;RESULT LOW BYTE xxxxxxxx XXXXXXXX
HIDEC EQU 0x46 ;RESULT DECIMAL PORTION xxxxxxxx xxxxxxxx.XXXXXXXX
HITEMP EQU 0x47 ;TEMP HIGH BYTE XXXXXXXX xxxxxxxx
LOTEMP EQU 0x48 ;TEMP LOW BYTE xxxxxxxx XXXXXXXX
DVRTMP EQU 0x49 ;TEMP DIVISOR .XXXXXXXX
HDECTMP EQU 0x50 ;TEMP DECIMAL PORTION xxxxxxxx xxxxxxxx.XXXX
;***************************************************
;****INITIALIZE DIVISION ROUTINE VARIABLES****
CLRF CNTR1 ;0000 0000 INITIALIZE CNTR1
CLRF CNTR2 ;0000 0000 INITIALIZE CNTR2
CLRF DVDHI ;0000 0000 INITIALIZE DVDHI
CLRF DVDLO ;0000 0000 INITIALIZE DVDLO
CLRF HIRSLT ;0000 0000 INITIALIZE HIRSLT
CLRF LORSLT ;0000 0000 INITIALIZE LORSLT
CLRF HITEMP ;0000 0000 INITIALIZE HITEMP
CLRF LOTEMP ;0000 0000 INITIALIZE LOTEMP
CLRF HIDEC ;0000 0000 INITIALIZE HIDEC
CLRF DVSR ;0000 0000 INITIALIZE DVSR
CLRF DVRTMP ;0000 0000 INITIALIZE DVRTEMP
CLRF HDECTMP ;0000 0000 INITIALIZE HDECTMP
;***************************************************
;***********DIVISION ROUTINE***********
;***ENTER DIVIDEND AND 1/DIVISOR BELOW HERE***
;***ENTER DIVIDEND AND 1/DIVISOR BELOW HERE***
MOVLW 0xFF ;DIVIDEND HIGH BYTE XXXX XXXX
MOVWF DVDHI ;DVDHI=XXXX XXXX
MOVLW 0xFF ;DIVIDEND LOW BYTE XXXX XXXX
MOVWF DVDLO ;DVDLO=XXXX XXXX
MOVLW 0x01 ;1/DIVISOR .XXXX XXXX
MOVWF DVSR ;DVSR=.XXXX XXXX
;***ENTER DIVIDEND AND 1/DIVISOR ABOVE HERE***
;***ENTER DIVIDEND AND 1/DIVISOR ABOVE HERE***
;*****BEGINNING OF DIVISION ROUTINE****
MOVF DVDHI,W ;DVDHI TO W
MOVWF HITEMP ;HITEMP=DVDHI
MOVF DVDLO,W ;DVDHI TO W
MOVWF LOTEMP ;LOTEMP=DVDLO
MOVF DVSR,W ;DVSR TO W
MOVWF DVRTMP ;DVRTMP=DVSR
MOVLW 0x00 ;0000 0000
MOVWF HDECTMP ;HDECTMP=0
MOVLW 0x08 ;0000 1000 (8)
MOVWF CNTR1 ;CNTR1=8
MOVLW 0x00 ;0000 0000
MOVWF CNTR2 ;CNTR2=0
;TEST BIT 7 OF DVRTMP
BCF STATUS,C
INCF CNTR2,F ;BIT TEST COUNTER
BTFSS DVRTMP,7 ;TEST BIT 7 OF DVRTEMP
GOTO DIVIDECNTR
GOTO DIVIDE1
;SHIFT AND ADD DIVIDEND
DIVIDE1
BCF STATUS,C
RRF HITEMP,F ;ROTATE RIGHT HITEMP
RRF LOTEMP,F ;ROTATE RIGHT LOTEMP
RRF HDECTMP,F ;ROTATE RIGHT HDECTMP
BCF STATUS,C
DECF CNTR2,F ;BIT TEST COUNTER -1
MOVF CNTR2,F ;TESTING COUNTER FOR =0
BTFSS STATUS,Z ;IF INCREMENTAL SHIFTS NOT =O
GOTO DIVIDE1 ;ROTATE AGAIN
MOVF HDECTMP,W ;HIDECTMP SAVED TO W
ADDWF HIDEC,F ;ADD HDECTMP TO HIDEC
BTFSS STATUS,C ;TEST FOR CARRY OF HIDEC
GOTO $+5 ;IF NO CARRY
MOVLW 0x01
ADDWF LORSLT,F ;IF HIDEC CARRIED ADD 1 TO LORSLT
BTFSC STATUS,C ;TEST FOR CARRY OF LORSLT
INCF HIRSLT,F ;IF LORSLT CARRIED ADD 1 TO HIRSLT
MOVF LOTEMP,W
ADDWF LORSLT,F ;ADD LOTEMP TO LORSLT
BTFSC STATUS,C ;TEST FOR CARRY OF LORSLT
INCF HIRSLT,F ;IF LORSLT CARRIED ADD 1 TO HIRSLT
MOVF HITEMP,W
ADDWF HIRSLT,F ;ADD HITEMP TO HIRSLT
CLRF CNTR2 ;CLEAR CNTR2
GOTO DIVIDECNTR ;SHIFT AND TEST DIVISOR AGAIN
;MANAGE COUNTERS, SHIFT DIVISOR, TEST DIVISOR BITS
DIVIDECNTR
BCF STATUS,C
BCF STATUS,Z
DECF CNTR1,F ;-1 TOTAL SHIFTS COUNTER
MOVF CNTR1,F ;TESTING COUNTER FOR =0
BTFSC STATUS,Z ;CHECK FOR 8 TOTAL SHIFTS
GOTO $+6 ;IF ALL BITS OF DIVISOR HAVE BEEN TESTED THEN EXIT
RLF DVRTMP,F ;ROTATE LEFT FOR TESTING NEXT BIT
INCF CNTR2,F ;+1 BIT TEST COUNTER
BTFSS DVRTMP,7 ;TEST BIT 7 OF DVRTEMP
GOTO $-7 ;IF BIT 7 IS 0 SHIFT AND TEST AGAIN
GOTO DIVIDE1 ;IF BIT 7 IS 1 SHIFT AND ADD DIVIDEND
NOP ;TEMPORARY EXIT POINT
GOTO $-1 ;ENDLESS LOOP
;*******END OF DIVISION ROUTINE*******
;********************************
BOTTOM
ORG 0x2100 ; data EEPROM location
DE 1,2,3,4 ; define first four EEPROM locations as 1, 2, 3, and 4
END ; directive 'end of program'