;---------------------------------------------------------------------- ; [PASLIB] DIV.MAC: Signed and unsigned integer division and modulus. ; @DIV, @MOD, @XDIVD, @UDV, @UMD ; Revisions: ; 11/14/81 Last MGL update. ; 12/16/82 Fixed SPR problem in @MOD (CHW) ; ; ;---------------------------------------------------------------------- PUBLIC @DIV ;SIGNED DIV PUBLIC @MOD ;SIGNED MOD PUBLIC @UDV ;UNSIGNED DIV PUBLIC @UMD ;UNSIGNED MOD PUBLIC @XDIVD ;USED BY WRITE INTEGER PUBLIC @GZF ;GET DIVIDE BY ZERO BOOLEAN FLAG ROUTINE EXTRN @HLT EXTRN @WRS ;FOR ERROR MESSAGE EXTRN @LFB ;FOR ERROR MESSAGE EXTRN OUTPUT ;FOR ERROR MESSAGE DSEG DIVZFLAG: DS 1 ;= 1 IF PREV DIVIDE WAS DIVIDE BY 0 modsign: ds 1 ;= FF if result to be negative (12/16/82) CSEG @GZF: POP H LDA DIVZFLAG ;PUT INTO CARRY RAR ;AND PUSH IT (CARRY IS LOW ORDER BIT OF PSW) PUSH PSW ;PUT FLAG ON STACK PCHL ;AND EXIT DIVPOS: XCHG LXI H,0 ;*************************************************** ;SUBR :DHLDEBYBC ;PURP :DIVIDE HLDE BY BC ;ENTRY :HL=DIVIDEND HIGH WORD,DE=DIVIDEND LOW WORD ; :BC=DIVISOR ;EXIT :HL=QUOTIENT,DE=REMAINDER ; :IF BC=0 THEN ERROR=ZERODIVISOR ; :NOTE THE QUOTIENT MUST BE BETWEEN 0,65535 ; : EXAMPLE: 70000/1 IS ILLEGAL BUT 70000/2 IS LEGAL ;USED :ALL ;CALLS :@DHLDEBYBC ;MACROS:NEGBC ;*************************************************** @DHLDEBYBC: XRA A STA DIVZFLAG ;INITIALLY NO ERRORS MOV A,C ORA B JNZ CONT0 ;JIF NOT ZERO ;ELSE ERROR EXIT JMP ZDIV1 ; CONT0: ;DIVISOR<>0 MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B ;TAKE NEGATIVE OF BC SO DAD B WILL ;SET HL=HL-BC MVI A,17 ;16 BITS + 1 NEXTBIT: DCR A JNZ CONT1 ;JIF NOT DONE ;ELSE EXIT XCHG ;HL=QOUTIENT,DE=REMAINDER JMP DIVXIT ; ;NOT DONE ;SHIFT HL LEFT CY=BIT 15 CONT1: DAD H JC DIV2 ;JIF BIT 15=1 ; ;SHIFT DE LEFT AND INTO HL (HL BIT0=DE BIT 15) XCHG DAD H XCHG ;DE SHIFTED CY=DE BIT 15 JNC DIV0 ;JIF BIT15=0 (HL BIT0=0 ALREADY) INR L ;ELSE SET IT TO 1 ; ;IF ABS(BC)>=HL THEN HL=HL-ABS(BC) AND E=E+1 ;?? DIV0: PUSH H ;SAVE HL DAD B JC DIV1 ;JIF ABS(BC) >= HL ; ELSE GOTO NEXTBIT POP H ;DISCARD SUBSTRACTION JMP NEXTBIT ; ; WELL ABS(BC) < HL SO INR E AND SET HL=HL-ABS(BC) ; DIV1: INR E INX SP INX SP ;DROP THE SAVED HL FROM THE STACK JMP NEXTBIT ; ; ;ARRIVE HERE IF NEXTBIT=1 DIV2: XCHG DAD H XCHG ;SHIFT DE LEFT JNC DIV3 ;JIF BIT 15=0 INR L ;ELSE SET BIT0 OF HL=1 ; ;NOW HL=HL-ABS(BC) AND E=E+1 DIV3: DAD B INR E JMP NEXTBIT ;CONTINUE ON ; DIVXIT: XCHG RET ZDIV1: lxi h,output ;make it portable! shld @lfb lxi h,div0msg push h lxi h,-1 push h push h call @wrs ; MVI C,9 ; LXI D,DIV0MSG ; CALL 5 CALL @HLT DIV0MSG: db div0len db 13,10,'Divide by zero',13,10 div0len equ $-div0msg-1 RET @XDIVD: XRA A STA DIVZFLAG ORA C JNZ Y10 ;CHECK FIRST BYTE, IF NOT ZERO BRANCH ORA B JZ Y99 ;IF NEXT BYTE 0 THEN DIVIDE BY 0 XRI 80H JZ Y99 ;MAKE SURE ITS NOT 32768 Y10: MOV A,B ANA A JM Y50 ;BR IF DENOMINATOR NEGATIVE, ILLEGAL Y20: ORA D JM Y40 ;BR IF NUMERATOR NEGATIVE Y30: XCHG CALL DIVPOS RET Y40: ;COME HERE WHEN NUMERATOR IS NEGATIVE MOV A,L CPI 1 ;IF WE ARE ENTERED VIA MOD BRANCH JZ ISMOD MOV A,E CMA MOV L,A MOV A,D CMA MOV H,A INX H ;TAKE TWOS COMPLEMENT OF NUMERATOR CALL DIVPOS MOV A,E CMA MOV E,A MOV A,D CMA MOV D,A INX D ;TAKE TWOS COMP OF QUOTIENT RET ISMOD: ; LXI H,0FFFFH ;SIGN EXTEND mov a,d cma mov d,a mov a,e cma mov e,a inx d lxi h,0 CALL @DHLDEBYBC ;GO DO THE DIVIDE RET ;AND EXIT Y50: XRA A SUB C MOV C,A MVI A,00H SBB B MOV B,A MOV A,D ANA A JM Y80 JNZ Y60 ORA E JZ Y80 Y60: XCHG CALL DIVPOS MOV A,E CMA MOV E,A MOV A,D CMA MOV D,A INX D Y70: MOV A,L SUB C MOV L,A MOV A,H SBB B MOV H,A INX H RET Y80: XRA A SUB E MOV L,A MVI A,00H SBB D MOV H,A CALL DIVPOS XRA A SUB L MOV L,A MVI A,00H SBB H MOV H,A RET Y99: JMP ZDIV1 MVI A,1 STA DIVZFLAG LXI D,0FFFFH LXI H,0 RET @DIV: POP H POP B POP D PUSH H MVI L,0 ;SIGNAL NOT MOD CALL @XDIVD POP H PUSH D PCHL @MOD: POP H POP B POP D PUSH H mvi a,0 sta modsign mvi a,128 ana d jz mod1 mvi a,255 sta modsign mod1: MVI L,1 ;SIGNAL MOD CALL @XDIVD lda modsign cpi 255 jnz mod2 mov a,h cma mov h,a mov a,l cma mov l,a inx h mod2: XTHL PCHL @UDV: ;UNSIGNED DIVIDE POP D ;RET ADR POP B ;DIVIDEND POP H ;DIVISOR PUSH D CALL DIVPOS XCHG XTHL PCHL @UMD: ;UNSIGNED MOD POP D POP B POP H PUSH D CALL DIVPOS XTHL PCHL END