	TITLE	'ASM IO MODULE'
;	I/O MODULE FOR MP/M ASSEMBLER
;
	org	0
base	equ	$

	ORG	200H
BOOT	EQU	base+00H	;REBOOT LOCATION
;	I/O MODULE ENTRY POINTS
	JMP	INIT	;INITIALIZE, START ASSEMBLER
	JMP	SETUP	;FILE SETUP
	JMP	GNC	;GET NEXT CHARACTER
	JMP	PNC	;PUT NEXT OUTPUT CHARACTER
	JMP	PNB	;PUT NEXT HEX BYTE
	JMP	PCHAR	;PRINT CONSOLE CHARACTER
	JMP	PCON	;PRINT CONSOLE BUFFER TO CRLF
	JMP	WOBUFF	;WRITE OUTBUFFER
	JMP	PERR	;PLACE ERROR CHARACTER INTO PBUFF
	JMP	DHEX	;PLACE HEX BYTE INTO OUTPUT BUFFER
	JMP	EOR	;END OF ASSEMBLY
;	DATA FOR I/O MODULE
BPC:	DS	2	;BASE PC FOR CURRENT HEX RECORD
DBL:	DS	1	;HEX BUFFER LENGTH
DBUFF:	DS	16	;HEX BUFFER
;
;	DISK NAMES
CDISK:	DS	1	;CURRENTLY SELECTED DISK
ADISK:	DS	1	;.ASM DISK
PDISK:	DS	1	;.PRN DISK
HDISK:	DS	1	;.HEX DISK
;
;
;
;	COMMON EQUATES
QBMAX	EQU	90	;MAX PRINT SIZE
QBUFF	EQU	base+10CH	;PRINT BUFFER
QBP	EQU	QBUFF+QBMAX	;PRINT BUFFER POINTER
;
TOKEN	EQU	QBP+1	;CURRENT TOKEN UDER SCAN
VALUE	EQU	TOKEN+1	;VALUE OF NUMBER IN BINARY
ACCLEN	EQU	VALUE+2	;ACCUMULATOR LENGTH
ACMAX	EQU	64	;MAX ACCUMULATOR LENGTH
ACCUM	EQU	ACCLEN+1
;
EVALUE	EQU	ACCUM+ACMAX	;VALUE FROM EXPRESSION ANALYSIS
;
SYTOP	EQU	EVALUE+2	;CURRENT SYMBOL TOP
SYMAX	EQU	SYTOP+2		;MAX ADDRESS+1
;
PASS	EQU	SYMAX+2	;CURRENT PASS NUMBER
FPC	EQU	PASS+1	;FILL ADDRESS FOR DHEX ROUTINE
ASPC	EQU	FPC+2	;ASSEMBLER'S PSEUDO PC
;
CR	EQU	0DH	;CARRIAGE RETURN
LF	EQU	0AH	;LINE FEED
EOF	EQU	1AH	;END OF FILE MARK
;
;
;	DOS ENTRY POINTS
BDOS	EQU	base+5H	;DOS ENTRY POINT
READC	EQU	1	;READ CONSOLE DEVICE
WRITC	EQU	2	;WRITE CONSOLE DEVICE
REDYC	EQU	11	;CONSOLE CHARACTER READY
SELECT	EQU	14	;SELECT DISK SPECIFIED BY REGISTER E
OPENF	EQU	15	;OPEN FILE
CLOSF	EQU	16	;CLOSE FILE
DELEF	EQU	19	;DELETE FILE
READF	EQU	20	;READ FILE
WRITF	EQU	21	;WRITE FILE
MAKEF	EQU	22	;MAKE A FILE
CSEL	EQU	25	;RETURN CURRENTLY SELECTED DISK
SETDM	EQU	26	;SET DMA ADDRESS
;
;	FILE AND BUFFERING PARAMETERS
NSB	EQU	8	;NUMBER OF SOURCE BUFFERS
NPB	EQU	6	;NUMBER OF PRINT BUFFERS
NHB	EQU	6	;NUMBER OF HEX BUFFERS
;
SSIZE	EQU	NSB*128
PSIZE	EQU	NPB*128
HSIZE	EQU	NHB*128
;
;	FILE CONTROL BLOCKS
SCB:	DS	9	;FILE NAME
	DB	'ASM'	;FILE TYPE
