; ;----- call.asm: Small-C ver. 2 arithmetic and logical library ; (ASM Version 7-28-83, Bill Randle) ; (Global symbols added 02-07-84, Dennis Quinn) ; (.8080 added 10 Jan 85, Earl Boebert) ; (Updated to version in the Handbook 4 Feb 85, Earl Boebert) ; .8080 _call:: EXT _END ; CCDCAL:: PCHL ; CCDDGC:: DAD D JMP CCGCHAR ; CCDSGC:: INX H INX H DAD SP ; ;FETCH A SINGLE BYTE FROM THE ADDRESS IN HL AND ;SIGN EXTEND INTO HL ; CCGCHAR:: MOV A,M ; ;PUT THE ACCUM INTO HL AND SIGN EXTEND THROUGH H. ; CCARGC:: CCSXT:: MOV L,A RLC SBB A MOV H,A RET ; CCDDGI:: DAD D JMP CCGINT ; CCDSGI:: INX H INX H DAD SP ; ;FETCH A FULL 16-BIT INTEGER FROM THE ADDRESS IN HL ;INTO HL ; CCGINT:: MOV A,M INX H MOV H,M MOV L,A RET ; CCDECC:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR DCX H MOV A,L STAX D RET ; CCINCC:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR INX H MOV A,L STAX D RET ; ; CCDDPC:: DAD D CCPDPC:: POP B ;;RET ADDR POP D PUSH B ; ;STORE A SINGLE BYTE FROM HL AT THE ADDRESS IN DE ; CCPCHAR:: PCHAR:: MOV A,L STAX D RET ; CCDECI:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT DCX H JMP CCPINT ; CCINCI:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT INX H JMP CCPINT ; ; CCDDPI:: DAD D CCPDPI:: POP B ;;RET ADDR POP D PUSH B ; ;STORE A 16-BIT INTEGER IN HL AT THE ADDRESS IN DE ; CCPINT:: PINT:: MOV A,L STAX D INX D MOV A,H STAX D RET ; ;INCLUSIVE "OR" HL AND DE INTO HL ; CCOR:: MOV A,L ORA E MOV L,A MOV A,H ORA D MOV H,A RET ; ;EXCLUSIVE "OR" HL AND DE INTO HL ; CCXOR:: MOV A,L XRA E MOV L,A MOV A,H XRA D MOV H,A RET ; ;"AND" HL AND DE INTO HL ; CCAND:: MOV A,L ANA E MOV L,A MOV A,H ANA D MOV H,A RET ; ;IN ALL THE FOLLOWING COMPARE ROUTINES, HL IS SET TO 1 IF THE ;CONDITION IS TRUE, OTHERWISE IT IS SET TO 0 (ZERO). ; ;TEST IF HL = DE ; CCEQ:: CALL CCCMP RZ DCX H RET ; ;TEST IF DE <> HL ; CCNE:: CALL CCCMP RNZ DCX H RET ; ;TEST IF DE > HL (SIGNED) ; CCGT:: XCHG CALL CCCMP RC DCX H RET ; ;TEST IF DE <= HL (SIGNED) ; CCLE:: CALL CCCMP RZ RC DCX H RET ; ;TEST IF DE >= HL (SIGNED) ; CCGE:: CALL CCCMP RNC DCX H RET ; ;TEST IF DE < HL (SIGNED) ; CCLT:: CALL CCCMP RC DCX H RET ; ;COMMON ROUTINE TO PERFORM A SIGNED COMPARE ; OF DE AND HL ;THIS ROUTINE PERFORMS DE - HL AND SETS THE CONDITIONS: ; CARRY REFLECTS SIGN OF DIFFERENCE (SET MEANS DE < HL) ; ZERO/NON-ZERO SET ACCORDING TO EQUALITY. ; CCCMP:: MOV A,H ;;INVERT SIGN OF HL XRI 80H MOV H,A MOV A,D ;;INVERT SIGN OF DE XRI 80H CMP H ;;COMPARE MSBS JNZ CCCMP1 ;;DONE IF NEQ MOV A,E ;;COMPARE LSBS CMP L CCCMP1: LXI H,1 ;;PRESET TRUE COND RET ; ;TEST IF DE >= HL (UNSIGNED) ; CCUGE:: CALL CCUCMP RNC DCX H RET ; ;TEST IF DE < HL (UNSIGNED) ; CCULT:: CALL CCUCMP RC DCX H RET ; ;TEST IF DE > HL (UNSIGNED) ; CCUGT:: XCHG CALL CCUCMP RC DCX H RET ; ;TEST IF DE <= HL (UNSIGNED) ; CCULE:: CALL CCUCMP RZ RC DCX H RET ; ;COMMON ROUTINE TO PERFORM UNSIGNED COMPARE ;CARRY SET IF DE < HL ;ZERO/NONZERO SET ACCORDINGLY ; CCUCMP:: MOV A,D CMP H JNZ CCUCP1 MOV A,E CMP L CCUCP1: LXI H,1 RET ; ;SHIFT DE ARITHMETICALLY RIGHT BY HL AND RETURN IN HL ; CCASR:: XCHG DCR E RM MOV A,H RAL MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A JMP CCASR+1 ; ;SHIFT DE ARITHMETICALLY LEFT BY HL AND RETURN IN HL ; CCASL:: XCHG DCR E RM DAD H JMP CCASL+1 ; ;SUBTRACT HL FROM DE AND RETURN IN HL ; CCSUB:: MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A RET ; ;FORM THE TWO'S COMPLEMENT OF HL ; CCNEG:: CALL CCCOM INX H RET ; ;FORM THE ONE'S COMPLEMENT OF HL ; CCCOM:: MOV A,H CMA MOV H,A MOV A,L CMA MOV L,A RET ; ;MULTIPLY DE BY HL AND RETURN IN HL ;(SIGNED MULTIPLY) ; CCMULT:: MULT:: MOV B,H MOV C,L LXI H,0 CCMLT1: MOV A,C RRC JNC CCMLT2 DAD D CCMLT2: XRA A MOV A,B RAR MOV B,A MOV A,C RAR MOV C,A ORA B RZ XRA A MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RZ JMP CCMLT1 ; ;DIVIDE DE BY HL AND RETURN QUOTIENT IN HL, REMAINDER IN DE ;(SIGNED DIVIDE) ; CCDIV:: DIV:: MOV B,H MOV C,L MOV A,D XRA B PUSH PSW MOV A,D ORA A CM CCDENEG MOV A,B ORA A CM CCBCNEG MVI A,16 PUSH PSW XCHG LXI D,0 CCDIV1: DAD H CALL CCRDEL JZ CCDIV2 CALL CCCMPBCDE JM CCDIV2 MOV A,L ORI 1 MOV L,A MOV A,E SUB C MOV E,A MOV A,D SBB B MOV D,A CCDIV2: POP PSW DCR A JZ CCDIV3 PUSH PSW JMP CCDIV1 CCDIV3: POP PSW RP CALL CCDENEG XCHG CALL CCDENEG XCHG RET ; ;NEGATE THE INTEGER IN DE ;(INTERNAL ROUTINE) ; CCDENEG: MOV A,D CMA MOV D,A MOV A,E CMA MOV E,A INX D RET ; ;NEGATE THE INTEGER IN BC ;(INTERNAL ROUTINE) ; CCBCNEG: MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B RET ; ;ROTATE DE LEFT ONE BIT ;(INTERNAL ROUTINE) ; CCRDEL: MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RET ; ;COMPARE BC TO DE ;(INTERNAL ROUTINE) ; CCCMPBCDE: MOV A,E SUB C MOV A,D SBB B RET ; ; LOGICAL NEGATION ; CCLNEG:: MOV A,H ORA L JNZ $+6 MVI L,1 RET LXI H,0 RET ; ; EXECUTE "SWITCH" STATEMENT ; ; HL = SWITCH VALUE ; (SP) -> SWITCH TABLE ; DW ADDR1, VALUE1 ; DW ADDR2, VALUE2 ; ... ; DW 0 ; [JMP default] ; continuation ; CCSWITCH:: XCHG ;;DE = SWITCH VALUE POP H ;;HL -> SWITCH TABLE SWLOOP: MOV C,M INX H MOV B,M ;;BC -> CASE ADDR, ELSE 0 INX H MOV A,B ORA C JZ SWEND ;;DEFAULT OR CONTINUATION CODE MOV A,M INX H CMP E MOV A,M INX H JNZ SWLOOP CMP D JNZ SWLOOP MOV H,B ;;CASE MATCHED MOV L,C SWEND: PCHL ; ;(code added from DDJ) ; _end: LHLD 6 ;get bdos address SPHL ;use for base of stack LXI H, _end ;get start of free memory SHLD _memptr## ;use for memory allocation JMP _main## ;parse command line, execut program END _end