|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 4736 (0x1280) Types: TextFile Names: »MPDMUL.MAC«
└─⟦01b5c9619⟧ Bits:30005906 Microsoft Multiplan v1.05 og HELP └─ ⟦this⟧ »MPDMUL.MAC«
; ; ; 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»