SCBR:	DS	1	;REEL NUMBER (ZEROED IN SETUP)
	DS	19	;MISC AND DISK MAP
SCBCR:	DS	1	;CURRENT RECORD (ZEROED IN SETUP)
;
PCB:	DS	9
	DB	'PRN',0
	DS	19
	DB	0	;RECORD TO WRITE NEXT
;
HCB:	DS	9
	DB	'HEX',0
	DS	19
	DB	0
;
;	POINTERS AND BUFFERS
SBP:	DW	SSIZE	;NEXT CHARACTER POSITION TO READ
SBUFF:	DS	SSIZE
;
PBP:	DW	0
PBUFF:	DS	PSIZE
;
HBP:	DW	0
HBUFF:	DS	HSIZE
FCB	EQU	base+5CH	;FILE CONTROL BLOCK ADDRESS
FNM	EQU	1	;POSITION OF FILE NAME
FLN	EQU	9	;FILE NAME LENGTH
BUFF	EQU	base+80H	;INPUT DISK BUFFER ADDRESS
;
SEL:	;SELECT DISK IN REG-A
	LXI	H,CDISK
	CMP	M	;SAME?
	RZ
	MOV	M,A	;CHANGE CURRENT DISK
	MOV	E,A
	MVI	C,SELECT
	CALL	BDOS
	RET
;
SCNP:	;SCAN THE NEXT PARAMETER
	INX	H
	MOV	A,M
	CPI	' '
	JZ	SCNP0
	SBI	'A'	;NORMALIZE
	RET
SCNP0:	LDA	CDISK
	RET
;
PCON:	;PRINT MESSAGE AT H,L TO CONSOLE DEVICE
	MOV	A,M
	CALL	PCHAR
	MOV	A,M
	INX	H
	CPI	CR
	JNZ	PCON
	MVI	A,LF
	CALL	PCHAR
	RET
;
FNAME:	;FILL NAME FROM DEFAULT FILE CONTROL BLOCK
	LXI	D,FCB
	MVI	B,FLN
FNAM0:	LDAX	D	;GET NEXT FILE CHARACTER
	CPI	'?'
	JZ	FNERR	;FILE NAME ERROR
	MOV	M,A	;STORE TO FILE CNTRL BLOCK
	INX	H
	INX	D
	DCR	B
	JNZ	FNAM0	;FOR NEXT CHARACTER
	RET
;
INIT:	;SET UP STACK AND FILES, START ASSEMBLER
	LXI	H,TITL
	CALL	PCON
	JMP	SET0
;
OPEN:	;OPEN FILE ADDRESSED BY D,E
	MVI	C,OPENF
	CALL	BDOS
	CPI	255
	RNZ
;	OPEN ERROR
	LXI	H,ERROP
	CALL	PCON
	JMP	BOOT
;
CLOSE:	;CLOSE FILE ADDRESSED BY D,E
	MVI	C,CLOSF
	CALL	BDOS
	CPI	255
	RNZ		;CLOSE OK
	LXI	H,ERRCL
	CALL	PCON
	JMP	BOOT
;
DELETE:	;DELETE FILE ADDRESSED BY D,E
	MVI	C,DELEF
	JMP	BDOS
;
MAKE:	;MAKE FILE ADDRESSED BY D,E
	MVI	C,MAKEF
	CALL	BDOS
	CPI	255
	RNZ
;	MAKE ERROR
	LXI	H,ERRMA
	CALL	PCON
	JMP	BOOT
