DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦f3d66126c⟧ TextFile

    Length: 4736 (0x1280)
    Types: TextFile
    Names: »MPDMUL.MAC«

Derivation

└─⟦01b5c9619⟧ Bits:30005906 Microsoft Multiplan v1.05 og HELP
    └─ ⟦this⟧ »MPDMUL.MAC« 

TextFile

;
;
;	Title		Multiple-Precision Decimal Multiplication
;	Name:		MPDMUL
;
;
;	Purpose:	Multiply 2 arrays of BCD bytes
;			Multiplicand = multiplicand * multiplier
;
;	Entry:		Register pair HL = Multiplicand base address
;			Register pair DE = Multiplier base address
;			Register B = Lenght of arrays in bytes
;
;			  The arrays are unsigned BCD numbers with a
;			  maximum lenght of 255 bytes, ARRAYÆ0Å is  the
;			  least significant byte, and ARRAYÆLENGHT-1Å
;			  the most significant byte.
;
;	Exit:		Multiplicand := multiplicand * multiplier
;
;	Registers used:	AF,BC,DE,HL
;
;	Time:		Assuming the average digit value of multiplicand
;			is 5, the time is approximately
;			  (694 * lenght ^2) + (1555 * lenght) + 272 cycles
;
;	Size:		Program 167 bytes
;			Data    520 bytes
;
;
;
MPDMUL:
	;Initilize counters and pointers
	ld	a,b		;Test lenght of operands
	or	a
	ret	z		;Exit if lenght is 0
	ld	(len),a		;Save langht
	ld	(lpcnt),a	;Loop counter = lenght in bytes
	ld	(mcadr),hl	;Save multiplicand address
	ld	(mpadr),de	;Save multiplier address
	
	;Save multiplicand in temporary buffer (mcand)
	ld	de,mcand	;DE points to temporary multiplicand
	ld	(nbyte),de
				;HL points to multiplicand
	ld	c,b		;BC = lenght
	ld	b,0
	ldir			;Move multiplicand to buffer
	;Clear partial product, consisting of upper bytes
	;  starting at prod and lower bytes replacing
	;  multiplicand
	ld	hl,(mcadr)
	ld	a,(len)
	call	zerobuf		;Zero multiplicand

	;Zero product
	ld	hl,prod
	call	zerobuf		;Zero product array

	;
	;Loop through all bytes of multiplicand
loop:
	ld	a,1
	ld	(dcnt),a	;Start with lower digit

	;Loop through 2 digits per byte
	;  during lower digit DCNT = 1
	;  during upper digit DCNT = 1
dloop:
	sub	a		;A = 0
	ld	(ovrflw),a	;Clear overflow byte
	ld	a,(dcnt)
	or	a		;Test for lower digit (z=0)
	ld	hl,(nbyte)	;Get next byte
	ld	a,(hl)
	jr	nz,dloop1	;Shift upper digit right 4 bits
	rrca
	rrca
	rrca
	rrca
dloop1:
	and	0fh		;Keep only current digit
	jr	z,sdigit	;Branch if digit is zero
	ld	c,a		;C = digit

	;Add multiplier to product ndigits times
addlp:
	ld	a,(mpadr)	;HL = multiplier address
	ld	de,prod		;DE = product address
	ld	a,(len)
	ld	b,a		;B = lenght
	or	a		;Clear carry initialy

inner:
	ld	a,(de)		;Get next byte of product
	adc	a,(hl)		;Add next byte of multiplier
	daa			;Decimal adjust
	ld	(de),a		;Store sum in product
	inc	hl
	inc	de
	djnz	inner		;Continue until all bytes added
	jr	nc,decnd	;Jump if no overflow from addition
	ld	hl,ovrflw	;Else increment overflow byte
	inc	hl
decnd:
	dec	c
	jr	nz,addlp	;Continue until digit = 0

	;Store last significant digit of product
	;  as next digit of multiplicand
sdigit:
	ld	a,(prod)	;Get low byte of product
	and	0fh
	ld	b,a		;Save in B
	ld	a,(dcnt)
	or	a		;Test for lower digit (z=0)
	ld	a,b		;A = next digit
	jr	nz,sd1		;Else move digit to high bits
	rrca
	rrca
	rrca
	rrca
ds1:
	ld	hl,(mcadr)	;Place next digit in multiplicand
	or	(hl)
	ld	(hl),a

	;Shift product right 1 digit (4 bits)
	ld	a,(len)
	ld	b,a		;B = lengh
	ld	e,a
	ld	d,0
	ld	hl,prod
	add	hl,de		;HL points beyond end of prod
	ld	a,(ovrflw)	;A = overflow byte

shftlp:
	dec	hl		;Decrement, poit to next byte
	rrd			;Rotate byte of product right 1 digit
	jdnz	shftlp		;Continue until done

	;Check if done with both digits of this byte
	ld	hl,dcnt		;Are we on lower digit ?
	dec	(hl)
	jr	z,dloop		;Yes, do upper digit of same byte

	;Increment to next byte and see if done
	ld	hl,(nbyte)	;Increment to next multiplicand byte
	inc	hl
	ld	(nbyte),hl
	ld	hl,(mcadr)	;Increment to next result byte
	inc	hl
	ld	(mcadr),hl
	ld	hl,lpcnt	;Decrement loop counter
	dec	(hl)
	jr	nz,loop

exit:	ret

	;--------------------------------------------------
	; Routine: zerobuf
	; Purpose: Zero a buffer
	; Entry: HL points to first byte of buffer
	;	 len = lenght of buffer
	; Exit: Buffer zeroed
	; Registers used: AF,BC,DE,HL
	;--------------------------------------------------
zerobuf:
	ld	(hl),0		;Zero first byte
	ld	a,(len)
	dec	a
	ret	z		;Return if only one byte
	ld	d,h
	ld	e,l
	inc	de		;DE = seconnd byte
	ld	c,a		;BC = lenght of array
	ld	b,0
	ldir			;Clear rest of buffer by
	ret			;  propagating zeros from one
				;  byte to the next

	;DATA
len:	ds	1		;Lenght of arrays
dcnt:	ds	1		;Digit counter for bytes
lpcnt:	ds	1		;Loop counter
ovrflw:	ds	1		;Overflow byte
mcadr:	ds	2		;Next byte to store into
mpadr:	ds	2		;Address of multiplier
nbyte:	ds	2		;Next digit of multiplicand
prod:	ds	255		;Product buffer
mcand:	ds	255		;Multiplicand buffer

«eof»