Sirius microSystems logo   Address and telephone numbers

Multiplication and Division Subroutines

The multiplication subroutine multiplies two 8-bit numbers to produce a 16-bit result. The division subroutine divides one 8-bit number by another to produce an 8-bit result. Both subroutines are written to use variable instruction cycle times based on the starting numbers used.

For division, and for fastest multiplication, the number stored in the Num2 variable must be larger than the number stored in Num1. The subroutine includes a sort routine to arrange the numbers in this way.

;MULTDIV8.INC	V2.01	Last modified on December 19, 2001

;Description

;       This subroutine library file contains three subroutines: NumSort, to
;	sort the two eight-bit numbers in Num1 and Num2 so that Num2 is the
;	larger one; Mult8x8, to multiply the two eight-bit numbers in Num1
;	and Num2 into a 16-bit result stored in HighByte and LowByte; and
;	Div8x8, to divie the eight-bit number in Num2 by another in Num1 to
;	produce an eight-bit result stored in Quotient. Both the division
;	and multiplication algorithms are variable cycle length and require
;	that the smaller number is stored in Num1 and the larger number in
;	Num2.

;Requirements

;       A number of registers are required to hold the starting numbers, 
;	intermediate results and answers. Both the multiplication and 
;	division subroutines utitlize the same resgister naming for more
;	efficient code generation. All of the registers listed below must
;	be defined with equates in the calling program as shown below.
;	Copy the equates, below, into your calling program, but use
;	free register addresses.

;Register Equates

;Num1		equ	0Ch		;The smaller of two numbers
;Num2		equ	0Dh		;The larger of two numbers
;
;LowByte	equ	0Eh		;Result/intermediate register
;HighByte	equ	0Fh		;Result/intermediate register
;ShiftCounter	equ	10h		;Intermediate register
;
;Quotient	equ	11h		;Result register
			

NumSort		;Sorts the eight-bit numbers in Num1 and Num2 such that the
		;number in Num2 is larger.

		movf	Num1,W		;Load W with Num1
		subwf	Num2,W		;and compare with Num2
		btfsc	STATUS,C	;C=1 if Num2 > Num1
		return			;return if Num2 > Num1
		movf	Num1,W		;Otherwise, store Num1 in
		movwf	LowByte		;LowByte
		movf	Num2,W		;Copy Num2 into Num1
		movwf	Num1
		movf	LowByte,W	;Copy LowByte into Num2
		movwf	Num2
		return			;Done


Div8x8		;Divides the eight-bit number in Num2 by the eight-bit number
		;in Num1 to produce the answer in Quotient.

		movf	Num2,W		;Copy Num2 into HighByte
		movwf	HighByte	
		movf	Num1,W		;Copy Num1 into LowByte
		movwf	LowByte	
		clrf	Quotient	;Clear Quotient register

DivInit		clrf	ShiftCounter	;Set Shiftcounter register
		incf	ShiftCounter,F	;to 1
		
DivPrep		movf	Num2,F		;Check if done by checking
		btfsc	STATUS,Z	;if Num2 =  0
		return			;return if done
		bcf	STATUS,C	;Clear C
		rlf	Num2,F		;Rotate larger number into C
		btfsc	STATUS,C	;Check C for a 0
		goto	DivAcc		;If C=1, start division loop
		rlf	Num1,F		;If C=0, rotate smaller number
		btfss	STATUS,C	;Check Num1 for Carry
		goto	DivPrep		;Rotate Num2 until MSB=1
		return			;If Num1 > Num2 return

DivAcc		movf	LowByte,W	;Copy Num1 from LowByte back
		movwf	Num2		;to Num2
		
DivLoop		bcf	STATUS,C	;Clear C before multiplying
		rlf	Num1,F		;Multiply Num1 by 2 and check
		btfsc	STATUS,C	;C for equality with Num2
		goto	DivReset	;If MSDs are equal, accumulate
		rlf	ShiftCounter,F	;If not, multiply quotient and
		rlf	Num2,F		;multiply intermediate result
		goto	DivLoop		;Repeat until Num1 reaches 
					;same factor of 2 as Num2

DivReset	movf	ShiftCounter,W	;Add ShiftCounter to 
		addwf	Quotient,F	;Quotient register
		movf	Num2,W		;Subtract intermediate result
		subwf	HighByte,W	;from number in HighByte
		btfss	STATUS,C	;Check C for negative result
		goto	DivSub		;If negative, correct quotient
		movwf	Num2		;Copy result to Num2 and
		movwf	HighByte	;HighByte
		movf	LowByte,W	;Copy original Num1 back
		movwf	Num1		;to Num1
		subwf	Num2,W		;Compare Num1 to Num2
		btfsc	STATUS,C	;C=0 if Num1 > Num2
		goto	DivInit		;If Num1 < Num2 continue
		return			;otherwise finish

DivSub		decf	Quotient,F	;Subtract 1 from quotient
		return			;and finish


Mult8X8         ;Multiplies the eight-bit numbers Num1 and Num2 together to
		;form a sixteen-bit result stored in HighByte and LowByte.

		clrf	HighByte	;Clear high and low result registers
		clrf	LowByte        
		clrf	ShiftCounter	;Clear shift counter register
		bcf	STATUS,C	;Clear Carry before multiplying

MultLoop 	movf	Num1,F		;Move Num1 to itself and
		btfsc	STATUS,Z	;check the Z flag for a 0
		return			;Return if done
		movf	Num2,W		;Load W with Num2
		rrf	Num1,F		;Rotate LSB of Num1 into Carry and
		btfss	STATUS,C	;check Carry for 1
		goto	MultShift	;If Carry clear, bypass addition
		addwf	LowByte,F	;If set, add Num2 to Lowbyte
		btfsc	STATUS,C	;Check Carry after add and
		incf	HighByte,F	;increment HighByte if necessary
		movf	ShiftCounter,W	;Add ShiftCounter value to 
		addwf	HighByte,F	;HighByte
MultShift	bcf	STATUS,C	;Clear Carry before
		rlf	Num2,F		;rotating Num2 and
		rlf	ShiftCounter,F	;ShiftCounter
		goto	MultLoop	;Repeat until done   


© 2002 Sirius microSystems