;
SELA:	LDA	ADISK
	CALL	SEL
	RET
;
NPR:	;RETURN ZERO FLAG IF NO PRINT FILE
	LDA	PDISK
	CPI	'Z'-'A'
	RZ
	CPI	'X'-'A'	;CONSOLE
	RET
;
SELP:	LDA	PDISK
	CALL	SEL
	RET
;
SELH:	LDA	HDISK
	CALL	SEL
	RET
;
SET0:	;SET UP FILES FOR INPUT AND OUTPUT
	LDA	FCB	;GET FIRST CHARACTER
	CPI	' '	;MAY HAVE FORGOTTEN NAME
	JZ	FNERR	;FILE NAME ERROR
	MVI	C,CSEL	;CURRENT DISK?
	CALL	BDOS	;GET IT TO REG-A
	STA	CDISK
;
;	SCAN PARAMETERS
	LXI	H,FCB+FLN-1
	CALL	SCNP
	STA	ADISK
	CALL	SCNP
	STA	HDISK
	CALL	SCNP
	STA	PDISK
;
	LXI	H,SCB	;ADDRESS SOURCE FILE CONTROL BLOCK
	CALL	FNAME		;FILE NAME OBTAINED FROM DEFAULT FCB
;
	CALL	NPR	;Z OR X?
	JZ	NOPR
	LXI	H,PCB	;ADDRESS PRINT FILE CONTROL BLOCK
	PUSH	H	;SAVE A COPY FOR OPEN
	PUSH	H	;SAVE A COPY FOR DELETE
	CALL	FNAME	;FILL PCB
	CALL	SELP
	POP	D	;FCB ADDRESS
	CALL	DELETE
	POP	D	;FCB ADDRESS
	CALL	MAKE
;
NOPR:	;TEST FOR HEX FILE
	LDA	HDISK
	CPI	'Z'-'A'
	JZ	NOHEX
	LXI	H,HCB
	PUSH	H
	PUSH	H
	CALL	FNAME
	CALL	SELH
	POP	D
	CALL	DELETE
	POP	D
	CALL	MAKE
;
;	FILES SET UP, CALL ASSEMBLER
NOHEX:	JMP	ENDMOD
;
SETUP:	;SETUP INPUT FILE FOR SOURCE PROGRAM
	LXI	H,SSIZE
	SHLD	SBP	;CAUSE IMMEDIATE READ
	XRA	A	;ZERO VALUE
	STA	SCBR	;CLEAR REEL NUMBER
	STA	SCBCR		;CLEAR CURRENT RECORD
	STA	DBL		;CLEAR HEX BUFFER LENGTH
	CALL	SELA
	LXI	D,SCB
	CALL	OPEN
;
	RET
;
FNERR:	;FILE NAME ERROR
	LXI	H,ERRFN
	CALL	PCON
	JMP	BOOT
;
;
GCOMP:	;COMPARE D,E AGAINS H,L
	MOV	A,D
	CMP	H
	RNZ
	MOV	A,E
	CMP	L
	RET
;
GNC:	;GET NEXT CHARACTER FROM SOURCE BUFFER
	PUSH	B
	PUSH	D
	PUSH	H	;ENVIRONMENT SAVED
	LHLD	SBP
	LXI	D,SSIZE
	CALL	GCOMP
	JNZ	GNC2
;
;	READ ANOTHER BUFFER
	CALL	SELA
	LXI	H,0
	SHLD	SBP
	MVI	B,NSB	;NUMBER OF SOURCE BUFFERS
	LXI	H,SBUFF
GNC0:	;READ 128 BYTES
	PUSH	B	;SAVE COUNT
	PUSH	H	;SAVE BUFFER ADDRESS
	MVI	C,READF
	LXI	D,SCB
	CALL	BDOS	;PERFORM THE READ
	POP	H	;RESTORE BUFFER ADDRESS
	POP	B	;RESTORE BUFFER COUNT
	ORA	A	;SET FLAGS
	MVI	C,128
	JNZ	GNC1
