Hi Stew
No, I've never used any PICs other than the 16F's. Many years ago I started teacvhing myself C, and I liked that language compared to the Turbobasic I'd used previously. But, now I like the assembler coding as I feel close to the action and, so far, these PICs can do more than I need.
Below is the code I use for multiplying. As it says, it handles two 16-bit values (signed or unsigned) and gives a 32-bit result.
I'll sort out the division and subtraction code in a while.
I initially obtained these routines at
http://www.piclist.com/techref/microchip/math and they ask to link to their site rather than copy. Trouble is, my routines have been modified from the original and I know my code works fine.
One other point to bear in mind. I use PICs that have the extended mid-trange instruction set. I cannot remeber if any of the extended instructions are used in these routines.
Regards
Mike
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Combined sub-routines to multiply 2 16-bit numbers to a 32-bit product.
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; registers used:
; product(4 bytes)
; m_plier(2 bytes)
; m_plicand(2 bytes)
; bitcount
; flag register:
; misc_flags bit: MULT_NEG ; setting this bit signifies m_plier was negative
;*********************************************************************************************
; Call subroutine starting here when m_plier is signed.
;*********************************************************************************************
multiply_signed_16to32
; Test sign of m_plier and reverse if negative.
BANKSEL m_plier
btfss m_plier+1, 7 ; is sign bit set?
goto multiply_16to32
comf m_plier, F ; sign of m_plier is -ve so make 2's compl
comf m_plier+1, F
incfsz m_plier, F ; If result of incr is not zero, then no need to adjust high byte
goto _set_flag
incf m_plier+1, F
_set_flag
BANKSEL misc_flags
bsf misc_flags, MULT_NEG ; m_plier negative so set flag
goto _clear_product
;*************************************************************************************************
; Call subroutine starting here when m_plier is unsigned.
;*************************************************************************************************
multiply_16to32
BANKSEL misc_flags
bcf misc_flags, MULT_NEG ; ensure flag shows result is +ve
_clear_product
BANKSEL product
CLRF product
CLRF product+1
CLRF product+2
CLRF product+3
BANKSEL bitcount
MOVLW d'16' ; 16 bit operations
MOVWF bitcount
_mult32_1
BANKSEL m_plier
RRF m_plier+1, F ; shift both bytes of multiplier down
RRF m_plier, F
BTFSS STATUS, C ; If carry is set, then least sig bit was 1 so add current value of multiplicand to product
GOTO _mult32_2 ; carry not set so skip addition
BANKSEL product+4
CLRF product+4
BANKSEL m_plicand ; start 16-bit addition
MOVF m_plicand+1, W
BANKSEL product
ADDWF product+3, F
BTFSC STATUS, C ; check if a carry to byte-4 is needed
INCF product+4, F
BANKSEL m_plicand
MOVF m_plicand, W
BANKSEL product
ADDWF product+2, F
BTFSC STATUS, C ; check if a carry to byte-1 is needed
INCFSZ product+3, F
GOTO $+2
INCF product+4, F
_mult32_2
BCF STATUS, C ; ensure carry bit is clear, then rotate m_plicand bytes upwards
BANKSEL product ; rotate low byte first so any carry is accomplished automatically.
RRF product+4, F
RRF product+3, F
RRF product+2, F
RRF product+1, F
RRF product, F
BANKSEL bitcount
DECFSZ bitcount, F
GOTO _mult32_1
; Lastly test to see if result must be converted to 2's complement
BANKSEL misc_flags
btfss misc_flags, MULT_NEG
return
BANKSEL product
comf product, F
comf product+1, F
comf product+2, F
comf product+3, F
incfsz product, F
return
incfsz product+1, F
return
incfsz product+2, F
return
incf product+3, F
return