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
All projects, plans, schematic diagrams, programs and program subroutines at this site are provided on an "as is" basis, without any warranty, either expressed or implied. These materials are provided for educational purposes only, and Sirius microSystems does not assume any liability for damages, either incidental or consequential, arising out of the application, use, or misuse of any of the materials contained herein. Sirius microSystems further reserves the right to make any changes to these materials in order to improve their function, design, or reliability.
© 2002 Sirius microSystems