;	NORMAL READ OCCURRED
	LXI	D,BUFF	;SOURCE BUFFER ADDRESS
	MVI	C,128
MOV0:	LDAX	D	;GET CHARACTER
	MOV	M,A	;STORE CHARACTER
	INX	D
	INX	H
	DCR	C
	JNZ	MOV0
;	BUFFER LOADED, TRY NEXT BUFFER
;
	DCR	B
	JNZ	GNC0
	JMP	GNC2
;
GNC1:	;EOF OR ERROR
	CPI	3	;ALLOW 0,1,2
	JNC	FRERR	;FILE READ ERROR
GNCE:	MVI	M,EOF	;STORE AND END OF FILE CHARACTER
	INX	H
	DCR	C
	JNZ	GNCE	;FILL CURRENT BUFFER WITH EOF'S
;
GNC2:	;GET CHARACTER TO ACCUMULATOR AND RETURN
	LXI	D,SBUFF
	LHLD	SBP
	PUSH	H	;SAVE CURRENT SBP
	INX	H	;READY FOR NEXT READ
	SHLD	SBP
	POP	H	;RESTORE PREVIOUS SBP
	DAD	D	;ABSOLUTE ADDRESS OF CHARACTER
	MOV	A,M	;GET IT
	POP	H
	POP	D
	POP	B
	RET
;
FRERR:	LXI	H,ERRFR
	CALL	PCON	;PRINT READ ERROR MESSAGE
	JMP	BOOT
;
PNC:	;SAME AT PNCF, BUT ENVIRONMENT IS SAVED FIRST
	PUSH	B
;	CHECK FOR CONSOLE OUTPUT / NO OUTPUT
	MOV	B,A	;SAVE CHARACTER
	LDA	PDISK	;Z OR X?
	CPI	'Z'-'A'	;Z NO OUTPUT
	JZ	PNRET
;
	CPI	'X'-'A'
	MOV	A,B	;RECOVER CHAR FOR CON OUT
	JNZ	PNGO
	CALL	PCHAR
	JMP	PNRET
;
;	NOT X OR Z, SO PRINT IT
PNGO:	PUSH	D
	PUSH	H
	CALL	PNCF
	POP	H
	POP	D
PNRET:	POP	B
	RET
;
PNCF:	;PRINT NEXT CHARACTER
	LHLD	PBP
	XCHG
	LXI	H,PBUFF
	DAD	D
	MOV	M,A	;CHARACTER STORED AT PBP IN PBUFF
	XCHG		;PBP TO H,L
	INX	H	;POINT TO NEXT CHARACTER
	SHLD	PBP	;REPLACE IT
	XCHG
	LXI	H,PSIZE
	CALL	GCOMP	;AT END OF BUFFER?
	RNZ		;RETURN IF NOT
;
;	OVERFLOW, WRITE BUFFER
	CALL	SELP
	LXI	H,0
	SHLD	PBP
	LXI	H,PBUFF
	LXI	D,PCB	;D,E ADDRESS FILE CONTROL BLOCK
	MVI	B,NPB	;NUMBER OF BUFFERS TO B
;	(DROP THROUGH TO WBUFF)
;
WBUFF:	;WRITE BUFFERS STARTING AT H,L FOR B BUFFERS
;	CHECK FOR EOF'S
	MOV	A,M
	CPI	EOF
	RZ		;DON'T DO THE WRITE
;
	PUSH	B	;SAVE NUMBER OF BUFFERS
	PUSH	D	;SAVE FCB ADDRESS
	MVI	C,128	;READY FOR MOVE
	LXI	D,BUFF
WBUF0:	;MOVE TO BUFFER
	MOV	A,M	;GET CHARACTER
	STAX	D	;PUT CHARACTER
	INX	H
	INX	D
	DCR	C
	JNZ	WBUF0
