;MULDIV/ASM - 16 x 8 multiplication & division SUBTTL '<16 X 8 multiply/divide>' PAGE OFF *MOD ; ; Multiply HL by A - SVC 91 ; HL => multiplicand ; A => multiplier ; HLA <= 24-bit result ; DE destroyed ; @MUL16 PUSH BC ;Save reg BC EX DE,HL ;Multiplicand to DE LD C,A ; & multiplier to C LD HL,0 ;Init value to zero LD A,L ; in regs HLA LD B,8 ;Init for 8-bit mult $?1 ADD HL,HL ;Shift to next place RLA ;Use A for bits 16-23 RLC C ;Multiply this bit? JR NC,$?2 ;Go if not ADD HL,DE ;Else add multiplicand ADC A,0 ; & any overflow to 16 $?2 DJNZ $?1 ;Loop for 8 bits LD C,A ;Tempy save LD A,L ;Xfer low-order to A LD L,H ;Xfer mid-order to L LD H,C ;Xfer hi-order to H POP BC RET ; ; Divide HL by A - SVC 94 ; HL => dividend ; A => divisor ; HL <= resulting quotient ; A <= remainder ; *MOD @DIV16 PUSH DE ;Save this reg pair LD D,A ;Xfer divisor to D LD E,16 ;Init for 16-bits XOR A $?1 ADD HL,HL ;Rotate dividend RLA ; & subtract divisor if JR C,$?2 ; carry into bit-16 CP D ;Compare divisor JR C,$?3 ;Go if no subtract $?2 SUB D ; else subtract divisor INC L ;Set lo-order $?3 DEC E ;Count down one bit JR NZ,$?1 ;Loop for 16-bits POP DE RET ; ; @HEXDEC - SVC 97 ; Routine to convert 16-bit hexadecimal to decimal ; HL => value ; DE => buffer pointer of 5-character buffer ; HL <= destroyed (always set to zero) ; DE <= Buffer+5 ; BC <= destroyed ; Z <= set ; *MOD @HEXDEC LD B,5 ;Length max @HEXD LD A,' ' ;Load blank HEXDEC1 LD (DE),A ;To string INC DE ;Bump pointer DJNZ HEXDEC1 ;Go for length PUSH DE ;Save end +1 DEC DE ;Adjust back HEXDEC2 LD A,10 ;Base to convert to CALL @DIV16 ;HL+A = HL/A ADD A,'0' ;Add ASCII to result LD (DE),A ; to user string DEC DE ;Move back ; ; Check if done ; LD A,H ;Get subtotal remainder OR L ;Done? JR NZ,HEXDEC2 ;Go till completed POP DE ;Restore end+1 RET ;Return Z ;