;
;	WRITE BUFFER
	POP	D	;RECOVER FCB ADDRESS
	PUSH	D	;SAVE IT AGAIN FOR LATER
	PUSH	H	;SAVE BUFFER ADDRESS
	MVI	C,WRITF	;DOS WRITE FUNCTION
	CALL	BDOS
	POP	H	;RECOVER BUFFER ADDRESS
	POP	D	;RECOVER FCB ADDRESS
	POP	B	;RECOVER BUFFER COUNT
	ORA	A	;SET ERROR RETURN FLAGS
	JNZ	FWERR
;
;	WRITE OK
	DCR	B
	RZ		;RETURN IF NO MORE BUFFERS TO WRITE
	JMP	WBUFF
;
FWERR:	;ERROR IN WRITE
	LXI	H,ERRFW
	CALL	PCON	;ERROR MESSAGE OUT
	JMP	EORC	;TO CLOSE AND REBOOT
;
;
PNB:	;PUT NEXT HEX BYTE
	PUSH	B
	PUSH	D
	PUSH	H
	CALL	PNBF
	POP	H
	POP	D
	POP	B
	RET
;
PNBF:	;PUT NEXT BYTE
;	(SIMILAR TO THE PNCF SUBROUTINE)
	LHLD	HBP
	XCHG
	LXI	H,HBUFF
	DAD	D
	MOV	M,A	;CHARACTER STORED AT HBP IN HBUFF
	XCHG
	INX	H	;HBP INCREMENTED
	SHLD	HBP
	XCHG		;BACK TO D,E
	LXI	H,HSIZE
	CALL	GCOMP	;EQUAL?
	RNZ
;
;	OVERFLOW, WRITE BUFFERS
	CALL	SELH
	LXI	H,0
	SHLD	HBP
	LXI	H,HBUFF
	LXI	D,HCB	;FILE CONTROL BLOCK FOR HEX FILE
	MVI	B,NHB
	JMP	WBUFF	;WRITE BUFFERS
;
PCHAR:	;PRINT CHARACTER IN REGISTER A
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,WRITC
	MOV	E,A
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	RET
;
WOCHAR:	;WRITE CHARACTER IN REG-A WITH REFLECT AT CONSOLE IF ERROR
	MOV	C,A	;SAVE THE CHAR
	CALL	PNC	;PRINT CHAR
	LDA	QBUFF
	CPI	' '
	RZ
;	ERROR IN LINE
	LDA	PDISK
	CPI	'X'-'A'
	RZ		;ALREADY PRINTED IF 'X'
;
	MOV	A,C	;RECOVER CHARACTER
	CALL	PCHAR	;PRINT IT
	RET
;
WOBUFF:	;WRITE THE OUTPUT BUFFER TO THE PRINT FILE
	LDA	QBP	;GET CHARACTER COUNT
	LXI	H,QBUFF	;BASE OF BUFFER
WOB0:	ORA	A	;ZERO COUNT?
	JZ	WOBE
;	NOT END, SAVE COUNT AND GET CHARACTER
	MOV	B,A	;SAVE COUNT
	MOV	A,M
	CALL	WOCHAR	;WRITE CHARACTER
	INX	H	;ADDRESS NEXT CHARACTER OF BUFFER
	MOV	A,B	;GET COUNT
	DCR	A
	JMP	WOB0
;
WOBE:	;END OF PRINT - ZERO QBP
	STA	QBP
;	FOLLOW BY CR LF
	MVI	A,CR
	CALL	WOCHAR
	MVI	A,LF
	CALL	WOCHAR
	LXI	H,QBUFF
	MVI	A,QBMAX	;READY TO BLANK OUT
WOB2:	MVI	M,' '
	INX	H
	DCR	A
	JNZ	WOB2
	RET
;
;
PERR:	;FILL QBUFF ERROR MESSAGE POSITION
	MOV	B,A	;SAVE CHARACTER
	LXI	H,QBUFF
	MOV	A,M
	CPI	' '
	RNZ	;DON'T CHANGE IT IF ALREADY SET
	MOV	M,B	;STORE ERROR CHARACTER
	RET
;
EOR:	;END OF ASSEMBLER
	CALL	NPR	;Z OR A?
	JZ	EOPR
;	FILL OUTPUT FILES WITH EOF'S
EOR2:	LHLD	PBP
	MOV	A,L
	ORA	H	;VALUE ZERO?
	JZ	EOPR
	MVI	A,EOF	;CTL-Z IS END OF FILE
	CALL	PNC	;PUT ENDFILES IN PRINT BUFFER
	JMP	EOR2	;EVENTUALLY BUFFER IS WRITTEN
;
EOPR:	;END OF PRINT FILE, CHECK HEX
	LDA	HDISK
	CPI	'Z'-'A'
	JZ	EORC
EOR0:	;WRITE TERMINATING RECORD INTO HEX FILE
	LDA	DBL	;MAY BE ZERO ALREADY
	ORA	A
	CNZ	WHEX	;WRITE HEX BUFFER IF NOT ZERO
	LHLD	FPC	;GET CURRENT FPC AS LAST ADDRESS
	SHLD	BPC	;RECORD LENGTH ZERO, BASE ADDRESS 0000
	CALL	WHEX	;WRITE HEX BUFFER
;
;	NOW CLEAR OUTPUT BUFFER FOR HEX FILE
EOR1:	LHLD	HBP
	MOV	A,L
	ORA	H
	JZ	EORC
	MVI	A,EOF
	CALL	PNB
	JMP	EOR1
;
;	CLOSE FILES AND TERMINATE
EORC:
	CALL	NPR
	JZ	EORPC
	CALL	SELP
	LXI	D,PCB
	CALL	CLOSE
EORPC:
	LDA	HDISK
	CPI	'Z'-'A'
	JZ	EORHC
	CALL	SELH
	LXI	D,HCB
	CALL	CLOSE
;
EORHC:
	LXI	H,ENDA
	CALL	PCON
	JMP	BOOT
;
TITL:	DB	'MP/M ASSEMBLER - VER 1.1',CR
ERROP:	DB	'NO SOURCE FILE PRESENT',CR
ERRMA:	DB	'NO DIRECTORY SPACE',CR
ERRFN:	DB	'SOURCE FILE NAME ERROR',CR
ERRFR:	DB	'SOURCE FILE READ ERROR',CR
ERRFW:	DB	'OUTPUT FILE WRITE ERROR',CR
ERRCL:	DB	'CANNOT CLOSE FILES',CR
ENDA:	DB	'END OF ASSEMBLY',CR
;
DHEX:	;DATA TO HEX BUFFER (BYTE IN REG-A)
	PUSH	B
	MOV	B,A	;HOLD CHARACTER FOR 'Z' TEST
	LDA	HDISK
	CPI	'Z'-'A'
	MOV	A,B	;RECOVER CHARACTER
	JZ	DHRET
	PUSH	D	;ENVIRONMENT SAVED
	PUSH	PSW	;SAVE DATA BYTE
	LXI	H,DBL	;CURRENT LENGTH
	MOV	A,M	;TO ACCUM
	ORA	A	;ZERO?
	JZ	DHEX3
;
;	LENGTH NOT ZERO, MAY BE FULL BUFFER
	CPI	16
	JC	DHEX1	;BR IF LESS THAN 16 BYTES
;	BUFFER FULL, DUMP IT
	CALL	WHEX	;DBL = 0 UPON RETURN
	JMP	DHEX3	;SET BPC AND DATA BYTE
;
DHEX1:	;PARTIAL BUFFER IN PROGRESS, CHECK FOR SEQUENTIAL BYTE LOAD
	LHLD	FPC
	XCHG
	LHLD	BPC	;BASE PC IN H,L
	MOV	C,A	;CURRENT LENGTH OF BUFFER
	MVI	B,0	;IS IN B,C
	DAD	B	;BPC+DBL TO H,L
	MOV	A,E	;READY FOR COMPARE
	CMP	L	;EQUAL?
	JNZ	DHEX2	;BR IF NOT
	MOV	A,D	;CHECK HO BYTE
	CMP	H
	JZ	DHEX4	;BR IF SAME ADDRESS
;
DHEX2:	;NON SEQUENTIAL ADDRESS, DUMP AND CHANGE BASE ADDRESS
	CALL	WHEX
DHEX3:	;SET NEW BASE
	LHLD	FPC
	SHLD	BPC
;
DHEX4:	;STORE DATA BYTE AND INC DBL
	LXI	H,DBL
	MOV	E,M	;LENGTH TO REG-E
	INR	M	;DBL=DBL+1
	MVI	D,0	;HIGH ORDER ZERO FOR DOUBLE ADD
	LXI	H,DBUFF
	DAD	D	;DBUFF+DBL TO H,L
	POP	PSW	;RESTORE DATA BYTE
	MOV	M,A	;INTO DATA BUFFER
	POP	D
DHRET:	POP	B	;ENVIRONMENT RESTORED
	RET
;
WRC:	;WRITE CHARACTER WITH CHECK SUM IN D
	PUSH	PSW
	RRC
	RRC
	RRC
	RRC
	ANI	0FH
	CALL	HEXC	;OUTPUT HEX CHARACTER
	POP	PSW	;RESTORE BYTE
	PUSH	PSW	;SAVE A VERSION
	ANI	0FH
	CALL	HEXC	;WRITE LOW NIBBLE
	POP	PSW	;RESTORE BYTE
	ADD	D	;COMPUTE CHECKSUM
	MOV	D,A	;SAVE CS
	RET
;
HEXC:	;WRITE CHARACTER
	ADI	90H
	DAA
	ACI	40H
	DAA
	JMP	PNB	;PUT BYTE
;
WHEX:	;WRITE CURRENT HEX BUFFER
	MVI	A,':'	;RECORD HEADER
	CALL	PNB	;PUT BYTE
	LXI	H,DBL	;RECORD LENGTH ADDRESS
	MOV	E,M	;LENGTH TO REG-E
	XRA	A	;ZERO TO REG-A
	MOV	D,A	;CLEAR CHECKSUM
	MOV	M,A	;LENGTH IS ZEROED FOR NEXT WRITE
	LHLD	BPC	;BASE ADDRESS FOR RECORD
	MOV	A,E	;LENGTH TO A
	CALL	WRC	;WRITE HEX VALUE
	MOV	A,H	;HIGH ORDER BASE ADDR
	CALL	WRC	;WRITE HO BYTE
	MOV	A,L	;LOW ORDER BASE ADDR
	CALL	WRC	;WRITE LO BYTE
	XRA	A	;ZERO TO A
	CALL	WRC	;WRITE RECORD TYPE 00
	MOV	A,E	;CHECK FOR LENGTH 0
	ORA	A
	JZ	WHEX1
;
;	NON - ZERO, WRITE DATA BYTES
	LXI	H,DBUFF
WHEX0:	MOV	A,M	;GET BYTE
	INX	H
	CALL	WRC	;WRITE DATA BYTE
	DCR	E	;END OF BUFFER?
	JNZ	WHEX0
;
;	END OF DATA BYTES, WRITE CHECK SUM
WHEX1:	XRA	A
	SUB	D	;COMPUTE CHECKSUM
	CALL	WRC
;
;	SEND CRLF AT END OF RECORD
	MVI	A,CR
	CALL	PNB
	MVI	A,LF
	CALL	PNB
	RET
;
;
;
ENDMOD	EQU	($ AND 0FFE0H)+20H
	END
