;
; Disassembly of ALS-8 System
; by Barry A. Watzman
;
DATA	EQU	0D000H		;LOCATION OF DATA BLOCK
CODE	EQU	0E000H		;LOCATION OF ACTUAL CODE
VDM1	EQU	0CC00H		;VDM-1 SCREEN MEMORY LOCATION
;
	ORG	CODE
ALS8:	NOP
	JMP	LE03B
;
;PART OF THE CODE TO DELETE CUSTOM COMMANDS
;
LE004:	CALL	LE50C		;SET UP ABUF, H,L FOR DELETE
	JMP	LE4B7		;USE SYMLD CODE TO DELETE COMD
;
;THIS ROUTINE FETCHES DIGITS FROM THE BUFFER ADDRESSED
;BY B,C AND CONVERTS THE ASCII DECIMAL DIGITS INTO
;BINARY.  UP TO A 16-BIT VALUE CAN BE CONVERTED.  THE
;SCAN STOPS WHEN A BINARY ZERO IS FOUND IN THE BUFFER.
;
ADEC:	LXI	H,0		;GET A 16 BIT ZERO
ADE1:	LDAX	B		;FETCH ASCII DIGIT
	ORA	A		;SET ZERO FLAG
	RZ			;RETURN IFF FINISHED
	MOV	D,H		;DUPLICATE CURRENT VALUE
	MOV	E,L		;FROM H,L INTO D,E
	DAD	H		;CURRENT VALUE TIMES TWO
	DAD	H		;AGAIN - NOW 4X ORIG. VALUE
	DAD	D		;ADD IN ORIG VALUE - NOW 5X
	DAD	H		;TIMES TWO - NOW 10X
	SUI	30H		;CONVERT FETCHED DGT TO BINARY
	CPI	10		;CHECK FOR LEGAL VALUE
	CMC			;SET UP CARRY FLAG
	RC			;RETURN W/CARRY SET IF ERROR
	MOV	E,A		;ELSE MOVE BINARY VALUE TO E
	MVI	D,0		;AND ZERO TO D
	DAD	D		;AND ADD TO 10X ORIG. NUMBER
	INX	B		;NOW POINT TO NEXT DIGIT
	JMP	ADE1		;AND PROCESS IT
;
;LOWEST LEVEL ENTRY POINT -- INITIALIZES EVERYTHING
;
INITA:	LXI	H,FILE0		;POINT TO START OF DATA AREA
	XRA	A		;GET A ZERO
	MOV	C,A		;MOVE IT TO C
INIT2:	MOV	M,A		;STASH THE ZERO
	DCR	C		;DECREMENT C
	INX	H		;POINT TO NEXT LOCATION
	JNZ	INIT2		;IF HAVEN'T DONE 256 LOCATIONS
	STA	SYSYM		;ANOTHER LOCATION TO ZERO
	STA	SMODE		;AND ANOTHER
	STA	CUCOM		;AND STILL ANOTHER
	JMP	ALS8		;NOW START UP THE SYSTEM
;
;WARM RESTART - RESTORES I/O DRIVERS AND DOES PARTIAL
;INITIALIZATION
;
LE03B:	MVI	C,(CRLF-IONME) AND 0FFH
	LXI	SP,SMODE	;SET STACK POINTER
	LXI	D,IONME		;POINT TO IO CODE SOURCE
	LXI	H,SYSIO		;POINT TO DEST IN DATA AREA
LE046:	LDAX	D		;GET A BYTE
	MOV	M,A		;PUT IT IN DATA AREA
	INX	D		;SOURCE POINTER
	INX	H		;DEST POINTER
	DCR	C		;NO OF BYTES LEFT TO BE MOVED
	JNZ	LE046		;IF NOT DONE
	LXI	H,ALS8		;POINT TO START CODE
	SHLD	SYMADD		;INITIAL SYMBOL TABLE ADDR
	MVI	A,(IBUF+81) AND 0FFH
	STA	TERMW		;INITIAL TERMINAL WIDTH
	XRA	A		;GET A ZERO
	STA	SMODE		;SAVE AS SMODE
	STA	CHRR		;AND CHRR
;
;WARM RESTART WITH NO INITIALIZATION
;PRINTS "READY" AND ENTERS MAIN PROCESSING LOOP
;
EORMS:	LXI	H,SYSIN		;POINT TO CUR DRIVER ADDRS
	CALL	LE15A		;SET I/O JUMPS TO CUR DRIVERS
	CALL	CRLF		;PRINT A CR/LF ON TERMINAL
	LXI	H,RDYMG		;POINT TO READY MESSAGE
	CALL	SCRN		;PRINT "READY"
	JMP	LE0CB		;ANOTHER CRLF & ENTER MAIN LOOP
;
;THIS IS THE MAIN ALS-8 COMMAND LOOP
;
LE072:	LXI	H,0		;GET A ZERO TO H,L
	SHLD	SWCH1		;TO SWITCH 1
LE078:	LXI	SP,SMODE	;SET STACK POINTER
	CALL	READ		;GET A COMND LINE IN IBUF
	INX	H		;POINT TO 1ST CHAR
	MOV	A,M		;GET IT
	CPI	'9'+1		;COMPARE TO 9
	JC	LINE		;NEW LINE IF 1ST CHAR NUMERIC
	CALL	VALC		;EXTRACT ASCII & BINARY ARGS
	MVI	B,4		;LENGTH OF ALS8 COMMANDS
	LXI	D,CTAB		;POINT AT COMMAND TABLE
	CALL	COMS		;SEE IF COMMAND IS IN TABLE
	PUSH	H		;SAVE H,L PNTR INTO LINE
	JZ	LE0AC		;MATCH WAS FOUND
	POP	H		;RESTORE POINTER TO LINE
	INX	D		;POINT TO 2ND PART OF TABLE
	CALL	COMS		;SEARCH 2ND PART
	JZ	LE0A5		;IF MATCH FOUND
	LXI	D,CUCOM		;NO MATCH, TRY CUSTOM TABLE
	CALL	LE240		;SEARCH CUSTOM TABLE
	JNZ	WHAT		;ERROR MSG IF NO MATCH FOUND
LE0A5:	PUSH	H		;SAVE H,L
	CALL	LE31E		;CONVERT ABUF CNTS TO BINARY
	JC	WHAT		;IF ABUF NOT LEGAL NO.
LE0AC:	LDA	IOSWC		;1 COMND DRVR SWTCH DELAY 
FLAG
	ORA	A		;SET FLAGS
	CNZ	LE157		;TIME TO SWITCH DRIVERS
	POP	H		;RESTORE POINTER TO COMD LINE
	CALL	LE0DD		;EXECUTE THE COMMAND
EOR:	LDA	SWCH1		;GET I/O RESTORE SWITCH
	ORA	A		;SET FLAGS
	JNZ	EORMS		;RESTORE JMPS & PRT "READY"
	LDA	SWCH2		;GET DRIVER HOLD REQ.
	ORA	A		;SET FLAGS
	JNZ	EORNS		;HOLD CURRENT DRVR, DO CRLF
	LXI	H,SYSIN		;POINT TO SYSTEM DRIVERS
	CALL	LE15A		;PUT IN JUMPS & DO CRLF
LE0CB:	CALL	CRLF		;PRINT CRLF
	JMP	LE072		;DO ANOTHER ALS8 COMMAND
;
;END OF MAIN PROCESSING LOOP
;
;FOLLOWING RETURN POINT DOES A CR/LF AND LEAVES
;ALL DRIVERS AND SWITCHES INTACT
;
EORNS:	CALL	CRLF		;PRINT A CRLF
	JMP	LE078		;RET LEAVING DRIVERS INTACT
;
;SIGN-ON AND COMMAND MODE MESSAGE
;
RDYMG:	DB	'READY',0DH
;
;HERE IS WHERE WE DISPATCH TO COMMANDS
;NOTE THAT SINCE THIS IS A CALLED ROUTINE, SO
;IN EFFECT IS THE ROUTINE TRANSFERED TO
;
LE0DD:	PCHL			;GO TO IT
;
;THE IODR COMMAND AND IT'S ZILLION FORMS
;
IODR:	MVI	C,MAXFIL	;MAX NUMBER OF DRIVER NAMES
	LXI	H,IOFLE		;POINT TO DRIVER FILE
	LDA	FBUF		;NAME IN SLASHES AFTR COMMAND ?
	ORA	A		;SET FLAGS
	JZ	LE151		;NO - PRT LIST OF DRIVERS
	XCHG			;YES - TABLE PNTR TO D,E
	CALL	LE68D		;SEARCH DIRECTORY FOR NAME
	JNZ	LE0FE		;NAME FOUND
	CALL	VCHK		;NOT FOUND - CHECK FOR PARMS
	LDA	FEF		;GET FREE ENTRY FOUND FLAG
	ORA	A		;SET FLAGS
	JZ	LE5CC		;NO ENTRIES LEFT - PRT "FULL"
	LHLD	FREAD		;GET ADDR OF FREE ENTRY
LE0FE:	SHLD	FREAD		;FREAD HAS ADDR OF ENTRY
	CALL	ROOM		;PUT FILE NAME INTO DIRECTORY
	LXI	H,NMLEN		;NAME LENGTH
	DAD	D		;H,L POINT JUST AFTER NAME
	LDA	ABUF		;SEE IF ADDR SPECIFIED
	ORA	A		;SET FLAGS
	JNZ	LE119		;IF ADDR WAS SPECIFIED
	SHLD	OPRD		;NO ADDR, SET UP FOR SWTCH
	INR	A		;MAKE ACCUM. NON-ZERO
	STA	IOSWC		;SET I/O SWITCH FLAG
	JMP	LE14C		;PRINT THE SELECTED ENTRY
LE119:	XCHG			;SAVE I/O ADDRS IN D,E	
	LHLD	BBUF		;GET 1ST ADDR SPECIFIED
	MOV	A,L		;L TO A
	ORA	H		;SEE IF ADDRS IS 0
	LDA	ABUF+7		;POINT TO 2ND ASCII PARM.
	JNZ	LE130		;IF 1ST ADDR NOT ZERO
	ORA	A		;SEE IF 2ND ADDR SPECIFIED
	JNZ	LE12D		;IF 2ND ARGUMENT NOT OMITTED
	STAX	D		;STORE 0 FOR INPUT, DELT ENTRY
	INX	D		;FOR 2ND BYTE
	STAX	D		;ZERO IT TOO
BITBKT:	RET			;DONE
;
;1ST ARG. WAS 0, 2ND WAS PRESENT
;
LE12D:	LHLD	SYSIN		;GET STD SYSIN DRIVER
LE130:	XCHG			;TO D,E
	MOV	M,E		;STORING IT AS INPUT DRIVER
	INX	H		;2ND BYTE
	MOV	M,D		;STORE IT
	INX	H		;POINT TO OUTPUT DRIVER
	XCHG			;OUTPUT DRIVER ADDR TO D,E
	ORA	A		;SET FLAGS FOR 2ND ARG OMITTED
	LXI	H,BITBKT	;POINT TO THE BIT BUCKET
	JZ	LE148		;IF 2ND ARG OMITTED
	LHLD	BBUF+2		;GET 2ND ARG
	MOV	A,L		;MOVE L TO A
	ORA	H		;SEE IF ARG = 0
	JNZ	LE148		;JMP IF NOT ZERO
	LHLD	SYSOT		;ELSE SET TO USE SYSOT
LE148:	XCHG			;OUTPUT ADDR TO D,E
	MOV	M,E		;MOVING IT TO OUTPUT TABLE
	INX	H		;2ND HALF
	MOV	M,D		;DONE
LE14C:	MVI	C,1		;SET UP TO PRINT ENTRY
	LHLD	FREAD		;GET IT'S ADDRESS
LE151:	CALL	LE62A		;PRINT IT
	JMP	EORNS		;DONE WITH IODR
;
;SET UP I/O JUMPS TO I/O DRIVER SET WHOSE ADDRESSES
;ARE POINTED TO BY OPRD (SET ABOVE)
;
LE157:	LHLD	OPRD		;GET ADDRESS OF I/O ADDRESSAS
;
;STORE I/O JUMPS TO ADDRESSES POINTED TO BY CONTENTS OF
;H,L -- SYSIO, OR IF ENTERD IN LINE, ONE OF THE OTHER
;I/O DRIVERS
;
LE15A:	CALL	LODM		;GET THE 4 BYTES OF 2 ADDRESSES
	LXI	H,IN8		;POINT TO THE I/O JUMPS
	MVI	M,0C3H		;STORE JUMP INST.
	INX	H		;POINT TO NEXT BYTE
	MOV	M,B		;STORE IT
	INX	H		;2ND BYTE
	MOV	M,C		;STORE IT
	INX	H		;NOW 1ST BYTE FOR OUTPUT
	MVI	M,0C3H		;STORE JUMP INST
	INX	H		;POINT TO ADDR 1ST BYTE
	MOV	M,D		;STORE IT
	INX	H		;POINT 2ND BYTE
	MOV	M,E		;STORE IT
	XRA	A		;A ZERO
	STA	IOSWC		;RESET SWITCH TO NO-SWITCH MODE
	RET			;DONE
;
;THE FOLLOWING ROUTINE READS A COMMAND LINE FROM THE
;TERMINAL AND PUTS IT IN THE OUTPUT BUFFER
;
READ:	LXI	H,IBUF		;GET INPUT BUFFER ADDR
	SHLD	ADDS		;SAVE ADDRESS
	MVI	E,2		;INIT. CHAR COUNT
NEXT:	CALL	IN8		;READ A LINE
	CPI	'X'-40H		;CHECK FOR CNTL X
	JNZ	CR		;CHECK FOR C/R IF NOT CNTL X
	CALL	CRLF		;ELSE DO CRLF
	JMP	READ		;AND START OVER
CR:	CPI	0DH		;IS IT A C/R ?
	JNZ	DEL		;IF NOT, CHECK FOR CHAR DELETE
	MOV	A,L		;GET LOW ORDER BYTE OF ADDR
	CPI	IBUF AND 0FFH	;SEE IF CR IS ONLY CHAR ON LINE
	JZ	READ		;GET ANOTHER LINE IF SO
	MOV	M,B		;PUT CHAR IN THE LINE
	INX	H		;POINT TO NEXT POSITION
	MVI	M,1		;PUT END OF LINE INDICATOR
	INX	H		;POINT 1 AFTER THE LINE
	CALL	LF3DF		;GET TERMW+1 IN A
	INR	A		;INCREMENT IT FOR EOF MARK
	CALL	CLER		;CLEAR REST OF THE BUFFER
	LXI	H,IBUF-1	;POINT TO CHAR COUNT
	MOV	A,E		;PUT IT BEFORE THE LINE
	STA	CCNT		;AND SAVE AS CHAR COUNT
	RET			;DONE
DEL:	CPI	7FH		;IS THE CHAR A DELETE ?
	JNZ	CHAR		;IF NOT, PUT IT IN LINE
	MVI	A,IBUF AND 0FFH	;ELSE GET LOW-ORDER ADDR
	CMP	L		;MAKE SURE NOT AT IBUF
	JZ	NEXT		;IF SO, IGNORE DELETE
	DCX	H		;ELSE DCR BUFFER POINTER
	DCR	E		;AND CHAR COUNT
BSPA:	MVI	B,5FH		;GET BACKSPACE CHAR
	CALL	OUT8		;MAKE TERMINAL BKSPACE
	JMP	NEXT		;THEN GET NEXT CHAR
CHAR:	CALL	OUT8		;ECHO THE CHAR
	CPI	' '		;MAKE SURE IT'S PRINTABLE
	JC	NEXT		;SKIP IT IF IT'S CNTL CHAR
	MOV	M,A		;ELSE PUT IT IN THE BUFFER
	LDA	TERMW		;GET TERMINAL WIDTH
	CMP	L		;SEE IF WE'RE THERE
	JZ	BSPA		;BACKSPACE IF BUFFER OVERFLOW
	INX	H		;ELSE INCREMENT THE BUFFER PNTR
	INR	E		;AND THE CHAR COUNT
	JMP	NEXT		;THEN DO NEXT CHAR
;
;THIS ROUTINE IS USED TO BLANK OUT A PORTION OF MEMORY
;SINCE ONLY L IS TESTED, AREA MUST BE < 256 BYTES
;
CLER:	CMP	L		;SEE IF AT END OF AREA TO BLANK
	RZ			;DONE IF SO
	MVI	M,' '		;ELSE GET A SPACE
	INX	H		;INCREMENT THE MEMORY POINTER
	JMP	CLER		;AND TEST NEW ADDRESS
;
;HERE ARE THE BUILT IN I/O DRIVERS AND THEIR NAME
;THIS CODE IS MOVED INTO THE DATA PORTION DURING
;PROGRAM INITIALIZATION.
;PART OF THE ENTER COMMAND IS ALSO MOVED, FOR NO REASON.
;
IONME:	DB	'SYSIO'		;STANDARD DRIVER NAME
	DW	INDR		;INPUT ROUTINE ADDR
	DW	OUTDR		;OUTPUT ROUTINE ADDR
INP8:	CALL	STAT		;BECOMES INDR: AFTER THE MOVE
	JZ	INDR
	IN	UDATA
	ANI	7FH
	MOV	B,A
	RET
	IN	USTA		;THIS BECOMES STAT:
	ANI	DAV
	RET
OUTP8:	CALL	STAT
	JZ	NOCHR
	IN	UDATA		;NOTE THAT BEFORE EA. OUTPUT
	ANI	7FH
	CPI	ESC		;ALS8 TESTS FOR AN ESC. CHAR
	JZ	EORMS		;AND RETNS TO CMD MODE IF FOUND
	IN	USTA		;BECOMES NOCHR:
	ANI	TBE
	JZ	NOCHR
	MOV	A,B
	OUT	UDATA
	RET
;
;THE ENTER COMMAND.
;
ENTR:	CALL	VCHK		;MAKE SURE PARAMETERS GIVEN
	CALL	ENTS		;TO DO THE ENTER FUNCTION
	JC	WHAT		;IF ERROR FOUND
;
;CRLF UTILITY
;
CRLF:	MVI	B,0DH		;CAR. RETURN
	CALL	OUT8
LF:	MVI	B,0AH		;LINE FEED
	CALL	OUT8
	MVI	B,7FH		;NULLS FOR SLOW TERMINALS
	CALL	OUT8
	JMP	OUT8		;LET OUT8 DO THE RETURN
;
;TABLE SEARCH ROUTINE USED FOR BOTH COMMAND SEARCHES AND
;SYMBOL LOOK-UPS.  ZERO FLAG SET IF MATCH FOUND, IN WHICH
;CASE H,L HAS VALUE OF STRING (16 BIT).
;LENGTH OF STRING IS IN B, TABLE ADDRESS IS IN
;D,E, ADDS POINTS TO ITEM TO BE LOOKED UP.
;IF NO MATCH, D,E POINT TO BYTE AFTER TABLE END.
;
COMS:	LHLD	ADDS		;GET ADDR OF ITEM TO LOOK UP
	MOV	C,B		;LENGTH OF ITEM TO LOOK UP
	LDAX	D		;1ST BYTE OF NEXT TABLE ENTRY
	ORA	A		;IF ZERO, ==> END OF TABLE
	JZ	LE23E		;TO SET RET FLAG FOR NO MATCH
	CALL	SEAR		;SEE IF ENTRY MATCHES STRING
	LDAX	D		;GET 1ST BYTE OF VALUE
	MOV	H,A		;MOVING TO H,L
	INX	D		;INCREMENT POINTER
	LDAX	D		;GET 2ND BYTE OF VALUE
	MOV	L,A		;MOVE TO H,L COMPLETE
	RZ			;RET IF SEAR INDICATED MATCH
	INX	D		;ELSE POINT TO NEXT TABLE ITEM
	JMP	COMS		;AND TEST IT
LE23E:	INR	A		;MAKE NON ZERO
	RET			;INDICATING NO MATCH
;
;THE FOLLOWING ROUTINE IS THE SAME AS COMS, ABOVE, EXCEPT
;THAT IT IS USED TO SEARCH THE CUSTOM COMMAND TABLE, WHICH
;CONSISTS OF 5 CHAR NAMES WITH ONLY 1ST FOUR TESTED.
;BECAUSE OF THIS IT HAS AN EXTRA INX D INSTR.
;
LE240:	LHLD	ADDS		;GET ADDR OF ITEM TO LOOK UP
	MOV	C,B		;LENGTH OF ITEM TO LOOK UP
	LDAX	D		;1ST BYTE OF TABLE ENTRY
	ORA	A		;IF ZERO ==> END OF TABLE
	JZ	LE23E		;TO SET RET FLAG FOR NO MATCH
	CALL	SEAR		;SEE IF ENTRY MATCHES STRING
	INX	D		;SKIP 5TH CHAR OF ENTRY NAME
	LDAX	D		;GET 1ST BYTE OF VALUE
	MOV	H,A		;MOVING TO H,L
	INX	D		;POINT TO 2ND BYTE OF VALUE
	LDAX	D		;GET 2ND BYTE OF VALUE
	MOV	L,A		;MOVE TO H,L COMPLETE
	RZ			;RET IF SEAR INDICATED MATCH
	INX	D		;POINT TO NEXT ENTRY
	JMP	LE240		;TEST IT
;
;ROUTINE TO SEE IF TWO STRINGS ARE EQUAL.  STRINGS POINTED
;TO BY D,E AND H,L.  ZERO FLAG SET INDICATES MATCH.  REG C
;HAS LENGTH OF MASTER STRING.  D POINT AFTER ITS STRING
;EVEN IF NO MATCH; H,L POINTS AFTER IT'S STRING IF MATCH,
;ELSE TO 1ST NON-MATCHING CHAR.
;
SEAR:	LDAX	D		;GET A CHAR FROM 1 STRING
	CMP	M		;COMPARE TO OTHER STRING
	JNZ	INCA		;IF IT DOESN'T MATCH
	INX	H		;INCREMENT POINTER
	INX	D		;INCREMENT POINTER
	DCR	C		;COUNT OF CHARS LEFT TO CHECK
	JNZ	SEAR		;IF CHARS LEFT, TEST THEM
	RET			;ELSE DONE
INCA:	INX	D		;INCREMENT POINTER
	DCR	C		;DECREMENT COUNT
	JNZ	INCA		;KEEP INR. POINTER IF NOT DONE
	INR	C		;ELSE CLEAR ZERO FLAG
	RET			;AND RETURN
;
;ROUTINE TO ZERO OUT A BUFFER IN MEMORY
;
ZBUF:	XRA	A		;GET A ZERO
	LXI	D,ABUF+16	;POINT TO THE BUFFER
	MVI	B,16		;BUFFER LENGTH
ZBU1:	DCX	D		;DECREMENT POINTER
	STAX	D		;ZERO OUT A LOCATION
	DCR	B		;DECREMENT COUNT
	JNZ	ZBU1		;IF MORE LEFT TO ZERO
	RET			;DONE
;
;THE EXECUTE COMMAND - DOES A CALL TO A SPECIFIED ADDR.
;
EXEC:	CALL	VCHK		;CHECK FOR PROPER ARGUMENT
	CALL	CRLF		;DO CRLF
	LHLD	BBUF		;GET EXEC ADDR
	PCHL			;GO TO IT
;
;ROUTINE TO EXTRACT VALUES FROM A COMMAND LINE
;AND PLACE THEM IN BUFFERS
;
ETRA:	LXI	H,0		;GET A ZERO
	SHLD	BBUF+2		;ASSUME NO 2ND OPERAND
	SHLD	FBUF		;ASSUME NO FILE NAME IN /'S
	CALL	ZBUF		;ZERO OUT ABUF
	LXI	H,IBUF-1	;SET TO SCAN COMMAND LINE
VAL1:	INX	H		;POINT TO NEXT CHAR
	MOV	A,M		;GET CHAR
	CPI	' '		;SPACE ?
	CMC			;SET CARRY TO INDICATE CNTL CHR
	RNC			;DONE-CR ONLY CNTL CHR ALLOWED
	JNZ	VAL1		;IF CHAR WAS NOT A SPACE
	SHLD	PNTR		;ELSE SPACE, SAVE POINTER
	CALL	SBLK		;AND SCAN TO 1ST CHAR
	CMC			;CARRY SET ==> C/R 1ST CHAR
	RNC			;DONE THEN
	CPI	'/'		;FILE NAME DELIMITER ?
	JNZ	VAL5		;NO, LOOK FOR OTHER PARAMETERS
	LXI	D,FBUF		;YES, POINT TO FILE NAME BUFFER
	MVI	C,NMLEN		;FILE NAME LENGTH
VAL2:	INX	H		;MOVING NAME TO FILE NAME BUFR
	MOV	A,M		;GET A CHAR
	CPI	'/'		;TERMINATING SLASH ?
	JZ	VAL3		;DONE MOVING NAME THEN
	DCR	C		;ELSE DCR COUNT OF CHARS LEFT
	JM	WHAT		;IF NAME > 5 CHARS
	STAX	D		;ELSE PUT LETTER IN BUFFER
	INX	D		;INCREMENT DEST. POINTER
	JMP	VAL2		;AND DO NEXT CHARACTER
VAL3:	MVI	A,' '		;GET A SPACE
VAL4:	DCR	C		;DECREMENT COUNT OF CHARS LEFT
	JM	DONE		;IF NEGATIVE, DONE
	STAX	D		;PAD REST OF BUFR WITH SPACES
	INX	D		;INCREMENT BUFFER POINTER
	JMP	VAL4		;CONTINUE TILL BUFFER FILLED
DONE:	CALL	SBL2		;SCAN TO NEXT NON-SPACE CHAR
	CMC			;CARRY MEANS CHAR. RETRN FOUND
	RNC			;AND CAR. RETRN = DONE
VAL5:	LXI	D,ABUF		;POINT TO THE ASCII BUFFER
	CALL	LE2D7		;PUT IN ABUF & CNVRT BY MODE
	RC			;IF C/R WAS TERMINATING CHAR
	CALL	SBLK		;ELSE SCAN TO 2ND ASCII PARM.
	CMC			;TEST FOR C/R FOUND
	RNC			;RET., ELSE FALL THRU TO DO 2ND
LE2D7:	CALL	ALPS		;PUT PARM. IN ABUF
	MOV	A,E		;GET ENDING ADDR LOW BYTE
	SUB	B		;SUBTRACTING PARM LENGTH
	MOV	L,A		;TO GET BACK TO START
	MOV	A,D		;NOW HIGH ORDER BYTE
	SBI	0		;IN CASE OF BORROW
	MOV	H,A		;H,L HAS START OF PARM IN ABUF
	LDA	SMODE		;GET NUMERIC MODE
	ADD	A		;MULT. BY 2
	ADI	4		;AND ADD 4
	CMP	B		;TEST FOR NO. OF DIGITS ALLOWED
	RC			;# DIGITS > 4 AND HEX MODE
	CALL	NORM		;NORMALIZE ASCII NUMBER
	XCHG			;START OF SUB-BUFFER TO D,E
	LXI	H,7		;LENGTH OF SUB-BUFFERS IN ABUF
	DAD	D		;H,L POINT TO NEXT SUB-BUFFER
	XCHG			;NEXT SUB-BUFFER IN D,E
	RET			;DONE
;
;SOME NUMERICAL CONVERSION ROUTINES FOLLOW.
;B,C POINT TO 1ST ASCII DIGIT, NUMERIC STRING ENDS WITH 
;BINARY ZERO.  ANSWER IN H,L AND CARRY SET = ERROR.
;
;EMODE CONVERTS BASED ON CURRENT MODE SETTING, SMODE
;EQUAL TO 0 FOR HEX, 1 FOR OCTAL.
;
EMODE:	LDA	SMODE		;GET MODE SETTING
	ORA	A		;SET FLAGS
	JNZ	AOCT		;OCTAL IS 1
AHEX:	LXI	H,0		;START WITH A ZERO
AHE1:	LDAX	B		;GET A DIGIT
	ORA	A		;SEE IF ZERO
	RZ			;YES - DONE
	DAD	H		;MULT H,L BY TWO
	DAD	H		;AGAIN - NOW 4X ORIG VALUE
	DAD	H		;AGAIN - NOW 8X ORIG VALUE
	DAD	H		;AGAIN - NOW 10H X ORIG VALU
	CALL	AHS1		;CONVERT DIGIT TO BINARY
	CPI	10H		;SEE IF LEGAL
	CMC			;SET CARRY FLAG
	RC			;FOR PROPER ILLEAGLE RETURN
	ADD	L		;OTHERWISE ADD IT INTO THE NO.
	MOV	L,A		;AND RESTORE TO H,L
	INX	B		;NOW POINT TO NEXT ASCII DIGIT
	JMP	AHE1		;AND PROCESS IT
;
;ROUTINE TO CONVERT ASCII HEX DIGIT INTO BINARY
;
AHS1:	SUI	30H		;CONVERT 0-9 TO BINARY
	CPI	0AH		;SEE IF > ASCII 9
	RC			;RETURN IF NOT, DONE
	SUI	7		;TO TAKE CARE OF A-F
	CPI	0AH		;COMPARE TO DECIMAL 10
	RNC			;IF > 10 OR =, RETURN DONE
	MVI	A,0FFH		;ELSE BAD CHAR, SET A > 10H
	RET			;AND RETURN
;
;HERE IS A ROUTINE TO CONVERT BOTH OF TWO POSSIBLE
;VALUES IN ABUF INTO BINARY BASED ON THE CURRENT MODE
;SETTING, AND PLACE THEM INTO BBUF AND BBUF+2
;
LE31E:	LXI	B,ABUF		;POINT TO THE 1ST OPERAND
	CALL	EMODE		;CONVERT IT
	RC			;RETURN W/CARRY SET ON ERROR
	SHLD	BBUF		;PUT VALUE IN BBUF
	LXI	B,ABUF+7	;POINT TO 2ND VALUE
	CALL	EMODE		;CONVERT IT
	RC			;RETURN W/CARRY SET ON ERROR
	SHLD	BBUF+2		;PUT IT IN THE BINARY BUFFER
	RET			;DONE
;
;OCTAL TO BINARY CONVERSION
;
AOCT:	LXI	H,0		;START W/ZERO
LE336:	LDAX	B		;GET A CHAR
	ORA	A		;ZERO ?
	RZ			;DONE THEN, RETURN
	DAD	H		;MULT H,L BY TWO
	DAD	H		;AGAIN - NOW 4X ORIG VALU
	DAD	H		;AGAIN - NOW 8X ORIG VALU
	SUI	30H		;CONVERT ASCII DIGIT TO BINARY
	CPI	8		;LEGAL VALUE ?
	CMC			;SET CARRY FOR PROPER RETURN
	RC			;RETURN IF BAD
	ADD	L		;ELSE ADD IN VALUE
	MOV	L,A		;AND PUT IT BACK
	INX	B		;POINT TO NEXT ASCII DIGIT
	JMP	LE336		;AND PROCESS IT
;
;DECIMAL OUTPUT ROUTINE FOR BINARY NO. IN REG A.
;
DOUT:	CALL	BIND		;CONVRT A TO DECIMAL IN ADDS
LE34B:	CALL	LE57A		;PRINT 1ST TWO CHARS IN ADDS
	INX	H		;POINT TO 3RD CHAR IN ADDS
	MOV	B,M		;GET IT
	JMP	OUT8		;PRINT IT AND RETURN
;
;OCTAL OUTPUT ROUTINE
;
OOUT:	CALL	BINO		;CONVERT TO OCTAL IN ADDS
	JMP	LE34B		;PUT OUT 3 OCTAL DIGITS AND RET
;
;OCTAL FOLLOWED BY SPACE
;
OOTB:	CALL	OOUT		;PUT OUT OCTAL NO.
LE35C:	MVI	B,' '		;GET A SPACE
	JMP	OUT8		;PUT IT OUT
;
;OUTPUT NUMBER OF SPACES IN REG C
;
BLKO:	CALL	LE35C		;PUT OUT A SPACE
	DCR	C		;DECREMENT COUNT
	JNZ	BLKO		;PUT OUT MORE IF NOT DONE
	RET			;ELSE RETURN
;
;COMPARE THE ADDRESSES AT BBUF AND BBUF+2
;INCREMENT THE ADDR AT BBUF AND RET CARRY SET IF SAME
;USED BY DUMP COMMAND TO TEST FOR END
;
ACHK:	LHLD	BBUF		;GET 1ST ADDRESS
	LDA	BBUF+3		;GET HIGH BYTE OF 2ND ADDR
	CMP	H		;COMPARE HIGH ORDER BYTES
	JNZ	ACH1		;BBUF LOWER, INR IT & GO HOME
	LDA	BBUF+2		;GET 2ND ADDR LOW BYTE
	CMP	L		;COMPARE TWO ADDR.
	JNZ	ACH1		;BBUF LOWER, INR IT & GO HOME
	STC			;ADDR. ARE SAME, SET CARRY
ACH1:	INX	H		;INCREMENT BBUF ADDR
	SHLD	BBUF		;PUT IT BACK
	RET			;DONE
;
;PRINT CHARACTERS UNTIL A CAR. RET. FOUND
;
SCRN:	XRA	A		;BINARY ZERO
	STA	XOUT		;LAST CHAR OUTPUT
	MOV	B,M		;GET A CHARACTER
	MVI	A,0DH		;CAR. RETRN TO A.
	CMP	B		;CHAR IN B = C/R ?
	RZ			;YES - DONE
	CALL	OUT8		;NO - OUTPUT IT & MOV TO A
	INX	H		;INCREMENT POINTER
	JMP	SCRN+1		;UPDATE XOUT AND DO NEXT CHAR
;
;CONVERT BINARY TO HEX ASCII & STORE
;
BINH:	LXI	H,ADDS		;DESTINATION FOR ASCII
	MOV	B,A		;SAVE CHAR IN B
	RAR			;MOVING HIGH ORDER NIBBLE TO
	RAR			;LOW ORDER NIBBLE
	RAR	
	RAR	
	CALL	BIN1		;CONVERT TO LETTER OR NO.
	MOV	M,A		;STORE IT
	INX	H		;INCREMENT DEST. POINTER
	MOV	A,B		;GET BACK ORIG NO.
	CALL	BIN1		;CONVERT LOW ORDER NIBBLE TO NO
	MOV	M,A		;PUT IT IN MEMORY
	RET			;DONE
;
;CONVERT LOW ORDER NIBBLE OF A TO HEX ASCII
;
BIN1:	ANI	0FH		;MASK LOW NIBBLE
	ADI	30H		;CONVERT TO NO.
	CPI	'9'+1		;SEE IF > 9
	RC			;IT WASN'T -- DONE
	ADI	7		;ADD 7 TO GET LETTER
	RET			;DONE
;
;BINARY TO DECIMAL
;
BIND:	LXI	H,ADDS		;POINT TO DESTINATION
	MVI	B,100		;DOING SUCCESSIVE SUBTRACTIONS
	CALL	BID1		;SUBTRACT & KEEP COUNT
	MVI	B,10		;NOW WORK WITH TENS
	CALL	BID1		;MORE SUBTRACTIONS
	ADI	30H		;CONVERT UNITS TO DECIMAL ASCII
	MOV	M,A		;STORE UNITS DIGIT IN MEMORY
	RET			;DONE
BID1:	MVI	M,'0'-1
	INR	M		;INCR COUNT OF SUBTRACTIONS
	SUB	B		;DO A SUBTRACTION
	JNC	BID1+2		;DO IT AGAIN IF ANS > 0
	ADD	B		;IF ANS < 0, UN-SUBTRACT
	INX	H		;INCREMENT DEST. POINTER
	RET			;DIGIT STORED
;
;BINARY TO OCTAL
;
;NOTE THAT THE CARRY IS USED, SO THE MAX SINGLE BYTE OCTAL
;VALUE THAT CAN BE HANDLED IS 777 NOT 377.  THIS FEATURE IS
;USED IN THE DUMP ROUTINE.
;
BINO:	LXI	H,ADDS		;GET DEST. POINTER
	MOV	B,A		;SAVE ORIG NO. IN B
	RAL			;HIGH ORDER BITS & CARRY
	RAL			;MOVING TO LOW ORDER 3 BITS
	RAL			;
	ANI	7		;MASK TO 3 BITS
	ADI	30H		;CONVERT TO ASCII
	MOV	M,A		;STORE IN MEMORY
	MOV	A,B		;GET ORIG. NO.
	RAR			;MOVE MIDDLE 3 BITS
	RAR			;TO LOW ORDER 3 BITS
	RAR	
	ANI	7		;AND MASK THEM OUT
	ADI	30H		;CONVERT TO ASCII
	INX	H		;INCREMENT MEMORY POINTER
	MOV	M,A		;AND PUT DIGIT IN MEMORY
	MOV	A,B		;GET ORIGINAL DIGIT AGAIN
	ANI	7		;MASK TO LOW ORDER 3 BITS
	ADI	30H		;CONVERT TO ASCII
	INX	H		;INCREMENT MEMORY POINTER
	MOV	M,A		;AND STORE IN MEMORY
	RET			;DONE
;
;HERE IS THE ALS-8 COMMAND TABLE
;
CTAB:	DB	'LIST'
	DB	(LIST SHR 8) AND 0FFH, LIST AND 0FFH
	DB	'TEXT'
	DB	(TEXT SHR 8) AND 0FFH, TEXT AND 0FFH
	DB	'DELT'
	DB	(DELT SHR 8) AND 0FFH, DELT AND 0FFH
	DB	'MODE'
	DB	(MODE SHR 8) AND 0FFH, MODE AND 0FFH
	DB	'FCHK'
	DB	(FCHK SHR 8) AND 0FFH, FCHK AND 0FFH
	DB	'FORM'
	DB	(FORM SHR 8) AND 0FFH, FORM AND 0FFH
	DB	'NFOR'
	DB	(NFOR SHR 8) AND 0FFH, NFOR AND 0FFH
	DB	'SWCH'
	DB	(EORNS SHR 8) AND 0FFH, EORNS AND 0FFH
	DB	'SIMU'
	DB	(SIMU SHR 8) AND 0FFH, SIMU AND 0FFH
	DB	0
	DB	'DUMP'
	DB	(DUMP SHR 8) AND 0FFH, DUMP AND 0FFH
	DB	'EXEC'
	DB	(EXEC SHR 8) AND 0FFH, EXEC AND 0FFH
	DB	'ENTR'
	DB	(ENTR SHR 8) AND 0FFH, ENTR AND 0FFH
	DB	'FILE'
	DB	(FILE SHR 8) AND 0FFH, FILE AND 0FFH
	DB	'ASSM'
	DB	(ASSM SHR 8) AND 0FFH, ASSM AND 0FFH
	DB	'ASSI'
	DB	(ASSM SHR 8) AND 0FFH, ASSM AND 0FFH
	DB	'IODR'
	DB	(IODR SHR 8) AND 0FFH, IODR AND 0FFH
	DB	'STAB'
	DB	(STAB SHR 8) AND 0FFH, STAB AND 0FFH
	DB	'SYML'
	DB	(SYML SHR 8) AND 0FFH, SYML AND 0FFH
	DB	'CUST'
	DB	(CUST SHR 8) AND 0FFH, CUST AND 0FFH
	DB	'RNUM'
	DB	(RNUM SHR 8) AND 0FFH, RNUM AND 0FFH
	DB	'FMOV'
	DB	(FMOV SHR 8) AND 0FFH, FMOV AND 0FFH
	DB	'EDIT'
	DB	(TXT2 SHR 8) AND 0FFH, TXT2 AND 0FFH
	DB	'AUTO'
	DB	(AUTO SHR 8) AND 0FFH, AUTO AND 0FFH
	DB	'FIND'
	DB	(FIND2 SHR 8) AND 0FFH, FIND2 AND 0FFH
	DB	'TERM'
	DB	(TERM SHR 8) AND 0FFH, TERM AND 0FFH
	DB	0
;
;SYSTEM SYMBOL TABLE ROUTINES
;
SYML:	LXI	H,IBUF+4	;POINT TO FIFTH CHAR
	MOV	A,M		;GET IT
	CPI	'E'		;SYMLE - ENTER INTO TABLE ?
	JZ	LE4AB		;YES - MAKE AN ENTRY
	CPI	'D'		;SYMLD - DELETE FROM TABLE ?
	JZ	LE4B4		;YES - DELETE IT THEN
;
;PRINT CONTENTS OF SYSTEM SYMBOL TABLE
;
	LXI	H,SYSYM		;POINT TO SYSTEM SYMBOL TABLE
LE48F:	MVI	A,4		;PRINT 4 ACROSS
	STA	CCNT		;SAVE AS COUNT
	CALL	CRLF		;START ON NEW LINE
LE497:	MOV	A,M		;GET 1ST CHAR
	ORA	A		;END OF TABLE ?
	JZ	LE4EE		;THEN PRINT END ADDRESS
	CALL	LEEA8		;PRINT 1 SYMBOL & VALUE
	INX	D		;POINT TO NEXT SYMBOL
	LXI	H,CCNT		;POINT AT COUNT
	DCR	M		;DCR NO LEFT THIS LINE
	XCHG			;TABLE POINTER TO H,L
	JNZ	LE497		;PRINT MORE THIS LINE
	JMP	LE48F		;OR START NEW LINE
;
;ENTER NEW SYMBOL INTO TABLE
;
LE4AB:	CALL	VCHK		;CHECK FOR VALID VALUE & NAME
LE4AE:	CALL	LE4CE		;VALIDATE NAME & MOVE TO ABUF
	JMP	LECE2		;PUT SYMBOL INTO TABLE
;
;DELETE SYMBOL
;
LE4B4:	CALL	LE4AE		;H,L POINTS TO VALUE ON RET
LE4B7:	INX	H		;POINT TO 2ND CHAR OF VALUE
	INX	H		;POINT TO NEXT SYMBOL
	XCHG			;D,E POINT AT SYM. AFTR DELETED
	LXI	H,-(NMLEN+2)	;SYMBOL TABLE ENTRY LENGTH
	DAD	D		;H,L POINTS AT BEG. OF ENTRY
	LDAX	D		;GET CHAR FROM TABLE ENTRY
LE4BF:	ORA	A		;SET FLAGS
	MVI	B,(NMLEN+2)	;ENTRY LENGTH
LE4C2:	MOV	M,A		;MOVE CHAR UP IN TABLE
	RZ			;IF END OF TABLE MOVED
	INX	H		;INR DEST. POINTER
	INX	D		;INR SOURCE POINTER
	LDAX	D		;GET NEXT CHAR FROM SYMBOL
	DCR	B		;COUNT OF CHRS THIS SYMBOL
	JNZ	LE4C2		;IF NOT DONE THIS SYMBOL
	JMP	LE4BF		;TO MOVE NEXT SYMBOL UP
;
;ROUTINE TO VALIDATE A SYMBOL NAME & MOVE IT TO ABUF
;
LE4CE:	CALL	ZBUF		;BLANK OUT ABUF
	XCHG			;H,L POINT TO START OF ABUF
	SHLD	ADDS		;SAVE ADDRESS
	LXI	D,FBUF		;POINT AT FILE-NAME BUFFER
	XCHG			;H,L=FBUF & D,E=ABUF
	XRA	A		;GET A ZERO
	STA	FREAD		;SAVE AS 1ST FREE ADDRESS
	MOV	A,M		;GET 1ST CHAR OF NAME
	ORA	A		;ZERO ?
	JZ	WHAT		;ERROR IF NO NAME GIVEN
	CALL	LF154		;MOVE THE NAME IF IT'S VALID
	CPI	21H		;MAKE SURE SPACE FOLLOWS NAME
	JNC	WHAT		;ERROR IF SPACE DOESN'T FOLLOW
	LHLD	BBUF		;GET VALUE
	RET			;RETURN W/VALUE IN H,L
;
;DO A CR/LF AND PRINT ASCII CONTENTS OF ADDR POINTED TO BY H,L
;
LE4EE:	XCHG			;POINTER FROM D,E TO H,L
	CALL	CRLF		;START ON NEW LINE
	JMP	ADOUT		;PRINT ADDR POINTED TO BY H,L
;
;CUSTOM COMMAND TABLE MANAGEMENT
;
CUST:	LXI	H,IBUF+4	;POINT AT 5TH CHAR
	MOV	A,M		;GET IT
	CPI	'E'		;ENTER NEW CUST. COMMAND ?
	JZ	LE509		;YES - DO IT
	CPI	'D'		;DELETE CUSTOM COMMAND ?
	JZ	LE004		;YES - DO IT
	LXI	H,CUCOM		;POINT AT CUSTOM COMMAND TABLE
	JMP	LE48F		;PRINT USING SYML ROUTINES
;
;ENTER AND DELETE MOSTLY USE SYMLE & SYMLD CODE
;
LE509:	CALL	VCHK		;MAKE SURE VALUE GIVEN
LE50C:	CALL	LE4CE		;VALIDATE NAME & MOVE TO ABUF
	LXI	D,CUCOM		;D,E POINT AT CUST. TABLE
	JMP	LECE5		;PUT VALUE INTO TABLE
;
;ROUTINE TO EXTRACT VALUES FROM COMMAND LINE & REPORT AN 
ERROR
;
VALC:	CALL	ETRA		;ETRA DOES THE REAL WORK
	JC	WHAT		;IF AN ERROR OCCURED
	RET			;DONE, NO ERROR
;
;ROUTINE TO VERIFY THAT REQUIRED PARAMETERS WERE ENTERED
;
VCHK:	LDA	ABUF		;GET 1ST CHAR OF ABUF
	ORA	A		;ZERO ?
	JZ	WHAT		;ERROR - REQD. PARM. OMITTED
	RET			;DONE
;
;THE DUMP COMMAND
;
DUMP:	CALL	VCHK		;MAKE SURE ADDRESS GIVEN
	MVI	A,16		;16 VALUES PER LINE
	STA	CCNT		;SAVE AS COUNT
LE52C:	CALL	CRLF		;START NEW LINE
	LHLD	BBUF		;GET ADDRESS
	XCHG			;DO D,E
	CALL	ADOUT		;PRINT ADDRESS ON LEFT OF LINE
	MVI	B,':'		;FOLLOW ADDRESS WITH COLON
	CALL	OUT8		;PRINT IT
	CALL	LE35C		;PUT OUT A SPACE
	LDA	CCNT		;GET COUNT OF ADDRS/LINE
LE541:	STA	DCNT		;SAVE AS DUMP COUNT
	LHLD	BBUF		;GET ADDR TO DUMP
	MOV	A,M		;GET DATA AT THAT ADDR
	CALL	DUMO		;PRINT ITS VALUE
	CALL	LE35C		;PUT A SPACE OUT
	CALL	ACHK		;COMPARE BBUF & BBUF+2
	RC			;REACHED END ADDRS. - DONE
	LDA	DCNT		;ELSE GET DUMP COUNT
	DCR	A		;DCR COUNT BYTES LEFT THIS LINE
	JNZ	LE541		;DO MORE BYTES ON THIS LINE
	JMP	LE52C		;DO ANOTHER LINE
;
;ROUTINE TO PUT OUT AN ADDRESS
;
;NOTE THAT THIS ROUTINE TAKES ADVANTAGE (?) OF THE FACT THAT
;BINO USES THE CARRY BIT TO OUTPUT A SINGLE BYTE IN A AS
;XXX WHERE XXX MAY BE 777 (INCLUDING CARRY) AND IS NOT
;LIMITED TO 377.  ADDRESSES THUS COME OUT AS A SINGLE 16 BIT
;NUMBER RATHER THAN IN THE MORE COMMON "SPLIT OCTAL" 
CONSISTING
;OF TWO SEPERATE 8 BIT QUANTITIES WITH A MAX VALUE OF 377 EACH.
;
ADOUT:	LDA	SMODE		;GET CURRENT MODE
	ORA	A		;CLEAR CARRY & SET ZERO FLAG
	MOV	A,D		;HIGH ORDER BYTE TO A
	JZ	LE565		;SKIP NEXT PART IF BASE HEX
	RAR			;LOW ORDER BIT TO CARRY FOR OCT
LE565:	MOV	D,A		;RESTORE HIGH ORDER BYTE
	RAL			;SHIFT LEFT 1 BIT THRU ACCUM.
	MOV	C,A		;LOW BIT/CARRY IN C FOR OCTAL
	MOV	A,D		;GET HIGH ORDER BYTE
	CALL	DUMO		;OUTPUT USING CURRENT MODE
	MOV	A,C		;FOR OCTAL, GET ORIG HIGH BYTE
	RAR			;SET CARRY BIT
	MOV	A,E		;GET LOW ORDER BYTE
DUMO:	LXI	H,SMODE		;POINT TO MODE
	MOV	B,M		;GET IT
	DCR	B		;DECR (OCTAL MODE = 1)
	JZ	OOUT		;FOR OCTAL
HOUT:	CALL	BINH		;CONVERT BIN TO HEX IN ADDS
LE57A:	LXI	H,ADDS		;BUFFER WHERE CHARS STORED
	MOV	B,M		;GET CHAR IN B
	CALL	OUT8		;PRINT A HEX ASCII CHAR
	INX	H		;INX POINTER
	MOV	B,M		;GET NEXT CHAR
	JMP	OUT8		;PRINT IT & GO HOME
HOTB:	CALL	HOUT		;PUT OUT HEX
	JMP	LE35C		;PUT OUT SPACE & GO HOME
;
;MODE - USED TO SET THE OUTPUT MODE
;
MODE:	CALL	VCHK		;VERIFY PARAMETER GIVEN
	LXI	B,ABUF		;POINT TO PARAMETER
	CALL	AHEX		;CONVERT TO BINARY
	JC	WHAT		;IF PARAMETER INVALID
	MOV	A,H		;GET HIGH ORDER BYTE
	ORA	A		;SET FLAGS
	JNZ	WHAT		;PARM. MUST BE < 256
	MVI	B,0		;ASSUME HEX SPECIFIED
	MOV	A,L		;GET LOW ORDER PARMATER
	CPI	16H		;IS PARAMETER 16 ?
	JZ	LE5AB		;YES - STORE 0 AS MODE
	INR	B		;MAKE B = MODE = 1
	CPI	8		;IS PARAMETER 8 ?
	JNZ	WHAT		;MUST BE EITHER 8 OR 16
LE5AB:	MOV	A,B		;GET MODE (REG B)
	STA	SMODE		;MAKE IT THE MODE
	RET			;WE ARE DONE
;
;PROCESS THE FILE COMMANDS
;
FILE:	LDA	FBUF		;GET 1ST CHAR OF FILE NAME
	ORA	A		;SET FLAGS
	JZ	FOUT		;NO NAME GIVEN - DO A LISTING
	CALL	FSEA		;LOOK UP FILE
	XCHG			;D,E HAS ADDR OF DIR. ENTRY
	JNZ	TEST		;IF DIR. ENTRY FOUND
;
;ENTRY MATCHING FBUF NOT FOUND
;
	LDA	ABUF		;CHECK FOR PARAMETER GIVEN
	ORA	A		;SET FLAGS
	JZ	WHAT		;ADDR. REQUIRED FOR NEW FILE
;
;CHECK FOR ROOM TO ADD A NEW FILE
;
	LDA	FEF		;GET FREE ENTRY FOUND FLAG
	ORA	A		;SET FLAGS
	JNZ	ROOM1		;TO ADD THE NEW FILE
LE5CC:	LXI	H,EMES1		;POINT TO ERROR MESSAGE
	JMP	MESS		;PRINT IT
;
;ENTRY MATCHING FBUF FOUND
;
TEST:	LDA	ABUF		;SEE IF PARAMETER GIVEN
	ORA	A		;SET FLAGS
	JZ	SWAPS		;NO PARMS - MAKE IT CUR FILE
	LHLD	BBUF		;GET BINARY VALU OF PARM
	MOV	A,H		;HIGH ORDER BYTE
	ORA	L		;SEE IF PARM IS ZERO
	JZ	SWAPS		;TO DELETE THE FILE
LE5E1:	LXI	H,EMES2		;CAN'T RESPECIFY EXISTING FILE
	JMP	MESS		;TELL IT TO THE OPERATOR
;
;CREATE NEW FILE - NAME IS IN FBUF
;FREAD POINTS TO A FREE DIRECTORY ENTRY
;
ROOM1:	CALL	ROOM		;MOVE NAME IN FBUF TO 
DIRECTORY
;
;MAKE FILE POINTED TO BY D,E CURRENT
;
SWAPS:	LXI	H,FILE0		;POINT H,L TO CUR FILE
	MVI	C,FELEN		;BYTE COUNT
SWAP:	LDAX	D		;GET A BYTE FROM NEW CUR FILE
	MOV	B,M		;GET BYTE FROM CUR CUR FILE
	MOV	M,A		;NEW CUR FILE BYTE TO FILE 0
	MOV	A,B		;EXCHANGE
	STAX	D		;CUR CUR FILE BYTE TO FREAD
	INX	D		;INR NON-CURRENT FILE POINTER
	INX	H		;INR FILE 0 POINTER
	DCR	C		;COUNT OF BYTES TO MOVE
	JNZ	SWAP		;IF NOT DONE SWAPPING ENTRIES
;
;CHECK FOR 2ND PARAMETER (ADDRESS)
;
	LDA	ABUF		;GET 2ND PARAMETER 1ST CHAR
	ORA	A		;SET FLAGS
	JZ	FOUT		;NONE GIVEN
;
;PROCESS 2ND PARAMETER
;
	LHLD	BBUF		;GET 2ND PARAMETER ADDRESS
	SHLD	BOFP		;MAKE IT BEG OF FILE POINTER
	SHLD	EOFP		;AND END OF FILE POINTER
	MOV	A,L		;TEST FOR ADDR = 0
	ORA	H		;
	JZ	FIL35		;YES - DELETE IT
	MVI	M,1		;NO - PUT EOF MARK AT BOFP
FIL35:	XRA	A		;BINARY ZERO
	STA	MAXL		;AT MAX. LINE NO.
	JMP	FOOT		;OUTPUT PARAMETERS
;
;LIST 1 OR MORE FILES & THEIR PARAMETERS
;
FOUT:	CALL	CRLF		;DO A CR/LF
	LDA	IBUF+4		;GET OPT. 5TH CHAR
	CPI	'S'		;WAS COMMAND FILES ?
	MVI	C,MAXFIL	;MAX NO OF FILES
	JZ	FOUL		;YES - LIST ALL FILES
FOOT:	MVI	C,1		;ELSE LIST ONLY 1 FILE
;
;LIST PARMS. FOR NO OF FILES IN REG C.
;
FOUL:	LXI	H,FILE0		;POINT TO DIRECTORY
LE62A:	MOV	A,C		;GET NO FILES LEFT TO LIST
FINE:	STA	FOCNT		;SAVE AS FILE OUTPUT COUNT
	PUSH	H		;SAVE DIRECTORY POINTER
	LXI	D,NMLEN		;NAME LENGTH
	DAD	D		;POINT AT FILES BOFP
	MOV	A,M		;GET 1ST BYTE OF BOFP
	ORA	A		;ZERO ?
	JNZ	FOOD		;NO - LIST IT
	INX	H		;POINT AT 2ND BYTE OF BOFP
	ADD	M		;ADD TO 1ST BYTE
	INX	H		;POINT TO EOFP 1ST BYTE
	JNZ	FOOD		;BOFP NON ZERO - LIST IT
	INX	SP		;TO "UN-PUSH" H,L
	INX	SP		;
	INX	H		;POINT TO 2ND BYTE OF EOFP
	INX	H		;POINT TO MAXL
	JMP	FEET		;TO GO TO NEXT ENTRY
;
;HAVE A VALID ENTRY TO OUTPUT
;
FOOD:	POP	H		;GET POINTER TO FILES NAME
	CALL	CRLF		;START IT ON A FRESH LINE
	MVI	C,NMLEN		;LENGTH
FAST:	MOV	B,M		;GET A CHAR OF NAME
	CALL	OUT8		;PRINT IT
	DCR	C		;DECREMENT COUNT
	INX	H		;POINT TO NEXT CHAR
	JNZ	FAST		;PRINT REMAINING CHARS IF ANY
	CALL	LE666		;PRINT SPACE, BOFP, SPACE
	CALL	LE666		;PRINT SPACE, EOFP, SPACE
FEET:	LXI	D,FELEN-NMLEN-4	;LENGTH OF MAXL
	DAD	D		;POINT AT NEXT FILE ENTRY
	LDA	FOCNT		;PRINTING 1 OR ALL ?
	DCR	A		;DECR. COUNT
	JNZ	FINE		;TO PRINT MORE
	RET			;DONE
;
;ROUTINE TO PRINT AN ADDRESS
;
LE666:	CALL	LE35C		;PRINT SPACE
	MOV	E,M		;GET BYTE OF BOFP OR EOFP
	INX	H		;POINT TO 2ND BYTE
	MOV	D,M		;GET IT
	PUSH	H		;SAVE POINTER INTO FILE DIR.
	CALL	ADOUT		;PRINT ADDRESS
	CALL	LE35C		;AND TRAILING SPACE
	POP	H		;RESTORE POINTER
	INX	H		;POINT TO MAXL
	RET			;DONE
;
;MOVE FILE NAME TO BLOCK POINTED TO BY FREAD
;
ROOM:	LHLD	FREAD		;GET ADDR OF FREE ENTRY
	XCHG			;TO D,E
	LXI	H,FBUF		;ADDR OF NAME IN COMMAND
	PUSH	D		;SAVE DIRECTORY ADDR
	MVI	C,NMLEN		;NO CHARS TO MOVE
MOV23:	MOV	A,M		;GET CHAR FROM COMMAND
	STAX	D		;PUT INTO DIRECTORY
	INX	D		;INCR. DIR. POINTER
	DCR	C		;DCR CHAR COUNT
	INX	H		;INCR. FBUF POINTER
	JNZ	MOV23		;MOVE REMAINING CHARS
	POP	D		;RESTORE DIR. POINTER
	RET			;DONE
;
;FILE DIRECTORY SEARCH ROUTINE
;LOOK FOR ENTRY W/NAME IN FBUF - ZERO SET ==> NOT FOUND
;ELSE H,L POINT TO THE ENTRY
;ALSO, IF ENTRY FOUND W/BOFP ADDR = 0, SET FEF FLAG > 0
;AND FREAD TO THE ADDR OF THAT ENTRY
;
FSEA:	LXI	D,FILE0		;POINT TO DIRECTORY
LE68D:	XRA	A		;GET ZERO
	STA	FEF		;ASSUME NO FREE ENTRIES
	MVI	B,MAXFIL	;NO OF ENTRIES IN DIR.
FSE10:	LXI	H,FBUF		;ADDR OF NAME TO LOOK UP
	MVI	C,NMLEN		;NO CHARS PER NAME
	CALL	SEAR		;COMPARE CURRENT ENTRY TO FBUF
	PUSH	PSW		;SAVE RESULTS FLAG
	PUSH	D		;SAVE DIR POINTER
	LDAX	D		;GET BYTE OF BOFP ADDR
	ORA	A		;EMPTY ?
	JNZ	FSE20		;NO
	INX	D		;2ND BYTE
	LDAX	D		;GET IT
	ORA	A		;SET FLAGS
	JNZ	FSE20		;NOT ZERO
	XCHG			;DIR POINTER TO H,L
	LXI	D,-NMLEN-1	;
	DAD	D		;POINT BACK TO EMPTY ENTRY
	SHLD	FREAD		;AND SAVE IT'S ADDRESS
	MOV	A,D		;D HAPPENS TO BE NON-ZERO
	STA	FEF		;AND SO NOW IS FEF
	POP	H		;RESTORE DIR POINTER TO H,L
	POP	PSW		;RESTORE SEAR RESULTS FLAG
;
;MOVE TO NEXT ENTRY
;
FSE15:	LXI	D,FELEN-NMLEN
	DAD	D		;H,L POINTS TO NEXT ENTRY
	XCHG			;ENTRY ADDR TO D,E
	DCR	B		;COUNT OF FILES IN DIR
	RZ			;NO FILES LEFT TO SEARCH
	JMP	FSE10		;SEARCH REMAINING FILES
;
;ENTRY WASN'T FREE, LOOK AT SEAR RESULTS
;
FSE20:	POP	H		;RESTORE DIRECTORY POINTER
	POP	PSW		;SEAR RESULTS IN FLAG
	JNZ	FSE15		;IT DIDN'T MATCH ANYWAY
;
;MATCHING ENTRY FOUND WHICH WASN'T FREE
;
	LXI	D,-NMLEN
	DAD	D		;H,L POINT AT THE DIR. ENTRY
	MOV	A,D		;D IS NON-ZERO
	ORA	A		;SET FLAGS TO CLEAR ZERO FLAG
	RET			;DONE
;
;FORM COMMAND TO SET OUTPUT MODE
;
FORM:	CMA			;ALL COMNDS ARE EXEC WITH A=0
NFOR:	STA	LFMT		;
	JMP	EORMS		;IT'S THAT SIMPLE, FOLKS
;
;FCHK
;
FCHK:	LHLD	BOFP		;GET BEG. OF FILE PTR
	MOV	A,H		;SEE IF BOFP IS ZERO
	ORA	L		;WOULD IMPLY NO FILES
	JZ	LE5E1		;PRINT ERROR MESSAGE
	LXI	B,4		;LENGTH OF LINE NO.
	DAD	B		;H,L POINTS JUST PAST LINE NO
	INR	C		;C = 5 = LINE LEN TO THIS PT.
LE6E0:	INX	H		;POINT TO NEXT CHAR
	INR	C		;LINE LENGTH TO THIS POINT
	CALL	LE72B		;GET TERM WIDTH IN A
	CMP	C		;LINE > TERMINAL WIDTH ?
	JC	LE718		;YES - ERROR
	MOV	A,M		;GET LINE CHAR
	CPI	0DH		;END OF LINE ?
	JNZ	LE6E0		;KEEP TESTING THIS LINE
	LHLD	BOFP		;GET BEG. OF FILE PTR
	MOV	M,C		;MAKE LENGTH BYTE OK 1ST LINE
LE6F3:	MOV	A,M		;GET LENGTH BYTE
	CPI	1		;END OF FILE ?
	JZ	LE725		;TO RESET MAXL
	CPI	6		;MIN LINE LEN (NO. + LEN + CR)
	JC	LE718		;REPORT ERROR IF LINE TOO SHORT
	CALL	LE72B		;GET TERMINAL WIDTH IN A
	CMP	M		;COMPARE WITH LENGTH BYTE
	MOV	C,M		;LENGTH BYTE TO C
	DCR	C		;GOING TO COUNT CHARS IN LINE
LE704:	DCR	C		;COUNT OF ACUTAL CHARS LEFT
	INX	H		;POINT TO NEXT CHAR
	MOV	A,M		;GET IT
	JZ	LE712		;COUNT TO 0 - MUST BE C/R
	CPI	20H		;IS CHAR CNTL CHAR ?
	JC	LE718		;CNTL CHARS NOT ALLOWED
	JMP	LE704		;TEST NEXT CHAR IN LINE
LE712:	CPI	0DH		;IS CHAR C/R ?
	INX	H		;POINT TO NEXT CHAR
	JZ	LE6F3		;YES - GO ON, CHECK FOR EOF
;
;ERROR
;
LE718:	XCHG			;BAD ADDRESS TO D,E
	CALL	LE35C		;PRINT A SPACE
	CALL	ADOUT		;FOLLOWED BY THE BAD ADDRESS
	LXI	H,FERR		;POINT TO FILE ERROR MESSAGE
	JMP	MESS		;PRINT THE ERROR MESSAGE
LE725:	CALL	LEA50		;UPDATE MAXL
	JMP	FOUT		;PRINT FILE PARMS & RETURN
LE72B:	LDA	TERMW		;GET TERM WIDTH
	ADI	-(IBUF+1) AND 0FFH
	RET			;BINARY TERM WIDTH IN A
;
;FILE MOVE COMMANDS
;
FMOV:	CALL	VCHK		;CHECK FOR REQD PARMS
	LHLD	BOFP		;GET BEG OF FILE PTR
	XCHG			;BOFP TO D,E
	LHLD	BBUF		;GET DEST ADDR
	SHLD	BOFP		;NEW BEG OF FILE
	MOV	A,L		;LOW ORDER DEST TO A
	SUB	E		;SUBRACTING CUR BOF FROM NEW
	MOV	A,H		;TO SEE WHICH WAY TO MOVE
	SBB	D		;ANSWER NOW IN CARRY FLAG
	JC	LE760		;IF MOVING TO LOWER ADDR
;
;MOVING TO HIGHER ADDR
;
	LHLD	EOFP		;MOVING TO HIGHER ADDR
	MOV	A,L		;GOING TO SUBTRACT CUR (OLD)
	SUB	E		;BOFP FROM CUR EOFP & PUT
	MOV	C,A		;RESULT (FILE LENGTH) IN
	MOV	A,H		;REG B,C
	SBB	D		;
	MOV	B,A		;
	LHLD	BOFP		;GET DEST BEG OF FILE
	DAD	B		;ADD LENGTH = NEW END
	XCHG			;NEW END IN D,E
	MVI	M,2		;PUT 02H AT CUR BEG OF FILE
	MOV	C,M		;AND IN REG C
	LHLD	EOFP		;GET CUR END OF FILE TO H,L
	XCHG			;CUR EOF=D,E & NEW END H,L
	CALL 	RMOV		;DO THE MOVE
	JMP	LE765		;PUT 02H AT BOF AND FCHK
;
;MOVING LOWER IN MEMORY
;
LE760:	MVI	C,1		;LMOV WILL USE 01H AS END MARK
	CALL	LMOV		;DO THE MOVE
LE765:	MOV	M,C		;PUT TERMINATOR MARK IN FILE
	JMP	FCHK		;FCHK TO UPDATE 1ST L.B. & EOF
;
;RENUMBER COMMAND
;
RNUM:	CALL	VCHK		;CHECK FOR REQD. PARAMETERS
	LDA	ABUF+7		;SEE IF INCREMENT SPECIFIED
	MVI	B,5		;DEFAULT INCREMENT
	ORA	A		;SET FLAGS
	JZ	LE785		;NO INCREMENT GIVEN, USE 5
	LXI	B,ABUF+7	;POINT AT GIVEN INCREMENT
	CALL	ADEC		;CONVERT TO DECIMAL
	JC	WHAT		;IF ERROR
	MOV	A,L		;GET INCREMENT
	CPI	26		;MAXIMUM INCREMENT + 1
	JNC	WHAT		;IF INCREMENT > 25
	MOV	B,A		;INCREMENT IN B
LE785:	LHLD	BOFP		;GET BOF POINTER
	SHLD	APNT		;SAVE
LE78B:	MOV	A,M		;GET LENGTH BYTE
	CPI	1		;END OF FILE ?
	JZ	FCHK		;YES, DONE, DO FCHK
	INX	H		;POINT 1ST DIGIT
	LXI	D,ABUF		;STARTING LINE NO. SOURCE
	MVI	C,4		;LENGTH OF LINE NO.
LE797:	LDAX	D		;GET A DIGIT
	MOV	M,A		;PUT IT IN THE LINE
	INX	H		;POINT TO NEXT DIGIT
	INX	D		;IN SOURCE, TOO
	DCR	C		;COUNT OF DIGITS LEFT
	JNZ	LE797		;DO NEXT DIGITS
	LHLD	APNT		;GET POINTER TO LINE
	MOV	A,M		;GET LENGTH BYTE
	CALL	ADR		;POINT TO NEXT LINE
	SHLD	APNT		;UPDATE LINE POINTER
	DCX	H		;POINT TO LAST CHR OF PREV LINE
	MOV	A,M		;GET IT
	CPI	0DH		;IS IT A CARRIAGE RET ?
	JNZ	LE718		;DOING A LITTLE FCHKING HERE
	LXI	H,ABUF+3	;POINT TO LSB OF LINE NO.
	MOV	A,M		;GET IT
	ADD	B		;ADD INCREMENT
LE7B5:	CPI	'9'+1		;CARRY ?
	JNC	LE7CC		;NO - CONTINUE
	MOV	M,A		;PUT UPDATED DIGIT BACK
	LDA	ABUF		;GET MSB
	CPI	'9'		;EQUAL 9 ?
	CNC	LE7C9		;IF SO, CHANGE INCREMENT TO 1
	LHLD	APNT		;GET POINTER TO NEXT LINE
	JMP	LE78B		;AND DO IT
;
;CHANGE INCREMENT TO 1 IF NOS. GET TO 9000
;
LE7C9:	MVI	B,1		;NEW INCREMENT
	RET
;
;GET HERE IF ADDITION GAVE CARRY
;
LE7CC:	MVI	C,0		;C WILL BECOME DECIMAL CARRY
LE7CE:	INR	C		;INR FOR EA SUBTR. OF 10
	SUI	10		;SUB 10 FROM ADDITION RESULT
	CPI	'9'+1		;RESULT STILL > 9 ?
	JNC	LE7CE		;SUB AGAIN & KEEP CNT OF SUBTR
	MOV	M,A		;LESS THAN 10 - PUT DIGIT BACK
	DCX	H		;POINT TO NEXT MSB
	MOV	A,M		;GET IT
	ADD	C		;ADD CARRY FROM PREV. DIGIT
	JMP	LE7B5		;AND REPEAT THE PROCESS
;
;GENERAL ERROR MESSAGE ROUTINES
;
WHAT:	LXI	H,EMES
MESS:	CALL	CRLF		;DO CR/LF
	PUSH	H		;SAVE H,L
	LXI	H,SYSIN		;RESTORE STD I/O DRIVERS
	CALL	LE15A		;DO IT
	POP	H		;RESTORE H,L
	CALL	SCRN		;PRINT THE MSG POINTED TO BY H,L
	JMP	LE0CB		;GO BACK TO ALS-8 COMND MODE
;
;MESSAGES
;
EMES:	DB	'WHAT?', 0DH
EMES1:	DB	'FULL', 0DH
EMES2:	DB	'FCON', 0DH
FERR:	DB	' FILE ERR', 0DH
;
;THIS IS THE PROCESSING PORTION OF THE ENTER COMMAND
;
ENTS:	CALL	CRLF		;START ON A NEW LINE
	CALL	READ		;GET A LINE OF INPUT
	LXI	H,IBUF		;POINT TO IT'S START
	SHLD	PNTR		;SAVE POINTER
ENT1:	CALL	ZBUF		;CLEAR ASCII BUFFER
	CALL	SBLK		;SCAN TO CHARACTERS IN IBUF
	JC	ENTS		;C/R FOUND, GET ANOTHER LINE
	CPI	'/'		;ENTER TERMINATION CHAR ?
	RZ			;YES - DONE THEN
	CALL	ALPS		;LOAD ABUF FROM IBUF
	XCHG			;
	LXI	B,ABUF		;POINT TO THE LOADED BUFR
	LDA	SMODE		;GET THE CURRENT MODE
	ORA	A		;SET FLAGS
	JNZ	LE837		;JUMP IF OCTAL
	CALL	AHEX		;CONVERT ASCII HEX TO BINARY
	JMP	LE83A		;TO CONTINUE
LE837:	CALL	AOCT		;CONVERT OCTAL TO BINARY
LE83A:	RC			;RETURN IF ERROR
	LDAX	D		;GET CHAR FROM INPUT LINE
	CPI	':'		;NEW ADDRESS OR DATA ?
	JZ	LE84C		;NEW ADDRESS
	MOV	A,L		;DATA TO A
	LHLD	BBUF		;GET ENTER POINTER
	MOV	M,A		;PUT DATA IN MEMORY
	CALL	ACH1		;INCREMENT ENTER POINTER
	JMP	ENT1		;DO NEXT BYTE
LE84C:	SHLD	BBUF		;SAVE AS NEW ENTER ADDR
	XCHG			;IBUF POINTER TO H,L
	INX	H		;INCREMENT IT
	SHLD	PNTR		;SAVE IT
	JMP	ENT1		;DO MORE BYTES
;
;HERE ARE THE ROUTINES THAT ADD OR REPLACE LINES IN FILES
;BASED ON THEIR LINE NUMBERS.  DELETE IS HANDLED BY A
;SEPARATE ROUTINE
;
LINE:	CPI	'0'		;MAKE SURE 1ST CHAR IS NUMERIC
	JC	WHAT		;IF IT'S NOT
	LXI	H,3030H		;TWO ASCII ZEROES
	SHLD	IBUF-4		;PUT TWO BEFORE THE LINE
	SHLD	IBUF-2		;TWO MORE MAKES FOUR
	LXI	H,IBUF-1	;POINT TO SPACE BEFORE LINE
	MVI	C,4		;MAX NO DIGITS IN LINE NO
LE86A:	INX	H		;POINT TO 1ST CHAR
	MOV	A,M		;GET IT
	CPI	'0'		;NUMERIC ?
	JC	LE87C		;NO
	CPI	'9'+1		;NUMERIC ?
	JNC	LE87C		;NO
	DCR	C		;YES, NUMERIC
	JNZ	LE86A		;COUNT NUMERIC CHRS IN LINE NO.
;
;IF WE GET HERE THE LINE HAD A FULL 4-DIGIT NO. TO BEGIN WITH
;NOW MAKE SURE LINE NO. IS FOLLOWED BY AT LEAST ONE SPACE
;PUT ONE IN IF IT'S NOT
;
	INX	H		;POINT AFTER THE LINE NO
	MOV	A,M		;GET CHAR
LE87C:	CPI	' '		;IS CHAR AFTER LINE NO. SPACE ?
	MOV	B,C		;COUNT OF LEADING 0'S TO ADD
	DCX	H		;POINT TO LAST DIGIT OF LINE NO
	JZ	LE893		;IF LINE NO FOLLOWED BY SPACE
	INR	C		;INR COUNT OF TOTAL CHRS TO ADD
	MOV	B,C		;SAVE IN B
	MVI	C,4		;NEED TO MOVE 4 DIGIT LINE NO.
	MVI	A,' '		;TO INSERT A SPACE
LE889:	MOV	D,M		;GET CHAR
	MOV	M,A		;PUT CHAR IN A INTO LINE
	MOV	A,D		;CHAR REMOVED FROM LINE TO A
	DCX	H		;DECREMENT LINE POINTER
	DCR	C		;AND COUNT OF CHRS LEFT TO MOVE
	JNZ	LE889		;IF NOT DONE
	MOV	M,A		;REPLACE LAST CHARACTER
	MOV	C,B		;COUNT OF 0'S TO INSERT
LE893:	LXI	H,IBUF		;POINT TO IBUFFER
LE896:	DCX	H		;DECREMENT LINE POINTER
	DCR	C		;DCR COUNT OF 0'S TO INSERT
	JP	LE896		;LOOP TILL IT GOES NEGATIVE
	SHLD	SAVL		;H,L IS NEW START OF LINE
	LDA	CCNT		;GET OLD LINE LENGTH COUNT
	ADD	B		;ADD COUNT OF CHARACTERS ADDED
	STA	CCNT		;UPDATED COUNT
	CPI	7		;7 ==> ORIG LINE WAS BLANK
	JZ	LE92B		;TO DELETE THE LINE
	MOV	M,A		;PUT LEN BYTE AT HEAD OF LINE
	LXI	D,4		;LENGTH OF LINE NO.
	DAD	D		;H,L POINTS LAST CHR OF LINE NO
	SHLD	ADDS		;SAVE ADDR.
	LXI	D,MAXL+3	;END OF HIGHEST LIN # IN FILE
	CALL	COM0		;COMPARE LINE NO. TO MAXL
	JNC	INSRT		;LINE GOES INTO MIDDLE OF FILE
;
;LINE GOES AT END OF FILE
;
	INX	H		;POINT TO LINE NO.
	CALL	LODM		;GET IT IN BCDE
	LXI	H,MAXL+3	;POINT TO END OF MAXL
	CALL	STOM		;THIS LINE BECOMES NEW MAXL
	LHLD	SAVL		;GET ADDR OF LINE
	XCHG			;D,E IS LINE POINTER
	LHLD	EOFP		;H,L IS CURRENT END OF FILE
	MVI	C,1		;1 IS THE MOVE TERMINATOR CHAR
	CALL	LMOV		;MOVE LINE TO END OF FILE
	MOV	M,C		;PUT EOF MARK IN FILE
	SHLD	EOFP		;UPDATE END OF FILE
	JMP	EORNS		;DONE
;
;GET HERE TO INSERT A LINE INTO FILE
;
INSRT:	CALL	LE947		;FIND LINE NO IN FILE
	MVI	C,2		;FLAG INITIALIZATION
	JZ	EQUL		;LINE IN FILE HAS SAME NO.
	DCR	C		;C=1 ==> NO. NOT NOW IN FILE
EQUL:	MOV	B,M		;GET LENGTH OF LINE IN FILE
	DCX	H		;ADDR TO INSERT LINE AFTER
	MVI	M,2		;PUT MARKER THERE
	SHLD	APNT		;AND SAVE AS POINTER
	LDA	CCNT		;LENGTH OF LINE TO ADD
	DCR	C		;THE FLAG - 2 = REPLACEMENT
	JZ	LT		;IF NEW LINE # NOT = OLD LINE #
	SUB	B		;COMPUTE DIFF IN LINE LENGTHS
	JZ	ZERO		;IF LINES ARE SAME LENGTH
	JC	GT		;IF NEW LINE > OLD LINE
;
;GET HERE IF OLD LINE > NEW LINE OR DOING
;ADDITION RATHER THAN REPLACEMENT
;
LT:	LHLD	EOFP		;GET OLD END OF FILE
	MOV	D,H		;DUPLICATE IN D,E
	MOV	E,L		;
	CALL	ADR		;ADD DIFF. TO OLD EOFP
	SHLD	EOFP		;OLD + ADDED = NEW
	MVI	C,2		;MOVE TERMINATION MARK IN FILE
	CALL	RMOV		;DO THE MOVE
	JMP	ZERO		;INSERT LINE INTO GAP CREATED
;
;GET HERE IF OLD LINE < NEW LINE
;
GT:	CMA			;MAKE DIFFERENCE NEGATIVE
	INR	A		;TWO'S COMPLEMENT
	MOV	D,H		;DUPLICATE H,L IN D,E
	MOV	E,L		;
	CALL	ADR		;SUB. DIFF FROM OLD EOFP
	XCHG			;
	CALL	LMOV		;DELETE EXCESS CHAR IN FILE
	MVI	M,1		;E-O-F INDICATOR
	SHLD	EOFP		;E-O-F ADDRESS
;
;GET HERE TO INSERT CURRENT LINE INTO FILE AREA
;
ZERO:	LHLD	SAVL		;LINE ADDRESS
	XCHG			;TO D,E
	LHLD	APNT		;INSERT ADDRESS
	MVI	M,0DH		;REPLACE MOVE TERM. MARK W/CR
	INX	H		;POINT TO WHERE NEW LINE GOES
	MVI	C,1		;MOVE TERMINATION MARK
	CALL	LMOV		;PUT LINE INTO FILE
	JMP	EORNS		;DONE
;
;DELETE LINE IF LINE NO. ENTERED WITH NO TEXT
;
LE92B:	INX	H		;POINT TO LINE NO TO DELETE
	CALL	LODM		;GET IT IN B,C,D,E
	LXI	H,ABUF+3	;DESTINATION ADDRESS
	CALL	STOM		;STORE DELETE ADDRESS
	LXI	H,ABUF+10	;ADDRESS OF END OF 2ND PARM
	CALL	STOM		;STORE LINE NO. AGAIN
	CALL	LEA2F		;MAKE LIKE A DELT N,N COMMAND
	JMP	EORNS		;LINE DELETED, DONE
;
;FIND - SEARCH FILE FOR SPECIFIED LINE
;
FIND:	LXI	H,ABUF+3	;ADDRS. OF TEMP BUFFER
FIND1:	SHLD	ADDS		;ADDR OF NO. TO LOOK UP
LE947:	LHLD	BOFP		;START OF FILE TO SEARCH
FI1:	CALL	E01		;SEE IF AT END OF FILE
	XCHG			;FILE ADR TO D,E
	LHLD	ADDS		;GET ADDR OF NO TO LOOK UP
	XCHG			;SET UP
	MVI	A,4		;LENGTH OF LINE NO.
	CALL	ADR		;POINT TO END OF LINE NO.
	CALL	COM0		;SEE IF LINE NOS. ARE SAME
	RC			;NO IN FILE > SUBJECT
	RZ			;NOS. ARE THE SAME
FI2:	MOV	A,M		;GET LENGTH BYTE
	CALL	ADR		;POINT TO NEXT LINE
	JMP	FI1		;TEST NEXT LINE
;
;ROUTINE TO CHECK FOR END OF FILE
;
EOF:	INX	H		;
E01:	MVI	A,1		;EOF INDICATOR
	CMP	M		;SAME AS CHAR POINTED TO ?
	RNZ			;NO - RETURN
	JMP	EORNS		;YES - ABORT COMMAND
;
;ROUTINE TO ADD ONE BYTE NO IN A TO ADDR IN H,L
;
ADR:	ADD	L		;ADD A TO L
	MOV	L,A		;RESULT REPLACES L
	RNC			;DONE IF NO CARRY
	INR	H		;ELSE INCREMENT H
	RET			;DONE NOW
;
;CHARACTER MOVEMENT ROUTINE TO MOVE FROM D,E TO H,L
;INCREMENTING D,E (START AT LOW ADDRESS END OF BLOCK TO MOVE)
;MOVE ENDS WHEN CHAR IN REG C IS ENCOUNTERED.
;
LMOV:	LDAX	D		;GET SOURCE CHAR
	INX	D		;INR SOURCE POINTER
	CMP	C		;TERMINATION CHAR ?
	RZ			;YES - DONE THEN
	MOV	M,A		;NO - MOVE TO DEST.
	INX	H		;INR DESTINATION POINTER
	JMP	LMOV		;DO NEXT CHAR
;
;CHARACTER MOVEMENT ROUTINE TO MOVE FROM D,E TO H,L
;DECREMENTING POINTERS (START AT HIGH END OF BLOCK)
;MOVE ENDS WHEN CHAR IN REG C IS ENCOUNTERED
;
RMOV:	LDAX	D		;GET SOURCE CHAR
	DCX	D		;DECR SOURCE POINTER
	CMP	C		;TERMINATION CHAR ?
	RZ			;YES - DONE
	MOV	M,A		;NO - STORE CHAR AT DEST.
	DCX	H		;DECREMENT DEST. POINTER
	JMP	RMOV		;DO NEXT CHARACTER
;
;LOAD FOUR CHARS FROM MEMORY INTO REGS B,C,D,E
;
LODM:	MOV	B,M
	INX	H
	MOV	C,M
	INX	H
	MOV	D,M
	INX	H
	MOV	E,M
	RET
;
;STORE FOUR CHARS FROM REGS B,C,D,E INTO MEMORY
;
STOM:	MOV	M,E
	DCX	H
	MOV	M,D
	DCX	H
	MOV	M,C
	DCX	H
	MOV	M,B
	RET
;
;ROUTINE TO COMPARE TWO CHAR STRINGS OF LENGTH 4.
;ZERO FLAG SET ==> STRINGS EQUAL. CARRY ==> STRING
;ADDRESSED BY D,E GREATER THAN OR = STRING ADDR BY
;H,L
;
COM0:	MVI	C,4		;LENGTH OF COMPARISON
COM1:	MVI	B,1		;ASSUME EQUAL
	ORA	A		;CLEAR CARRY
C01:	LDAX	D		;FETCH CHARACTER
	SBB	M		;SET FLAGS & COMPARE
	JZ	C02		;THESE BYTES ARE THE SAME
	INR	B		;MAKE EQUAL FLAG = 2
C02:	DCX	D		;DECREMENT 1 STR. POINTER
	DCX	H		;DECR. OTHER POINTER
	DCR	C		;DECR. CNT OF BYTES TO COMPARE
	JNZ	C01		;DO NEXT BYTE
	DCR	B		;DECREMENT ZERO FLAG
	RET			;DONE W/ZERO SET
;
;ROUTINE TO TAKE ASCII CHARS AND ADD LEADING ASCII
;ZEROS TO YIELD A 4 CHARACTER ASCII VALUE
;
NORM:	CALL	LODM		;GET 4 DIGITS
	XRA	A		;GET A BINARY ZERO
	CMP	B		;ARE ALL DIGITS ZERO ?
	RZ			;YES - NOTHING TO NORMALIZE
NOR1:	CMP	E		;NORMALIZED ?
	CNZ	STOM		;YES, PUT DIGITS BACK
	RNZ			;AND RETURN
	MOV	E,D		;ELSE MOVE DIGITS UP
	MOV	D,C
	MOV	C,B
	MVI	B,'0'		;AND ADD A ZERO
	JMP	NOR1		;THEN TEST FOR NORMALIZATION
;
;ROUTINE TO MOVE A LINE FROM THE FILE BUFFER INTO 
;THE ASSEMBLERS LINE BUFFER
;
MOVEL:	LHLD	APNT		;GET ASSEMBLER POINTER
	MOV	A,M		;GET 1ST CHAR OF LINE
	CPI	1		;END OF FILE ?
	RZ			;YES, RETURN
	XCHG			;LINE ADDR TO D,E
	MOV	L,A		;GET LENGTH AS 16 BITS IN H,L
	MVI	H,0		;LENGTH < 128
	DAD	D		;ADD LENGTH TO START ADDR
	DCX	H		;POINT TO LAST CHAR OF LINE
	MOV	A,M		;GET IT
	CPI	0DH		;C/R ?
	JNZ	LE718		;REPORT FCHK ERROR
	INX	D		;POINT TO 1ST ACTUAL CHAR
	LXI	H,IBUF-5	;ASSEMBLERS BUFFER
	MVI	C,0DH		;TERMINATION CHAR
	CALL	LMOV		;MOVE THE LINE
	MOV	M,C		;PUT C/R AT END OF LINE
	XCHG			;1ST CHAR OF NEXT LINE TO H,L
	SHLD	APNT		;SAVE UPDATED ASSEM. POINTER
	ORA	A		;CLEAR FLAGS
	RET			;DONE
;
;LIST AND TEXT (LIST W/O LINE NUMBERS) COMMANDS
;
LIST:	CMA			;MAKE A NON-ZERO
TEXT:	STA	NOLIN		;SAVE AS FORMAT FLAG
	CALL	CRLF		;START ON FRESH LINE
	LXI	H,ABUF		;GET STARTING LINE NO.
	CALL	LODM		;
	XRA	A		;ZERO FLAGS & ACCUM.
	CMP	B		;LINE NO. GIVEN ?
	JNZ	LE9EF		;JUMP IF LINE NO. GIVEN
	MVI	B,0FFH		;MAKE LINE NO. > 9999
LE9EF:	LXI	H,ABUF+10
	CMP	M		;ENDING LINE NO. GIVEN ?
	JNZ	LE9F9		;IF ENDING NO. GIVEN
	CALL	STOM		;STORE ENDING LINE NO > 9999
LE9F9:	CALL	FIND		;FIND STARTING LINE NO.
	SHLD	APNT		;SAVE AS POINTER
LE9FF:	CALL	MOVEL		;MOVE LINE TO OUTPUT BUFFER
	JZ	EOR		;IF END OF FILE FOUND
	LXI	H,IBUF-2	;POINT TO LAST DIGIT OF LINE NO
	LXI	D,ABUF+10	;D POINTS TO ENDING LINE NO.
	CALL	COM0		;COMPARE LINE NO. & END LIN NO.
	RC			;RETURN IF > ENDING LINE NO
	LDA	LFMT		;GET FORMAT FLAG
	ORA	A		;SET FLAGS
	CNZ	LF361		;TO FORMAT LINE
	LXI	H,IBUF-5	;POINT TO START OF LINE
	LDA	NOLIN		;GET LINE NO. FLAG
	ORA	A		;SET FLAGS
	JNZ	LEA23		;PRINT WITH LINE NO.
	LXI	H,IBUF		;POINT PAST LIN NO.
LEA23:	CALL	SCRN		;PRINT LINE FROM H,L POINTER
	CALL	CRLF		;PUT CR/LF AFTER LINE
	JMP	LE9FF		;TO DO NEXT LINE
;
;DELT - THE DELETE LINE COMMAND
;
DELT:	CALL	VCHK		;CHECK FOR REQD PARAMETERS
LEA2F:	CALL	FIND		;GET STARTING DELT ADDR
	SHLD	DELP		;SAVE IT
	LXI	H,ABUF+10	;SEE IF 2ND PARM GIVEN
	MOV	A,M		;GET CHAR
	ORA	A		;SET FLAGS
	JNZ	LEA40		;IF 2ND PARM GIVEN
	LXI	H,ABUF+3	;FIRST & LAST LINE ARE SAME
LEA40:	SHLD	ADDS		;SAVE 1ST LINE FIND ADDR
	XCHG
	LXI	H,MAXL+3	;HIGHEST LINE NO.
	CALL	COM0		;COMPARE TO ENDING DELT LINE
	LHLD	DELP		;GET DELT POSITION TO H,L
	JC	NOVR		;DELETE DOES NOT INVOLVE END
;
;GET HERE IF DELETE INVOLVES END OF FILE
;
;THIS GETS COMPLICATED BECAUSE:
;  A) THE LAST LINE'S C/R IS NOT FOLLOWED BY ANY LINE NO.
;                      AND
;  B) IN GENERAL, A 0DH MIGHT BE EITHER A LENGTH BYTE OR C/R
;
LEA50:	SHLD	EOFP		;DELT POS. ==> NEW EOF
	MVI	M,1		;PUT NEW EOF MARK IN FILE
	MOV	B,M		;FLAG WHICH ISN'T REALLY USED
	XCHG			;D,E = EOF
	LHLD	BOFP		;H,L = BOF
	XCHG			;D,E = BOF & H,L = EOF
	DCX	H		;SO WE MISS LAST LINE'S C/R
DEL2:	MOV	A,L		;SUBTRACT BOF FROM EOF
	SUB	E		;
	MOV	A,H		;
	SBB	D		;
	MVI	A,0DH		;SETTING UP FOR COMPARE
	JC	DEL4		;NO 0DH IN FILE==> MAXL=0
	DCX	H		;MOVE UP 1 CHAR
	CMP	M		;0DH ?
	JNZ	DEL2		;NO, THEN TRY NEXT CHAR
	DCX	H		;YES - SEE IF TWO IN A ROW
	MOV	A,L		;SUBTRACTING BOF FROM POINTER
	SUB	E
	MOV	A,H		;
	SBB	D		;
	JC	DEL4		;0DH WAS 1ST CHAR==>LENGTH BYTE
	MVI	A,0DH		;COMPARE THIS CHAR TO 0DH
	CMP	M		;
	INX	H		;POINT TO NEXT CHAR
	INX	H		;POINT TO NEXT CHAR
	JZ	DEL3		;WERE TWO 0DH'S, AT LINE # NOW
LEA7A:	INX	H		;ONLY 1 0DH, 1 MORE==>AT LINE #
DEL3:	CALL	LODM		;GET LINE NO IN REGS
	LXI	H,MAXL+3	;WHERE IT GOES
	CALL	STOM		;PUT IT THERE
	RET			;MAXL IS UPDATED
DEL4:	XCHG			;FOR PROPER RETURN
	DCR	B		;ALWAYS 1 ==> 0
	JNZ	LEA7A		;NEVER TAKE JUMP
	STA	MAXL		;MAKES MAXL VERY SMALL ALWAYS
	RET			;DONE, EDITOR THINKS FILE EMPTY
;
;GET HERE IF DELETE IS IN THE MIDDLE OF THE FILE
;
NOVR:	CALL	FI1		;FIND END OF DELETE AREA
	CZ	FI2		;NEXT LINE IF LINE NOS. EQUL
	XCHG			;
	LHLD	DELP		;DEST = START OF DELT AREA
	MVI	C,1		;TERM ON EOF MARK
	CALL	LMOV		;DO THE MOVE TO DELETE
	SHLD	EOFP		;UPDATE EOF ADDRESS
	MVI	M,1		;PUT EOF MARK IN FILE
	RET			;DONE
;
;STAB COMMAND - SET SYMBOL TABLE ADDRESS
;
STAB:	CALL	VCHK		;CHECK FOR REQD PARM
	LHLD	BBUF		;GET IT
	SHLD	SYMADD		;SAVE AS SYMBOL TABLE ADDRESS
	JMP	EORMS		;DONE
;
; ***** END OF ALS8COM MODULE
;
;
;THE ASSEMBLER STARTS HERE
;
;ASPC IS THE PROGRAM COUNTER (GOES ON LISTING), AND
;BBUF+2 IS THE STORAGE COUNTER (WHERE OBJECT CODE GOES)
;
ASSM:	CALL	VCHK		;AT LEAST 1 PARM. REQD
	LDA	ABUF+7		;2ND PARM. (OFFSET) GIVEN ?
	ORA	A		;SET FLAGS
	JNZ	ASM4		;USE 2ND PARM. IF GIVEN
	LHLD	BBUF		;ELSE GET 1ST PARM
	SHLD	BBUF+2		;USE 1ST PARM. AS STORAGE CNTR
ASM4:	LDA	IBUF+4		;GET LETTER AFTER ASSM OR ASSI
	CPI	'E'		;'E' - OMIT NON-ERROR LINES ?
	JZ	LEAD6		;SKIP CHECKING FOR 'S' OR 'X'
	CPI	'S'		;'S' - LIST SYMBOL TABLE ?
	JZ	LEAD6		;SKIP CHECKING FOR 'X'
	CPI	'X'		;'X' - CROSS REFERENCE ?
	JZ	LEAD6		;HAVE PRINT FLAG
	CPI	' '		;MUST BE SPACE, E, S, OR X
	JNZ	WHAT		;WHOOPS - ILLEAGLE CHAR.
LEAD6:	STA	SYMX		;SAVE SYMBOL/PRINT FLAG
	LDA	IBUF+3		;GET ASSEMBLY TYPE (ASSM/ASSI)
	STA	ASMTY		;SAVE AS ASSEMBLY TYPE
	XRA	A		;GET A ZERO
	LHLD	SYMADD		;POINT TO SYMBOL TABLE START
	MOV	M,A		;PUT IN END OF TABLE MARK
	STA	ALST		;ASSUME LIST TURNED 'ON'
	STA	PASI		;SET PASS INDICATOR TO PASS 1
LEAEA:	LHLD	BBUF		;GET PGM. ORG
	SHLD	ASPC		;USE IT TO INIT. PROG. COUNTER
	LHLD	BOFP		;GET START OF SOURCE
	SHLD	APNT		;USE IT TO INIT. ASS. POINTER
;
;THIS IS THE START OF THE MAIN ASSEMBLER PROCESSING LOOP
;
LEAF6:	LXI	SP,SMODE
	LXI	H,OBUF		;POINT TO OUTPUT BUFFER
	MVI	A,IBUF AND 0FFH	;LOW BYTE OF END OF OBUF
	CALL	CLER		;CLEAR OBUF TO SPACES
	LDA	ASMTY		;GET ASSM/ASSI FLAG
	CPI	'I'		;USING EXTERNAL INPUT ?
	JZ	LEB12		;YES - CALL IT
	CALL	MOVEL		;ELSE MOVEL PUTS LINE IN IBUF
	JZ	LEE39		;IF END OF FILE DETECTED
	JMP	LEB15		;SKIP CALL TO EXT. INPUT
LEB12:	CALL	IN8		;CALL ASSI DRIVER FOR EXT INPUT
LEB15:	LDA	PASI		;GET PASS INDICATOR
	ORA	A		;SET FLAGS
	JNZ	ASM2		;DO THE 2ND PASS
	CALL	PAS1		;ELSE DO PASS 1
	JMP	LEAF6		;THEN BACK TO TOP OF LOOP
ASM2:	CALL	PAS2		;PROCESS PASS 2 LINE
	LXI	H,OBUF		;POINT TO OUTPUT BUFFER
	CALL	AOUT		;PRINT LINE
	JMP	LEAF6		;THEN BACK TO TOP OF LOOP
;
;END OF MAIN LOOP
;
;FOLLOWING ROUTINE PRINTS LINE DURING 2ND PASS
;
AOUT:	LDA	OBUF+18		;GET ERROR TYPE IN OUTPUT LINE
	CPI	' '		;WAS THERE AN ERROR ?
	JNZ	LEB41		;YES - PRINT LINE
	LDA	AERR		;GET SYMBOL/ERROR PRINT FLAG
	CPI	'E'		;ERRORS-ONLY LISTING ?
	RZ			;YES - DONE WITH THIS LINE
	LDA	ALST		;GET ASSEMBLER LIST FLAG
	ORA	A		;SET FLAGS
	RNZ			;DONE IF LISTING TURNED OFF
LEB41:	LDA	PASI		;GET PASS INDICATOR
	CPI	2		;GREATER THAN 1 (E.G. 3RD PASS)
	RNC			;DONE THEN
	LDA	LFMT		;GET FORMAT/NO FORMAT FLAG
	ORA	A		;SET FLAGS
	CNZ	LF361		;FORMAT LINE IF NECESSARY
	LXI	H,OBUF		;POINT TO LINE TO OUTPUT
	CALL	CRLF		;DO CARRIAGE RET FROM PREV LINE
	JMP	SCRN		;PRINT LINE & RET.
;
;PASS 1 OF THE ASSEMBLER USED TO FORM SYMBOL TABLE
;
PAS1:	CALL	ZBUF		;CLEAR OUT THE ASCII BUFFER
	STA	PASI		;PUT PASS INDICATOR BACK
	LXI	H,IBUF		;POINT TO 1ST CHAR OF LINE
	SHLD	PNTR		;SAVE AS POINTER INTO LINE
	MOV	A,M		;GET 1ST CHAR
	CPI	' '		;BLANK ?
	JZ	OPC		;NO LABEL THEN
	CPI	COMCHR		;COMMENT CHARACTER ?
	RZ			;DONE IF COMMENT LINE
;
;PROCESS LABEL POINTED TO IN LINE BY H,L
;
	CALL	SLAB		;SEE IF LABEL ALREADY IN TABLE
	JC	LF0E0		;ERROR IN LABEL
	JZ	ERRD		;DUPLICATE LABEL
	CALL	LCHK		;CHECK CHAR AFTER LABEL
	JC	LF0E0		;IF NOT SPACE OR COLON
	CALL	LEBA5		;TO MOVE LABEL INTO TABLE
	XCHG			;SYM. TABLE ADDR TO H,L
	SHLD	TABA		;SAVE AS SYMBOL TABLE PNTR
	LDA	ASPC+1		;PUTTING P.C. IN SYMBOL TABLE
	MOV	M,A		;PUT 1ST BYTE IN TABLE
	INX	H		;INR. TABLE POINTER
	LDA	ASPC		;GET 2ND BYTE
	MOV	M,A		;PUT IT IN TABLE
	INX	H		;POINT PAST VALUE
	MVI	M,0		;END OF TABLE MARK
;
;PROCESS OPCODE
;
OPC:	CALL	ZBUF		;BLANK OUT ABUF
	CALL	SBLK		;SCAN TO OPCODE
	JC	OERR		;IF FOUND C/R INSTEAD
	CALL	ALPS		;MOVE OPCODE INTO ABUF
	CPI	' '		;CHECK FOR SPACE AFTER OPCODE
	JC	OPCD		;OPCODE FOLLOWED BY C/R
	JNZ	OERR		;OPCODE FOLLOWED BY CHAR.
	JMP	OPCD		;TO CONTINUE OPCODE PROC.
;
;ROUTINE TO MOVE LABEL INTO SYMBOL TABLE
;
LEBA5:	MVI	C,LLAB		;LENGTH OF LABEL
	LXI	H,ABUF		;SOURCE
MLAB:	MOV	A,M		;GET CHAR FROM LABEL
	STAX	D		;PUT IT IN TABLE
	INX	D		;DEST. POINTER
	INX	H		;SOURCE POINTER
	DCR	C		;LENGTH POINTER
	JNZ	MLAB		;IF MORE CHARS TO MOVE
	RET			;ELSE DONE
;
;CHECK LABELS FOR VALID TERMINATOR
;
LCHK:	LHLD	PNTR		;GET POINTER
	MOV	A,M		;GET CHAR
	CPI	' '		;SPACE ?
	RZ			;OK THEN, RETURN
	CPI	':'		;COLON ?
	RNZ			;IF NOT, RETURN ZERO FLAG OFF
	INX	H		;ELSE OK, INR. PAST NON-SPACE
	SHLD	PNTR		;AND UPDATE POINTER
	RET			;THEN RETURN
;
;PROCESS PSEUDO OPS IN PASS 1
;H,L POINTS INTO LINE, D,E POINTS INTO OPCODE TABLE
;
PSU1:	CALL	SBLK		;SCAN TO OPERAND
	LDAX	D		;FETCH TABLE VALUE
	ORA	A		;SET FLAGS
	JZ	ORG1		;ORG PSEUDO OP
	JM	DAT2A		;DB PSEUDO OP
	CPI	2		;
	JC	EQU1		;EQU PSEUDO OP
	JZ	RESI		;DS PSEUDO OP
	CPI	8		;
	JZ	LEC26		;ASC PSEUDO OP
	CPI	5		;
	RNC			;PSEUDO-OPS NOT USED 1ST PASS
	JPE	LEE39		;END PSEUDO OP
;
;DO DW PSEUDO OP
;
ACO1:	MVI	C,2		;DW IS A 2-BYTE INSTR.
	XRA	A		;CLEAR CARRY & FLAGS
	JMP	OCN1		;TO INCREMENT PGM. COUNTER
;
;DO ORG PSEUDO OP
;
ORG1:	CALL	ASCN		;GET OPERAND TO H,L
	LDA	OBUF+18		;GET ERROR INDICATOR
	CPI	' '		;ANY ERRORS IN THIS LINE ?
	RNZ			;IF SO, DON'T PROCESS
	SHLD	ASPC		;ELSE PUT VALUE IN PGM. CTR.
	LDA	IBUF		;GET 1ST CHAR OF LINE
	CPI	' '		;SPACE OR LABEL CHAR ?
	RZ			;DONE IF SPACE
	JMP	EQUS		;ELSE CHANGE LABEL VALUE
;
;DO EQU PSEUDO OP
;
EQU1:	CALL	ASCN		;GET VALUE TO H,L
	LDA	IBUF		;POINT AT 1ST CHAR OF LINE
	CPI	' '		;SPACE OR LABLE CHAR ?
	JZ	ERRM		;EQU REQUIRES A LABEL ALWAYS
EQUS:	XCHG			;VALUE TO D,E
	LHLD	TABA		;TABLE ADDR TO H,L
	MOV	M,D		;STORE LABEL VALUE IN S. TABLE
	INX	H		;2ND BYTE
	MOV	M,E		;
	LDA	OBUF+18		;GET ERROR FLAG
	CPI	' '		;LINE O.K. ?
	RZ			;DONE THEN
	JMP	LEB41		;ELSE PRINT THE LINE
;
;DO DS PSEUDO OP
;
RESI:	CALL	ASCN		;GET OPERAND VALUE TO H,L
	MOV	B,H		;MOVING TO B,C
	MOV	C,L		;
	LDA	OBUF+18		;GET ERROR INDICATOR
	CPI	' '		;LINE O.K. ?
	JNZ	LEB41		;PRINT IT IF NOT
	JMP	RES21		;ELSE ADD B,C TO PGM. CTR.
;
;DO ASC PSEUDO OP
;
LEC26:	MOV	A,M		;GET 1ST NON-SPACE CHAR
	CPI	0DH		;CARRIAGE RETN ?
	RZ			;DONE
	MOV	D,A		;SAVE DELIMITER IN D
	LXI	B,0		;INITIALIZE CHAR COUNT TO 0
LEC2E:	INX	H		;POINT TO NEXT CHAR
	MOV	A,M		;GET IT
	CPI	0DH		;END OF LINE ?
	JZ	RES21		;DONE WITH STRING
	CMP	D		;2ND DELIMETER ?
	JZ	RES21		;DONE IF SO
	INX	B		;ELSE INR. CHAR COUNT
	JMP	LEC2E		;AND KEEP ON COUNTING
;
;PERFORM PASS 2 OF THE ASSEMBLER
;
PAS2:	LXI	H,OBUF		;SET OUTPUT BUFFER ADDRESS
	LDA	ASPC+1		;GET HIGH BYTE OF PGM. CTR.
	CALL	BINH+3		;CONVERT TO ASCII & STORE
	INX	H		;POINT PAST BYTE
	LDA	ASPC		;GET LOW ORDER BYTE
	CALL	BINH+3		;PUT IT IN ADDR FIELD, TOO
	SHLD	OIND		;SAVE H,L AS OUTPUT POINTER
	CALL	ZBUF		;CLEAR ABUFF
	LXI	H,IBUF		;POINT TO LINE TO ASSEMBLE
PABL:	SHLD	PNTR		;SAVE AS POINTER
	MOV	A,M		;GET 1ST CHAR OF LINE
	CPI	' '		;SPACE ?
	JZ	OPC		;YES, NO LABEL, PROC. OPCODE
	CPI	COMCHR		;IS IT A COMMENT LINE ?
	RZ			;DONE THEN
	CALL	SLAB		;LOOK UP LABEL IN TABLE
	JC	LF0E0		;LABEL ERROR
	CALL	LCHK		;CHECK TERM. CHAR
	JNZ	LF0E0		;NOT FOLLOWED BY '$' OR ':'
	JMP	OPC		;PROCESS THE OPCODE
;
;PROCESS PSEUDO OPS FOR THE 2ND PASS
;
PSU2:	LDAX	D		;GET TABLE VALUE
	ORA	A		;SET FLAGS
	JZ	ORG2		;ORG PSEUDO OP
	JM	DAT2		;DB PSEUDO OP
	CPI	2
	RC			;EQU WAS PROCESSED ON 1ST PASS
	JZ	RES2		;DS PSEUDO OP
	CPI	8
	JZ	LED01		;ASC PSEUDO OP
	CPI	5
	JZ	LECD3		;COM PSEUDO OP
	JNC	LECCD		;BOTH LST AND NLST
	JPE	LEE39		;END PSEUDO OP
;
;DO DW PSEUDO OP
;
ACO2:	CALL	TYS6		;GET VALUE & PUT IN MEM
	JMP	ACO1		;INR P.C. & RET
;
;DO DS PSEUDO OP IN PASS 2
;
RES2:	CALL	ASBL		;GET VALUE IN H,L
	MOV	B,H		;MOVING TO B,C
	MOV	C,L
	LHLD	BBUF+2		;GET STORAGE COUNTER
	DAD	B		;ADD NO BYTES IN DS STMNT
	SHLD	BBUF+2		;UPDATE STORAGE COUNTER
RES21:	XRA	A		;CLEAR ZERO FLAG
	JMP	OCN2		;TO UPDATE PGM. COUNTER
;
;DO PASS 2 DB PSEUDO OP
;
DAT2:	CALL	TYS5		;GET OPERNAD
DAT2A:	XRA	A		;MAKE ACC. ZERO
	MVI	C,1		;BYTE COUNT
	JMP	OCN1		;TO INR. PGM. COUNTER
;
;DO ORG PSEUDO OP
;
;P.T. SCREWED THIS ONE UP, AS THEY STORE THE NEW ORG NOT ONLY
;AS THE ASSEMBLERS PROGRAM COUNTER, BUT ALSO AS THE STORAGE
;COUNTER, WHICH POINTS TO WHERE THEY ARE STORING THE OBJECT
;CODE. THUS IF YOU WERE USING AN OFFSET (E.G. ASSM XXXX YYYY)
;BEFORE THE ORG STATEMENT, YOU WON'T BE AFTERWARDS.  WHAT'S
;SURPRISING IS THAT IMSAI'S SCS-1, WRITTEN BY THE SAME CO.
;THAT WROTE ALS-8 FOR P.T. (MICRO-TEC OF SUNNYVALE CALIF.),
;HAS THIS FIXED, EVEN THOUGH IT WAS AN EARLIER PRODUCT.
;
ORG2:	CALL	ASBL		;GET ORG VALUE
	LDA	OBUF+18		;FETCH ERROR FLAG
	CPI	' '		;LINE O.K. ?
	RNZ			;IGNORA IF NOT
	XCHG			;VALUE TO D,E
	LHLD	ASPC		;GET CUR. PGM COUNTER
	XCHG			;NEW ORG H,L - PC IN D,E
	SHLD	ASPC		;MAKE ORG NEW P.C.
	SHLD	BBUF+2		;AND MAKE IT STORAGE CNTR ALSO
	RET			;DONE, AND YOU ARE SCREWED
;
;PROCESS THE $ SYMBOL (CUR. VALUE OF PGM. COUNTER)
;
LECC3:	INX	H		;INCREMENT POINTER
	SHLD	PNTR		;SAVE POINTER
	LHLD	ASPC		;GET CUR. PGM. COUNTER
	JMP	AVAL		;TO FINISH EXPR. EVALUATION
;
;PROCESS NLST AND LST PSEUDO OPS.
;
LECCD:	SUI	6		;CONVERT LST/NLST TO 0 OR 1
	STA	ALST		;SAVE AP LIST FLAG
	RET			;DONE
;
;PROCESS COM PSEUDO OP
;
LECD3:	CALL	ZBUF		;CLEAR ABUF
	CALL	SBLK		;SCAN TO LABEL TO ENTER
	CALL	SLAB		;LOOKUP LABEL, VALUE IN H,L
	JC	ERRA		;IF ERROR IN LABEL
	JNZ	ERRU		;IF LABEL NOT FOUND
LECE2:	LXI	D,SYSYM		;SYSTEM SYMBOL TABLE
LECE5:	SHLD	OPRD		;SAVE VALUE IN OPRD
	MVI	B,LLAB		;LENGTH OF LABELS
	CALL	COMS		;SEE IF ALREADY IN SYSTEM TABLE
	JZ	LECF9		;ALREADY IN TABLE, CHG VALUE
	CALL	LEBA5		;NOT IN TABLE, ADD IT
	INX	D		;POINT PAST (UNDEFINED) VALUE
	INX	D		;2ND BYTE
	XRA	A		;GET BINARY ZERO
	STAX	D		;TABLE'S NEW END MARK
	DCX	D		;POINT TO 2ND BYTE OF VALUE
	INR	A		;TURN ZERO FLAG OFF
LECF9:	LHLD	OPRD		;GET SYMBOL'S VALUE
	XCHG			;TO D,E
	MOV	M,E		;STORE 1 BYTE
	DCX	H		;POINT FROM 2ND TO 1ST BYTE
	MOV	M,D		;STORE IT, TOO.
	RET			;DONE
;
;DO ASC PSEUDO OP
;
LED01:	CALL	SBLK		;SCAN TO 1ST NON BLANK CHAR
	JC	ERRA		;IF C/R FOUND
	MOV	C,A		;SAVE AS DELIM.
	INX	H		;POINT TO 1ST CHR OF STRING
	MOV	A,M		;GET IT
	CPI	0DH		;END OF LINE ?
	JZ	ERRA		;ERROR THEN
	CMP	C		;SECOND DELIMITER ?
	JZ	ERRA		;ERROR THEN, TOO
	MVI	B,0F9H		;******MAY BE ADDRESS DEPENDANT
LED15:	MOV	A,M		;GET THE CHAR FROM STRING
	CPI	0DH		;END OF LINE ?
	JZ	LED57		;DONE WITH STRING THEN
	CMP	C		;2ND DELIMITER ?
	JZ	LED57		;DONE WITH STRING THEN
	SHLD	PNTR		;SAVE STRING POINTER
	LHLD	ASPC		;GET PROGRAM COUNTER
	INX	H		;THIS USED UP 1 BYTE
	SHLD	ASPC		;PUT UPDATED POINTER BACK
	INR	B		;
	PUSH	B		;SAVE B,C
	CALL	ASTO		;PUT BYTE IN MEMORY & LISTING
	MOV	A,L		;GET LOW BYTE OF LISTING PTR
	CPI	(OBUF+15) AND 0FFH
	JNZ	LED4F		;NO, DO NEXT BYTE
	CALL	AOUT		;YES, PRINT THE LINE
	POP	B		;GET BACK B,C
	MVI	B,0		;RESET FLAG
	PUSH	B		;SAVE B,C AGAIN
	LXI	H,2020H		;TWO SPACES
	SHLD	OBUF		;BLANK ADDR FIELD BYTES 1 & 2
	SHLD	OBUF+2		;3RD & 4TH BYTES
	MVI	A,0DH		;GET C/R
	STA	OBUF+16		;LINE ENDS WITH OBJECT CODE
	LXI	H,OBUF+3	;LAST BYTE OF ADDR FIELD
	SHLD	OIND		;OUTPUT POINTER FOR NXT LINE
LED4F:	LHLD	PNTR		;GET STRING POINTER
	POP	B		;RESTORE B,C
	INX	H		;INCREMENT STRING POINTER
	JMP	LED15		;DO NEXT BYTE OF STRING
;
;GET HERE WHEN HAVE REACHED 2ND DELIMITER OR C/R
;
LED57:	MOV	A,B		;GET 1ST LINE FLAG TO A
	ORA	A		;SET FLAGS
	RM			;ON 1ST LINE, DONE
	JZ	LEAF6		;FOR S.T./XREF, MAIN LOOP
	LHLD	OIND		;GET OUTPUT LINE POINTER
	INX	H		;POINT PAST LAST BYTE
	MVI	M,0DH		;TERMINATE LINE
	RET			;DONE
;
;PROCESS STAX AND LDAX INST.
;
TYP2:	CALL	ASBL		;FETCH OPERAND
	CNZ	ERRR		;ILLEGAL REGISTER
	MOV	A,L		;GET LOW ORDER OPERAND
	ORA	A		;SET FLAGS
	JZ	TY31		;OPERAND = 0
	CPI	2		;OPERAND = 2
	CNZ	ERRR		;ILLEGAL REGISTER
	JMP	TY31
;
;PROCESS PUSH, POP, INX, DCX, DAD INSTRUCTIONS
;
TYP3:	CALL	ASBL		;FETCH OPERAND
	CNZ	ERRR		;ILLEGAL REGISTER
	MOV	A,L		;GET LOW ORDER OPERAND
	RRC			;CHECK LOW ORDER BIT
	CC	ERRR		;ILLEGAL REGISTER
	RAL			;RESTORE
	CPI	8		;
	CNC	ERRR		;ILLEGAL REGISTER
TY31:	RLC			;SHIFT LEFT 3 TIMES
	RAL			;
	RAL			;
TY32:	MOV	B,A		;SAVE REGISTER
	LDAX	D		;FETCH OPCODE BASE
	ADD	B		;FORM OPCODE W/REGISTER
	CPI	76H		;CHECK FOR MOV M,M
	CZ	ERRR		;ILLEGAL REGISTER
	JMP	ASTO		;PUT IN MEM & INR P.C.
;
;PROCESS ACCUMULATOR, INR, DCR, MOV, RST INSTRUCTIONS
;
TYP4:	CALL	ASBL		;FETCH OPERAND
	CNZ	ERRR		;ILLEGAL REGISTER
	MOV	A,L		;GET LOW ORDER OPERAND
	CPI	8		;
	CNC	ERRR		;ILLEGAL REGISTER
	LDAX	D		;FETCH OPCODE BASE
	CPI	40H		;CHECK FOR MOV INST.
	JZ	TY41		;PROCESS THEM SEPARATELY
	CPI	0C7H		;
	MOV	A,L		;OPERAND IN ACCUM.
	JZ	TY31		;RST INSTRUCTION
	JM	TY32		;ACCUMULATOR INST.
	JMP	TY31		;INR, DCR INSTRUCTIONS
;
;PROCESS MOV INSTRUCTIONS
;
TY41:	DAD	H		;MULT OPRND BY 8 (3 LFT SHIFTS)
	DAD	H		;
	DAD	H		;
	ADD	L		;FORM OPCODE
	STAX	D		;SAVE OPCODE
	CALL	MPNT		;
	CALL	ASCN		;
	CNZ	ERRR		;
	MOV	A,L		;FETCH LOW ORDER OPERAND
	CPI	8		;
	CNC	ERRR		;ILLEGAL REGISTERS
	JMP	TY32		;
;
;PROCESS IMMEDIATE INSTRUCTIONS
;IMMEDIATE BYTE CAN BE -256 TO +255
;MVI INSTRUCTION IS A SPECIAL CASE AND HAS 2 OPERANDS
;
TYP5:	CPI	6		;CHECK FOR MVI INST
	CZ	TY56		;SPECIAL CASE
	CALL	ASTO		;PUT OBJ. IN MEM & ON LISTING
TYS5:	CALL	ASBL		;GET IMMEDIATE ARG.
	INR	A		;
	CPI	2		;CHECK OPERAND FOR RANGE
	CNC	ERRV		;OPERAND OUT OF RANGE
	MOV	A,L		;
	JMP	ASTO		;PUT OBJECT IN MEM & ON LISTING
;
;FETCH 1ST ARGUMENT FOR MVI AND LXI INSTRUCTIONS
;
TY56:	CALL	ASBL		;FETCH ARGUMENT
	CNZ	ERRR		;ILLEGAL REGISTER
	MOV	A,L		;GET LOW ORDER ARGUMENT
	CPI	8		;
	CNC	ERRR		;ILLEGAL REGISTER
	DAD	H		;MULT BY 8 (3 LEFT SHIFTS)
	DAD	H		;
	DAD	H		;
	LDAX	D		;FETCH OPCODE BASE
	ADD	L		;FORM OPCODE
	MOV	E,A		;SAVE OBJECT BYTE
MPNT:	LHLD	PNTR		;FETCH POINTER
	MOV	A,M		;FETCH CHARACTER
	CPI	','		;CHECK FOR COMMA
	INX	H		;INCREMENT POINTER
	SHLD	PNTR		;AND SAVE IT
	JNZ	ERRS		;SYNTAX ERROR IF NO COMMA
	MOV	A,E		;
	RET			;
;
;PROCESS 3 BYTE INSTRUCTIONS
;LXI INSTRUCTION IS A SPECIAL CASE
;
TYP6:	CPI	1		;CHECK FOR LXI INSTRUCTION
	JNZ	TY6		;JUMP IF NOT LXI
	CALL	TY56		;GET REGISTER
	ANI	8		;CHECK FOR ILLEGAL REGISTER
	CNZ	ERRR		;REGISTER ERROR
	MOV	A,E		;GET OPCODE
	ANI	0F7H		;CLEAR BIT IN ERROR
TY6:	CALL	ASTO		;STORE OBJECT BYTE
TYS6:	CALL	ASBL		;FETCH OPERAND
	MOV	A,L		;TO ACCUM
	MOV	D,H		;
	CALL	ASTO		;PUT 2ND BYTE IN MEMORY
	MOV	A,D		;
;
;THIS ROUTINE IS USED TO STORE OBJECT CODE PRODUCED BY
;THE ASSEMBLER DURING THE 2ND PASS INTO MEMORY
;
ASTO:	LHLD	BBUF+2		;FETCH STORAGE COUNTER
	MOV	B,A		;SAVE OBJECT BYTE
	LDA	PASI		;GET PASS INDICATOR
	CPI	2		;3RD PASS ? (S.T./XREF)
	RNC			;SKIP OBJECT STORAGE THEN
	MOV	A,B		;ELSE RESTORE OBJECT BYTE
	MOV	M,A		;AND PUT IT IN MEMORY
	INX	H		;INCREMENT STORAGE POINTER
	SHLD	BBUF+2		;AND PUT IT BACK
	LHLD	OIND		;GET OUTPUT ADDRESS
	INX	H		;INCR. TO POINT PAST LAST BYTE
	INX	H		;AGAIN, PUT SPACE BETWEEN BYTES
	CALL	BINH+3		;CONVERT OBJECT BYTE TO ASCII
	SHLD	OIND		;AND SAVE UPDATED POINTER
	RET			;OBJECT IN MEM & ON LISTING
;
;PROCESS THE END PSEUDO OP
;
LEE39:	LXI	H,PASI		;POINT TO THE PASS INDICATOR
	MOV	A,M		;GET IT
	CPI	1		;JUST FINISHED 2ND PASS ?
	JZ	LEE4C		;YES - DONE OR START 3RD PASS
	JNC	LEE9D		;IF 3RD PASS COMPLETE
	CALL	CRLF		;DO CRLF AT START OF EA. PASS
	INR	M		;INCREMENT PASS COUNTER
	JMP	LEAEA		;START NEXT PASS
;
;GET HERE AT END OF 2ND PASS
;
LEE4C:	LDA	SYMX		;GET S.T./XREF FLAG
	CPI	'E'+1		;'S' OR 'X' OPTION REQUESTED ?
	JC	EORMS		;NO - ASSY DONE, BACK TO ALS8
	INR	M		;YES - INCREMENT PASS IND.
	CALL	CRLF		;CRLF AFTER EA. PASS
LEE58:	CALL	CRLF		;AGAIN BEFORE S.T./XREF
	XRA	A		;GET A ZERO
LEE5C:	STA	SCNT		;SAVE AS SYMBOL COUNT
	LHLD	SYMADD		;GET ADDR OF SYMBOL TABLE
	MOV	D,H		;DUPLICATE IN D,E
	MOV	E,L		;
;
;TEST NAMES POINTED TO BY D,E AND H,L
;LEAVE NAME WHICH COMES 1ST IN ALPHABETICAL ORDER
;POINTED TO BY D,E
;
LEE64:	LXI	B,LLAB-1	;OFFSET TO LAST CHAR OF NAME
	MOV	A,M		;GET 1ST CHAR OF NAME
	ORA	A		;ZERO ?
	JZ	LEE82		;REACHED END OF SYMBOL TABLE
	DAD	B		;POINT TO LAST CHAR
	XCHG			;
	DAD	B		;POINT TO LAST CHAR
	XCHG			;
	INR	C		;C = LENGTH OF NAME
	CALL	COM1		;COMPARE NAMES
	INX	H		;POINT BACK AT 1ST CHAR
	INX	D		;POINT BACK AT 1ST CHAR
	LXI	B,LLAB+2	;LENGTH OF TABLE ENTRY
	JC	LEE7E		;ALREADY IN CORRECT ORDER
	MOV	D,H		;MAKE D,E POINT TO "1ST" NAME
	MOV	E,L		;
LEE7E:	DAD	B		;H,L POINT TO NEXT NAME
	JMP	LEE64		;TST NAMES POINTED TO BY DE, HL
;
;GET HERE WHEN PASS COMPLETED THRU SYMBOL TABLE
;D,E POINT TO NAME WHICH COMES "1ST" IN ALPH. ORDER
;NOTE THAT THE SYMBOLS ARE NOT MOVED IN THE TABLE, BUT
;THAT THEIR 1ST CHAR IS REPLACED WITH 0FFH AS THE ARE PRINTED
;
LEE82:	XCHG			;"1ST" NAME TO D,E
	MOV	A,M		;GET 1ST CHAR OF "LOWEST" NAME
	DCR	A		;IS IT 0FFH ? (IT WASN'T ZERO)
	JM	EOR		;IF SO, RETURN TO ALS-8
	INR	A		;ELSE RESTORE
	SHLD	SYMSV		;AND SAVE IT'S ADDRESS
	CALL	LEEA8		;PRINT IT AND IT'S VALUE
	LDA	SYMX		;GET THE S.T./XREF FLAG
	CPI	'X'		;XREF REQUESTED ?
	JZ	LEAEA		;DO THE CROSS REFERENCE SEARCH
	LDA	SCNT		;ELSE GET SYMBOL COUNT
	INR	A		;INCREMENT IT
	CPI	4		;MAX NO. SYMBOLS PRINTED/LINE
LEE9D:	LHLD	SYMSV		;GET SYMBOL POINTER
	MVI	M,0FFH		;MAKE SYMBOL LAST
	JC	LEE5C		;DO MORE SYMBOLS THIS LINE
	JMP	LEE58		;TO START A NEW LINE
;
;THIS ROUTINE PRINTS NAMES AND THEIR VALUES.
;IT IS USED FOR BOTH THE S.T./XREF AND FOR THE FILES/IODR
;COMMANDS TO LIST THE DIRECTORY CONTENTS
;
LEEA8:	MVI	C,NMLEN		;CAREFUL IF LLAB <> NMLEN !
LEEAA:	MOV	B,A		;SAVE CHAR IN B
	ORA	A		;SET FLAGS
	JNZ	LEEB1		;IF CHAR IS NOT HEX 00
	MVI	B,' '		;PRINT SPACE TO PAD SHORT NAMES
LEEB1:	CALL	OUT8		;PRINT IT
	INX	H		;INCREMENT POINTER
	MOV	A,M		;GET CHAR TO PRINT
	DCR	C		;DCR COUNT OF CHARS LEFT
	JNZ	LEEAA		;DO REMAINING CHARS
	MVI	C,3		;NO OF SPACES TO FOLLOW NAME
	CALL	BLKO		;PRINT THEM
	MOV	D,M		;GET SYMBOL VALUE IN D,E
	INX	H		;2ND BYTE
	MOV	E,M		;IN D,E
	PUSH	H		;SAVE POINTER
	CALL	ADOUT		;PRINT VALUE
	POP	D		;RESTORE POINTER TO D,E
	MVI	C,5		;NO OF SPACES AFTER VALUE
	JMP	BLKO		;PRINT THEM & RETURN
;
;ROUTINE TO SCAN THROUGH SPACES UNTIL NON-BLANK CHAR FOUND
;
SBLK:	LHLD	PNTR		;GET POINTER
SBL1:	MOV	A,M		;GET CHAR AT POINTER
	CPI	' '		;SPACE ?
	RNZ			;NO - DONE
SBL2:	INX	H		;YES - INCREMENT POINTER
	SHLD	PNTR		;AND UPDATE IT
	JMP	SBL1		;THEN CHECK NEW CHAR
;
;THIS ROUTINE IS USED TO CHECK THE CONDITION CODE
;MNEMONICS FOR CONDITIONAL JUMPS, CALLS AND RETURNS.
;
COND:	LXI	H,ABUF+1	;POINT TO 2ND CHAR
	SHLD	ADDS		;SAVE IT'S ADDR.
	MVI	B,2		;MAX. LENGTH OF CONDITION
	JMP	COPC		;TO LOOKUP IN TABLE
;
;HERE IS THE ASSEMBLER OPCODE TABLE
;
;PSEUDO OPS WITH LENGTH OF 4 (OR PADDED TO 4 WITH HEX 0'S)
;COME FIRST
;
OTAB:	DB	'ORG'
	DW	0
	DB	'EQU'
	DW	0100H
	DB	'DB'
	DW	0
	DB	0FFH
	DB	'DS'
	DW	0
	DB	2
	DB	'DW'
	DW	0
	DB	3
	DB	'END'
	DW	0400H
	DB	'COM'
	DW	0500H
	DB	'LST'
	DW	0600H
	DB	'NLST'
	DB	7
	DB	'ASC'
	DW	0800H
	DB	0
;
;THESE ARE FOLLOWED BY 3 CHAR OPCODES (OR 2 CHAR PADDED TO 3)
;
	DB	'HLT'
	DB	118
	DB	'RLC'
	DB	7
	DB	'RRC'
	DB	15
	DB	'RAL'
	DB	23
	DB	'RAR'
	DB	31
	DB	'RET'
	DB	201
	DB	'CMA'
	DB	47
	DB	'STC'
	DB	55
	DB	'DAA'
	DB	39
	DB	'CMC'
	DB	63
	DB	'EI'
	DW	0FB00H
	DB	'DI'
	DW	0F300H
	DB	'NOP'
	DW	0
	DB	'XCHG'
	DB	235
	DB	'XTHL'
	DB	227
	DB	'SPHL'
	DB	249
	DB	'PCHL'
	DW	00E9H
	DB	'STAX'
	DB	2
	DB	'LDAX'
	DW	000AH
	DB	'PUSH'
	DB	197
	DB	'POP'
	DW	0C100H
	DB	'INX'
	DW	0300H
	DB	'DCX'
	DW	0B00H
	DB	'DAD'
	DW	0900H
	DB	0
	DB	'INR'
	DB	4
	DB	'DCR'
	DB	5
	DB	'MOV'
	DB	64
	DB	'ADD'
	DB	128
	DB	'ADC'
	DB	136
	DB	'SUB'
	DB	144
	DB	'SBB'
	DB	152
	DB	'ANA'
	DB	160
	DB	'XRA'
	DB	168
	DB	'ORA'
	DB	176
	DB	'CMP'
	DB	184
	DB	'RST'
	DW	00C7H
	DB	'ADI'
	DB	198
	DB	'ACI'
	DB	206
	DB	'SUI'
	DB	214
	DB	'SBI'
	DB	222
	DB	'ANI'
	DB	230
	DB	'XRI'
	DB	238
	DB	'ORI'
	DB	246
	DB	'CPI'
	DB	254
	DB	'IN'
	DW	0DB00H
	DB	'OUT'
	DB	211
	DB	'MVI'
	DW	0006H
;
;WHICH ARE FOLLOWED BY 4 CHAR OPCODES (OR LESS PADDED TO 4)
;
	DB	'JMP'
	DW	0C300H
	DB	'CALL'
	DB	205
	DB	'LXI'
	DW	0100H
	DB	'LDA'
	DW	3A00H
	DB	'STA'
	DW	3200H
	DB	'SHLD'
	DB	34
	DB	'LHLD'
	DW	002AH
;
;WHICH IS FINALLY FOLLOWED BY THE 2 CHAR CNDX CODE TABLE
;
	DB	'NZ'
	DB	0
	DB	'Z'
	DW	0800H
	DB	'NC'
	DB	16
	DB	'C'
	DW	1800H
	DB	'PO'
	DB	32
	DB	'PE'
	DB	40
	DB	'P'
	DW	3000H
	DB	'M'
	DW	3800H
	DB	0
;
;THIS ROUTINE IS USED TO CHECK A GIVEN OPCODE
;AGAINST THE LEGAL OPCODES IN THE OPCODE TABLE
;
COPC:	LHLD	ADDS		;GET POINTER
	LDAX	D		;FETCH CHARACTER
	ORA	A		;SET FLAGS
	JZ	COP1		;END OF TABLE
	MOV	C,B		;LENGTH OF STRING
	CALL	SEAR		;SEARCH THE TABLE
	LDAX	D		;
	RZ			;RETURN IF MATCH
	INX	D		;NEXT STRING
	JMP	COPC		;CONTINUE SEARCH
COP1:	INR	A		;CLEAR ZERO FLAG
	INX	D		;INCREMENT ADDRESS
	RET			;NO MATCH
;
;THIS ROUTINE CHECKS THE LEGAL OPCODES IN BOTH PASS 1
;AND PASS 2.  IN PASS 1 THE PROGRAM COUNTER IS INCREMENTED
;BY THE CORRECT NUMBER OF BYTES. AN ADDRESS IS
;ALSO SET SO THAT AN INDEXED JUMP CAN BE MADE TO
;PROCESS THE OPCODE FOR PASS 2.
;
OPCD:	LXI	H,ABUF		;GET ADDRESS
	SHLD	ADDS		;SAVE IT
	LXI	D,OTAB		;OPCODE TABLE ADDR.
	MVI	B,4		;LENGTH OF PSEUDO-OP ENTRIES
	CALL	COPC		;LOOK IT UP IN TABLE
	JZ	PSEU		;PSEUDO-OP IF FOUND
	DCR	B		;ELSE TRY 3-CHAR OPCODES
	CALL	COPC		;LOOK IT UP
	JZ	OP1		;IF FOUND IN THIS GROUP
	INR	B		;THEN TRY FOUR CHAR OPCODES
	CALL	COPC		;LOOK IT UP
OP1:	LXI	H,ASTO		;TYPE 1 INSTRUCTIONS
OP2:	MVI	C,1		;1 BYTE INST.
	JZ	OCNT		;IF FOUND
;
OPC2:	CALL	COPC		;CHECK FOR STAX, LDAX
	LXI	H,TYP2		;
	JZ	OP2		;
	CALL	COPC		;CHK FOR PUSH, POP, INX, DCX, DAD
;
	LXI	H,TYP3		;
	JZ	OP2		;
	DCR	B		;3 CHAR OPCODES
	CALL	COPC		;ACC INST: INR, DCR, MOV, RST
;
	LXI	H,TYP4		;
	JZ	OP2		;
;
OPC3:	CALL	COPC		;IMMEDIATE INSTRUCTIONS
	LXI	H,TYP5
	MVI	C,2		;2 BYTE INSTRUCTIONS
	JZ	OCNT		;
	INR	B		;4 CHAR OPCODES
	CALL	COPC		;JMP, CALL, LXI, LDA, STA,
;				;LHLD, SHLD
	JZ	OP4		;
	CALL	COND		;CONDITIONAL INST.
	JNZ	OERR		;ILLEGAL OPCODE
	ADI	192		;ADD BASE VALUE TO RETURN
	MOV	D,A		;
	MVI	B,3		;3 CHARACTER OPCODES
	LDA	ABUF		;FETCH 1ST CHAR
	MOV	C,A		;SAVE IT
	CPI	'R'		;CONDITIONAL RETURN
	MOV	A,D		;
	JZ	OP1		;
	MOV	A,C		;
	INR	D		;FORM CONDITIONAL JUMP
	INR	D		;
	CPI	'J'		;CONDITIONAL JUMP
	JZ	OPAD		;
	CPI	'C'		;CONDITIONAL CALL
	JNZ	OERR		;ILLEGAL OPCODE
	INR	D		;FORM CONDITIONAL CALL
	INR	D		;
OPAD:	MOV	A,D		;GET OPCODE
OP4:	LXI	H,TYP6		;
OP5:	MVI	C,3		;3 BYTE INSTRUCTIONS
OCNT:	STA	TEMP		;SAVE OPCODE
;
;CHECK FOR OPCODE ONLY CONTAINING CORRECT NO. OF CHARS.
;THUS ADDQ, SAY, WOULD GIVE AN ERROR
;
	MVI	A,ABUF AND 0FFH	;LOAD BUFFER ADDRESS
	ADD	B		;LENGTH OF OPCODE
	MOV	E,A		;
	MVI	A,ABUF/256	;
	ACI	0		;GET HIGH ORDER ADDRESS
	MOV	D,A		;
	LDAX	D		;FETCH CHAR AFTER OPCODE
	ORA	A		;IT SHOULD BE ZERO
	JNZ	OERR		;OPCODE ERROR
	LDA	PASI		;FETCH PASS INDICATOR
OCN1:	MVI	B,0		;
	XCHG			;
OCN2:	LHLD	ASPC		;FETCH PROGRAM COUNTER
	DAD	B		;ADD IN BYTE COUNT
	SHLD	ASPC		;STORE PC
	ORA	A		;WHICH PASS
	RZ			;RETURN IF PASS 1
	LDA	TEMP		;FETCH OPCODE
	XCHG			;
	PCHL			;
;
OERR:	LXI	H,ERRO		;SET ERROR ADDRESS
LF0DB:	MVI	C,3		;LEAVE 3 BYTES FOR PATCH
	JMP	OCN1-3		;
;
LF0E0	LXI	H,ERRL
	JMP	LF0DB
;
PSEU:	LXI	H,ABUF+4	;SET BUFFER ADDRESS
	MOV	A,M		;FETCH CHAR AFTER OPCODE
	ORA	A		;IT SHOULD BE ZERO
	JNZ	OERR		;IF NOT
	LDA	PASI		;GET PASS INDICATOR
	ORA	A		;PASS 1 ?
	JZ	PSU1		;YES - JUMP
	JMP	PSU2		;NO - DO 2ND PASS OPERATIONS
;
;THIS ROUTINE IS USED TO PROCESS LABELS.
;IT CHECKS TO SEE IF A LABEL IS IN THE SYMBOL TABLE
;OR NOT.  ON RETURN, Z=1 INDICATES A MATCH WAS FOUND
;AND H,L CONTAIN THE VALUE ASSOCIATED WITH THE LABEL.
;THE REGISTER NAMES A, B, C, D, E, H, L, AND M ARE
;PRE-DEFINED AND NEED NOT BE ENTERED BY THE USER.
;ON RETURN, C=1 INDICATES A LABEL ERROR.
;
SLAB:	CPI	'A'		;CHECK FOR LEGAL CHAR
	RC			;ILLEGAL CHAR
	CPI	'Z'+1		;CHECK FOR LEAGAL CHAR
	CMC			;SETTING CARRY FOR PROPER RET
	RC			;ILLEGAL CHAR
	CALL	ALPS		;PLACE SYMBOL IN ABUF
	LXI	H,ABUF		;POINT TO SYMBOL
	LDA	PASI		;GET PASS INDICATOR
	CPI	2		;DOING XREF/S.T. PASS ?
	INR	A		;BUMP PASS INDICATOR IN ACCUM.
	RNC			;RETURN IF ON XREF/S.T. PASS
	SHLD	ADDS		;SAVE ADDRESS OF SYMBOL
	DCR	B		;CHECK IF ONLY 1 CHAR SYMBOL
	JNZ	SLA1		;LOOK THEM UP IN REG. TABLE
	INR	B		;SET B=1
	LXI	D,RTAB		;POINT TO REGISTER TABLE
	CALL	COPC		;LOOK FOR MATCH
	JNZ	SLA1		;NOT FOUND, TRY SYMBOL TABLE
	MOV	L,A		;FOUND, VALUE TO L
	MVI	H,0		;AND MAKE H ZERO
	STC			;SET CARRY
	CMC			;COMPLEMENT CARRY
	RET			;DONE
SLA1:	LHLD	SYMADD		;GET SYMBOL TABLE ADDR
	XCHG			;TO D,E
	MVI	B,LLAB		;LENGTH OF LABELS
	CALL	COMS		;CHECK TABLE
	RET			;WITH FLAGS SET
;
;HERE IS THE INTERNAL REGISTER TABLE
;
RTAB:	DB	'A'
	DB	7
	DB	'B'
	DB	0
	DB	'C'
	DB	1
	DB	'D'
	DB	2
	DB	'E'
	DB	3
	DB	'H'
	DB	4
	DB	'L'
	DB	5
	DB	'M'
	DB	6
	DB	0
;
;THIS ROUTINE SCANS THE INPUT LINE AND PLACES THE
;OPCODES AND LABELS IN THE ABUF BUFFER.  THE SCAN TERMINATES
;WHEN A NON ALPHANUMERIC CHARACTER (A-Z, 0-9) IS FOUND.
;
ALPS:	MVI	B,0		;SET COUNT
ALP1:	STAX	D		;STORE CHAR IN BUFFER
	INR	B		;INCREMENT COUNT
	MOV	A,B		;FETCH COUNT
	CPI	15		;MAX BUFFER SIZE
	RNC			;RETURN IF BUFFER FILLED
	INX	D		;INCREMENT ABUF POINTER
	INX	H		;INCREMENT INPUT LINE POINTER
	SHLD	PNTR		;SAVE INPUT POINTER
	MOV	A,M		;FETCH CHARACTER
	CPI	'0'		;CHECK FOR LEGAL CHAR
	RC			;ILLEGAL CHAR
	CPI	'9'+1		;AGAIN
	JC	ALP1		;NUMERIC = O.K.
LF154:	CPI	'A'		;TEST FOR LETTER
	RC			;ILLEGAL CHAR
	CPI	'Z'+1		;
	JC	ALP1		;VALID LETTER
	RET			;W/CARRY SET, ILLEGAL CHAR
;
;THIS ROUTINE IS USED TO SCAN THE INPUT LINE AND DETERMINE
;THE VALUE OF AN OPERAND FIELD.  ON RETURN, VALUE IS IN H,L.
;
ASBL:	CALL	SBLK		;GET THE FIRST ARGUMENT
ASCN:	LHLD	PNTR		;FETCH SCAN POINTER
	MOV	A,M		;FETCH CHARACTER
	LXI	H,0		;GET A ZERO
	SHLD	OPRD		;INITIALIZE OPERAND
	INR	L		;L = 1 ==> BECOMES OPRI
	MOV	H,A		;CHAR TO H, BECOMES GTLT
	SHLD	OPRI		;SAVE OPRI AND GTLT
NXT1:	LHLD	PNTR		;GET SCAN POINTER
	DCX	H		;INIT. FOR LOOP BELOW
	CALL	ZBUF		;CLEAR OUT ABUFF
	STA	SIGN		;ZERO SIGN INDICATOR
NXT2:	INX	H		;INCREMENT POINTER
	MOV	A,M		;GET CHAR
	CPI	'<'		;HIGH ORDER BYTE SIGN ?
	JZ	NXT2		;ALREADY TAKEN CARE OF (GTLT)
	CPI	'>'		;LOW ORDER BYTE SIGN ?
	JZ	NXT2		;ALREADY TAKEN CARE OF (GTLT)
	CPI	' '+1		;CAR. RETURN OR SPACE ?
	JC	SEND		;END OF OPERAND FIELD THEN
	CPI	','		;FIELD SEPARATOR ?
	JZ	SEND		;ALSO END OF FIELD
;
;CHECK FOR OPERATORS
;
	CPI	'+'		;CHECK FOR PLUS
	JZ	LF1A6		;STORE 0 AS SIGN
	INR	B		;MAKE B 01
	CPI	'-'		;MINUS SIGN ?
	JZ	LF1A6		;SAVE NON-ZERO SIGN
	INR	B		;MAKE B 02
	CPI	'*'		;CHECK FOR MULTIPLY
	JZ	LF1A6		;STORE B AS 02
	INR	B		;MAKE B 03
	CPI	'/'		;CHECK FOR DIVIDE
	JNZ	ASC2		;IF NOT SIGN, CHK FOR OPERAND
LF1A6:	MOV	A,B		;MOVE B TO A
	STA	SIGN		;SET SIGN BYTE
ASC1:	LDA	OPRI		;FETCH OPERAND INDICATOR
	CPI	2		;CHECK FOR 2 OPERATORS TOGETHER
	JZ	ERRS		;SYNTAX ERROR
	MVI	A,2		;NOW SET UP OPRI AS 2
	STA	OPRI		;AND STORE IT
	JMP	NXT2		;ANOTHER WILL NOT BE ALLOWED
;
;CHECK FOR OPERANDS
;
ASC2:	MOV	C,A		;SAVE CHAR
	LDA	OPRI		;GET OPERATOR
	ORA	A		;CHECK FOR TWO OPERANDS
	JZ	ERRS		;TWO IN A ROW NOT ALLOWED
	MOV	A,C		;RESTORE CHAR
	CPI	'$'		;PGM. COUNTER ?
	JZ	LECC3		;GET IT & CONTINUE
;
;CHECK FOR ASCII CHARACTERS
;
ASC3:	CPI	27H		;QUOTE MARK ?
	JNZ	ASC5		;NO - MUST BE SOMETHING ELSE
	LXI	D,0		;INITIALIZE CHAR. VALUE
	MVI	C,3		;MAX CHAR COUNT + 1
ASC4:	INX	H		;POINT TO NEXT CHAR
	SHLD	PNTR		;SAVE POINTER
	MOV	A,M		;GET CHAR
	CPI	0DH		;CARRIAGE RETURN ?
	JZ	ERRA		;ARGUMENT ERROR THEN
	CPI	27H		;2ND QUOTE MARK ?
	JNZ	SSTR		;NO - PROCESS CHAR
	INX	H		;POINT PAST 2ND QUOTE
	SHLD	PNTR		;UPDATE POINTER
	MOV	A,M		;FETCH NEXT CHAR
	CPI	27H		;CHECK FOR TWO IN A ROW
	JNZ	AVAL+1		;WAS TERMINAL QUOTE
SSTR:	DCR	C		;CHECK COUNT
	JZ	ERRA		;TOO MANY CHARS
	MOV	D,E		;1ST CHAR (IF ANY) IN D
	MOV	E,A		;THIS CHAR IN E
	JMP	ASC4		;GET NEXT CHAR
ASC5:	CPI	'0'		;SEE IF NUMERIC
	JC	ERRA		;NO CHARS < 30H LEGAL
	CPI	'9'+1		;TRY HIGH END
	JNC	ALAB		;ALPHABETIC - TRY LABEL
	CALL	NUMS		;NUMERIC - CONVERT
	JC	ERRA		;ARGUMENT ERROR
AVAL:	XCHG			;OPERAND VALUE IN H,L
	LHLD	OPRD		;FETCH OPERAND VALUE
	XRA	A		;GET A ZERO
	STA	OPRI		;AND CLEAR OPERAND INDICATOR
	LDA	SIGN		;GET SIGN
	CPI	1		;MINUS SIGN ?
	JZ	ASUB		;THEN DO A SUBTACTION
	JNC	LF227		;MULTIPLY OR DIVIDE
	DAD	D		;ADD NEW OPERAND DE TO OLD HL
ASC7:	SHLD	OPRD		;AND UPDATE THE RESULT
	JMP	NXT1		;NOW SEE IF MORE
ASUB:	MOV	A,L		;GET OLD OPRAND IN H,L
	SUB	E		;SUBTRACT NEW OPRAND IN D,E
	MOV	L,A		;RESTORE RESULT TO H,L
	MOV	A,H		;NOW DO HIGH ORDER BYTE
	SBB	D		;
	MOV	H,A		;PUT IT BACK
	JMP	ASC7		;AND FINISH UP
;
;DO MULTIPLY DIVIDE
;
LF227:	MOV	B,D		;MOVE CURRENT OPRD IN DE TO BC
	MOV	C,E		;
	XCHG			;AND OLD OPRND TO D,E
	LXI	H,0		;INITIALIZE ANSWER
	CPI	3		;DOING DIVISION ?
	JZ	LF247		;YES
	CALL	LF238		;NO, MULITPLICATION - DO IT
	JMP	ASC7		;THEN FINISH UP
;
;MULTIPLICATION ROUTINE
;
;THIS ALGORITHM IS INTERESTING BUT DIFFICULT TO UNDERSTAND
;UNTIL STUDIED FOR A WHILE. BUT IT DOES WORK
;
LF238:	MVI	A,16		;16 BITS
LF23A:	DAD	H		;MULTIPLY PARTIAL ANS. BY 2
	XCHG			;CHANGE REGISTERS
	DAD	H		;MULT. MULTIPLIER BY 2
	XCHG			;RESTORE ORIG. REGISTERS
	JNC	LF242		;IF 2X MULTIPLIER ==> NO CARRY
	DAD	B		;ADD MULTIPLICAND TO INTER ANS
LF242:	DCR	A		;DCR NO OF BITS LEFT TO CHECK
	JNZ	LF23A		;DO IT OVER IF NOT DONE
	RET			;ELSE FINAL ANS. IS IN H,L
;
;DIVISION ROUTINE
;
;FIRST CHECK FOR DIVIDE BY ZERO
;
LF247:	MOV	A,B		;GET BYTE OF DIVISOR
	ORA	C		;OR IT WITH OTHER BYTE
	JZ	ASC7		;CAN'T DIVIDE BY ZERO
	CALL	LF253		;DO ACTUALLY DO THE DIVISION
	XCHG			;ANSWER TO H,L
	JMP	ASC7		;TO FINISH UP
;
;DIVISION ROUTINE FOLLOWS. IT IS SIMILAR IN PRINCIPLE TO
;THE MULTIPLICATION ROUTINE
;
LF253:	MVI	A,16		;16 BITS
LF255:	STA	SCNT		;SAVE AS COUNT
	DAD	H		;SHIFT LEFT
	XCHG			;SWITCH REGISTERS
	DAD	H		;SHIFT LEFT
	XCHG			;RESTORE REGISTERS
	JNC	LF260		;IF NO CARRY
	INX	H		;ELSE INCREMENT H,L
LF260:	MOV	A,L		;AND SUBTRACT DIVISOR FROM IT
	SUB	C		;
	MOV	L,A		;
	MOV	A,H		;
	SBB	B		;
	MOV	H,A		;
	INX	D		;INCREMENT PARTIAL ANSWER
	JNC	LF26C		;OK IF NO CARRY
	DAD	B		;ADD DIVISOR TO H,L
	DCX	D		;AND DECREMENT ANSWER
LF26C:	LDA	SCNT		;GET COUNT
	DCR	A		;DECREMENT IT
	JNZ	LF255		;IF NOT DONE, DO MORE
	RET			;ELSE DONE, ANS IN D,E
;
;CHECK FOR SYMBOLS FROM SYMBOL TABLE
;
ALAB:	CALL	SLAB		;SEE IF LABEL IN TABLE
	JZ	AVAL		;IF FOUND
	JC	ERRA		;IF LABEL ERROR
	LDA	PASI		;NOT FOUND, GET PASS IND.
	CPI	2		;DOING S.T./XREF PASS ?
	JNC	LF291		;YES - PROCESS
	LXI	D,SYSYM		;ELSE TRY SYSTEM SYMBOL TABLE
	CALL	COMS		;SEARCH IT
	JZ	AVAL		;IF FOUND
	JMP	ERRU		;ELSE UNDEFINED SYMBOL ERROR
;
;THE FOLLOWING ROUTINE IS USED TO HANDLE SYMBOLS DURING A
;SYMBOL TABLE/XREF PASS (3RD PASS, PASI = 2).
;DOES CROSS REFERENCE
;
LF291:	XCHG			;D,E ==> SYMBOL NAME IN ABUF
	LHLD	SYMSV		;SYMBOL DOING XREF PASS FOR
	MVI	C,LLAB		;LENGTH OF SYMBOL
	CALL	SEAR		;SAME ?
	JNZ	LF2C2		;NO
	LXI	H,SCNT		;POINT TO SYMBOL COUNT
	INR	M		;INCREMENT IT
	MOV	A,M		;GET IT
	CPI	12		;MAX. NO ON ONE LINE ?
	JC	LF2B1		;NO - DO MORE THIS LINE
	MVI	M,1		;YES - RESET COUNT
	CALL	CRLF		;DO CAR RET/LINE FEED
	MVI	C,17		;AND PRINT 17 SPACES
	CALL	BLKO		;DO IT
LF2B1:	LXI	H,IBUF-5	;POINT TO LINE NO.
	MVI	C,4		;LENGTH OF LINE NO
LF2B6:	MOV	B,M		;GET A CHAR
	CALL	OUT8		;PRINT IT
	INX	H		;POINT TO NEXT CHAR
	DCR	C		;DECR CHAR COUNT
	JNZ	LF2B6		;DO NEXT CHAR IF NOT DONE
	CALL	LE35C		;PUT OUT A SPACE AFTER LINE NO
LF2C2:	XRA	A		;CLEAR FLAGS
	MVI	H,0		;AND H,L
	JMP	AVAL		;AND CONTINUE SEARCH
;
;ROUTINE TO CHECK FOR TERMINATING CHARACTERS IN LABEL FILEDS
;
SEND:	LDA	OPRI		;FETCH OPERAND INDICATOR
	ORA	A		;SET FLAGS
	JNZ	ERRS		;SYNTAX ERROR
	LHLD	OPRD		;GET OPERAND VALUE
	LDA	GTLT		;GET SHIFT INDICATOR
	CPI	'<'		;USING HIGH HALF ONLY ?
	JNZ	LF2DE		;NO - OK AS IS
	MOV	L,H		;YES - MOVE HIGH HALF TO L
	JMP	LF2E3		;AND CLEAR HIGH HALF
LF2DE:	CPI	'>'		;USING LOW HALF ONLY ?
	JNZ	SEN1		;NO - OK AS IS THEN
LF2E3:	MVI	H,0		;ELSE CLEAR HIGH HALF
SEN1:	MOV	A,H		;GET HIGH ORDER BYTE
	LXI	D,TEMP		;GET ADDRESS
	ORA	A		;SET FLAGS
	RET			;DONE
;
;GET A NUMERIC VALUE, HEX, OCTAL, OR DECIMAL
;
NUMS:	CALL	ALPS		;PUT CHARS IN ABUFF
	DCX	D		;POINT TO LAST CHAR
	LDAX	D		;GET LAST CHAR
	LXI	B,ABUF		;B,C POINT TO NUMBER
	CPI	'H'		;HEX ?
	JZ	NUM2		;YES - PROCESS
	CPI	'Q'		;OCTAL ?
	JZ	NUM3		;YES - PROCESS
	CPI	'D'		;DECIMAL ?
	JNZ	ADEC		;PROCESS DECIMAL BY DEFAULT
NUM1:	XRA	A		;GET BINARY ZERO
	STAX	D		;CLEAR THE TYPE LETTER
	JMP	ADEC		;PROCESS DECIMAL
NUM2:	XRA	A		;GET A BINARY ZERO
	STAX	D		;CLEAR THE TRAILING H
	JMP	AHEX		;PROCESS HEX
NUM3:	XRA	A		;GET A BINARY ZERO
	STAX	D		;CLEAR THE TRAILING Q
	JMP	AOCT		;PROCESS OCTAL
;
;FOLLOWING ARE THE ERROR REPORTING ROUTINES
;
ERRR:	MVI	A,'R'		;REGISTER ERROR
	LXI	H,0		;CLEAR H,L
	STA	OBUF+18		;WHERE THE ERROR LETTER GOES
	RET			;DONE
ERRS:	MVI	A,'S'		;SYNTAX ERROR
	STA	OBUF+18		;WHERE THE ERROR LETTER GOES
	LXI	H,0		;CLEAR H,L
	JMP	SEN1		;FINISH UP & GO HOME
ERRU:	MVI	A,'U'		;UNDEFINED SYMBOL
	JMP	ERRS+2
ERRV:	MVI	A,'V'		;VALUE ERROR
	JMP	ERRR+2
ERRM:	MVI	A,'M'		;MISSING LABEL
	STA	OBUF+18		;WHERE THE ERROR LETTER GOES
	JMP	LEB41		;FINISH STATEMENT PROCESSING
ERRA:	MVI	A,'A'		;ARGUMENT ERROR
	JMP	ERRS+2
ERRO:	MVI	A,'O'		;OPCODE ERROR
	STA	OBUF+18		;WHERE ERROR LETTER GOES
	LDA	PASI		;GET PASS INDICATOR
	ORA	A		;SET FLAGS
	RZ			;RET IF ON 1ST PASS
	MVI	C,3		;ELSE SET UP TO LEAVE 3 BYTES
ERO1:	XRA	A		;GET A BINARY ZERO
	CALL	ASTO		;PUT IT IN MEMORY & LISTING
	DCR	C		;DECR COUNT
	JNZ	ERO1		;DO MORE IF NOT DONE
	RET			;DONE - ROOM LEFT FOR PATCH
ERRL:	MVI	A,'L'		;LABEL ERROR
	JMP	ERRO+2
ERRD:	MVI	A,'D'		;DUPLICATE LABEL
	STA	OBUF+18		;WHERE ERROR LETTER GOES
	CALL	LEB41		;DISPLAY THE ERROR
	JMP	OPC		;PROCESS OPCODE
;
;FOLLOWING IS THE LINE FORMATING ROUTINE
;
;IT IS BEING LEFT UN-COMMENTED SO THAT YOU MAY TRY TO
;COMMENT IT YOURSELF & THEREFORE HAVE A BETTER APPRECIATION
;OF THE WORK I HAVE GONE TO - NOTE THAT IT IS LESS THAN TWO
;PAGES LONG, AND WE ARE NOW OVER 50 PAGES INTO THIS MONSTER.
;HAVE FUN.  (PS - I HAVE GONE TO THE TROUBLE OF PUTING
;IN SYMBOLIC REFERENCES TO MAKE THE CODE RE-ASSEMBLEABLE)
;
LF361:	MVI	C,0
	LXI	H,IBUF
	MOV	A,M
	CPI	COMCHR
	RZ
	MVI	B,2
	CALL	LF37A
	RC
	INR	B
	CALL	LF37A
	RC
	MVI	D,2
	JMP	LF37C
LF37A:	MVI	D,1
LF37C:	MOV	A,B
	ADD	D
	MOV	B,A
	LDA	TERMW
	SUI	(IBUF+81) AND 0FFH
	JZ	LF392
	JNC	LF38E
	DCR	B
	JMP	LF392
LF38E:	MOV	A,D
	RAL
	ADD	B
	MOV	B,A
LF392:	MOV	A,B
	ADI	5
	MOV	B,A
LF396:	MOV	E,D
LF397:	INR	C
	MOV	A,M
	CPI	20H
	RC
	INX	H
	JNZ	LF396
	DCR	E
	JNZ	LF397
LF3A4:	INR	C
	MOV	A,M
	CPI	20H
	RC
	INX	H
	JZ	LF3A4
	MOV	A,C
	SUB	B
	RNC
	DCX	H
	DCX	H
	MVI	M,0
	MOV	C,A
	DCR	D
	JNZ	LF3C5
	LHLD	PNTR
	CMA
	INR	A
	MOV	E,A
	MVI	D,0
	DAD	D
	SHLD	PNTR
LF3C5:	MOV	L,C
	MVI	H,0FFH
	MVI	C,0
	LXI	D,IBUF+82
	DAD	D
	XCHG
	CALL	RMOV
	XCHG
LF3D3:	INX	H
	MVI	M,20H
	MOV	A,L
	CMP	E
	JNZ	LF3D3
	INX	H
	INX	H
	MOV	C,B
	RET
LF3DF:	LDA	TERMW
	INR	A
	RET
;
;FOLLOWING IS THE CODE TO SET THE TERMINAL WIDTH
;NOTE THAT WHAT IS ACTUALLY STORED IS THE LOW ORDER BYTE
;OF THE 1ST ADDR BEYOND THE BUFFER END, NOT THE WIDTH ITSELF.
;
TERM:	LXI	B,ABUF		;POINT TO KEYED IN VALUE
	CALL	ADEC		;CONVERT TO BINARY
	MOV	A,L		;VALUE TO A
	SUI	(-(IBUF+1)) AND 0FFH
	CPI	(IBUF+120) AND 0FFH
	JNC	WHAT		;IF TERMW > 120 SPECIFIED
	STA	TERMW		;SAVE IT
	JMP	EORMS		;DONE
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
;
; ****** END OF ALS8ASM MODULE
;
;
;THIS IS THE INTERPRETIVE DEBUGGING SIMULATOR
;IT'S BASIC OPERATION IS TO SIMULATE ALL OF THE 8080
;REGISTERS IN MEMORY, & THEN MOVE THE INST. TO BE
;SIMULATED INTO A 3 BYTE AREA IN RAM AND EXECUTE IT
;FOLLOWED BY A JUMP INST WHICH RETURNS CONTROL TO THE
;ROUTINE.  A SIMULATOR SIMILAR TO THIS WAS DESCRIBED IN
;DETAIL IN SEPT. 77 KILOBAUD PG. 64.  HOWEVER ALTHOUGH
;THE PRINCIPLE IS THE SAME, THE CODE IS QUITE DIFFERENT.
;THE SIMULATOR ENTRY POINT IS AT F75C.
;
;COME HERE TO "SIMULATE" A SINGLE INSTRUCTION
;
LF400:	LXI	H,0		;GET TWO ZEROS
	SHLD	LD14C+1		;CLEAR 2ND & 3RD INST BYTES
	LHLD	LD13C		;GET PGM COUNTER
	MOV	A,M		;GET NEXT INST TO SIMULATE
	STA	LD14C		;SAVE IT IN INST REG
	MOV	B,A		;AND IN B
	CPI	40H		;TRYING TO DETERMINE TYPE INST
	JC	LF422		;FOR FURTHER TESTING
	CPI	0C0H		;MORE TESTING
	JNC	LF475		;INST >= C0 HEX
	JMP	LF459		;1 BYTE ACCUM INST
;
;RETURN HERE TO PROCESS 1 BYTE ACCUM. INST
;
LF41B:	INX	H		;INR PGM COUNTER
	SHLD	LD13E		;SAVE ADDR OF NEXT INST
	JMP	LF634		;PROCESS THE INST
;
;GET HERE FOR INST WITH OPCODES LESS THAN 40H
;
LF422:	ANI	7		;MASK LOW 3 BITS
	JZ	LF41B		;NOP IS ONLY LEGAL 8080 INST
	CPI	3		;MASK LOW ORDER TWO BITS
	JC	LF439		;01,02,09,0A,..,31,32,39,3A ETC
	CPI	6		;CHECK FOR MVI
	JNZ	LF41B		;JMP IF NOT MVI
;
;COME HERE FOR ACCUMULATOR IMMEDIATE INST (MVI, ADI, CPI, ETC)
;
LF431:	INX	H		;POINT TO 2ND BYTE
	MOV	A,M		;GET IT
	STA	LD14C+1		;SAVE AS 2ND BYTE TO SIMULATE
	JMP	LF41B		;SIMULATE INST. EXECUTION
;
;COME HERE FOR LXI, STAX, DAD, LDAX, SHLD, LHLD, STA, LDA
;
LF439:	CPI	2		;STAX/LDAX,SHLD/LHLD,STA/LDA
	MOV	A,B		;RESTORE THE FULL OPCODE
	JZ	LF451		;FOR LIST 2 INST PREV.
	ANI	8		;CHECK FOR DAD
	JNZ	LF41B		;PROCESS DAD INST
LF444:	INX	H		;POINT TO 2ND BYTE
	MOV	A,M		;GET IT
	STA	LD14C+1		;PUT IT IN SIM'S INST REG
	INX	H		;POINT TO 3RD BYTE
	MOV	A,M		;GET IT
	STA	LD14C+2		;PUT IT IN AS 3RD BYTE
	JMP	LF41B		;SIMULATE EXECUTION OF THE INST
;
;COME HERE FOR STAX, LDAX, SHLD, LHLD, STA, LDA
;
LF451:	CPI	20H		;DIVIDE GROUP IN 2 PARTS
	JNC	LF444		;FOR SHLD/LHLD, STA/LDA
	JMP	LF41B		;FOR LDAX/STAX
;
;GET HERE FOR 1 BYTE ACCUM. INST > 40H AND < C0H
;MOV,CMP,ANA,ADD,ADC,SUB,SBB,XRA,ORA AND HLT
;
LF459:	CPI	76H		;HALT INST ?
	JZ	LF461		;YES - PROCESS IT
	JMP	LF41B		;NO - PROCESS OTHERS
;
;PROCESS HALT INST
;
LF461:	CALL	CRLF		;DO CR/LF
	CALL	LF6B8		;PRINT OUT SIMULATORS P.C.
	LXI	H,LF470		;POINT TO HALT MESSAGE
	CALL	SCRN		;PRINT "HALT"
	JMP	LF774		;AND THEN RESTART SIMULATOR
LF470:	DB	'HALT',0DH
;
;COME HERE FOR INST WITH OPCODES >= C0 HEX
;
LF475:	ANI	7		;MASK LOW 3 BITS
	JZ	LF49F		;CONDITIONAL RETURN
	CPI	2		;CONDITIONAL JUMP ?
	JZ	LF4CA		;YES - PROCESS CNDX JMP
	JC	LF4B0		;POP, RET, PCHL, SPHL
	CPI	4		;CONDITIONAL CALL ?
	JZ	LF505		;YES - PROCESS IT
	JC	LF4EF		;NO-JMP,IN,OUT,EI,DI,XTHL,XCHG
	CPI	6		;ACCUM. IMMEDIATE ?
	JZ	LF431		;YES - PROCESS
	JC	LF542		;PUSH, CALL & ILLEGAL
;
;GET HERE TO PROCESS RST INSTRUCTIONS
;
	XRA	A		;GET A ZERO
	STA	LD13E+1		;CLEAR HIGH ORDER CALLED ADDR
	MOV	A,B		;RESTORE OPCODE TO A
	ANI	38H		;MASK RST TYPE
	STA	LD13E		;STORE AS LOW ORDER BYTE
	JMP	LF511		;PROCESS AS NORMAL CALL
;
;COME HERE FOR CONDITIONAL RETURN
;
LF49F:	CALL	LF551		;OPERATE ON OPCODE & FLAG REG
	JNZ	LF4DA		;CNDX NOT MET,CLEAN UP, GO HOME
;
;COME HERE TO PROCESS RETURN
;
LF4A5:	XCHG			;SAVE PGM CTR IN D,E
	LHLD	LD140		;GET STACK POINTER H,L
	CALL	LF57F		;POP STK & SAVE AS NEXT ADDR
	INX	H		;INR STACK POINTER FOR 2ND BYTE
	JMP	LF521		;RESET STK PTR & GO TO NXT INST
;
;COME HERE FOR POP, RET, PCHL, SPHL
;
LF4B0:	MOV	A,B		;RESTORE INST TO A
	ANI	8		;POP INST ?
	JZ	LF41B		;YES - PROCESS IT
	MOV	A,B		;NO - RESTORE INST AGAIN
	CPI	0D9H		;ILLEGAL OPCODE ?
	JZ	LF589		;YES - PROCESS ILLEGAL OPCODE
	JC	LF4A5		;NO - RETURN INST IF CARRY
	CPI	0E9H		;NOT RET - PCHL ?
	JNZ	LF41B		;NO - MUST BE SPHL
	LHLD	LD144		;PCHL - GET H,L
	JMP	LF4DB		;MAKE ADDR OF NEXT INST & RET
;
;COME HERE FOR CONDITIONAL JUMP
;
LF4CA:	CALL	LF551		;EVALUATE CONDITION
;
;GET HERE FOR STD JUMP
;
LF4CD:	CALL	LF4E1		;FILL IN 2ND & 3RD BYTES
	JNZ	LF4D9		;JMP IF CNDX NOT MET
	CALL	LF57F		;UPDATE ADDR OF NXT INST
	JMP	LF66A		;DONE W/SIMULATED JUMP
LF4D9:	INX	H		;POINT TO 3RD BYTE
LF4DA:	INX	H		;POINT TO NEXT INST
LF4DB:	SHLD	LD13E		;SAVE H,L AS ADDR OF NXT INST
	JMP	LF66A		;DONE WITH THIS INST
;
;UPDATE 2ND & 3RD BYTES OF INST AT D14C
;DONE EVEN IF INST IS NOT REALLY EXECUTED SO DISPLAY
;OF INST WILL BE CORRECT.
;NOTE REVERSAL OF "BACKWARD" 8080 ADDRESSES
;
LF4E1:	PUSH	PSW		;SAVE PSW
	INX	H		;POINT TO INST 2ND BYTE
	MOV	A,M		;GET IT
	STA	LD14C+2		;SAVE AS SIM 2ND (3RD?) BYTE
	INX	H		;POINT TO INST 3RD BYTE
	MOV	A,M		;GET IT
	STA	LD14C+1		;SAVE AS SIM 3RD (2ND?) BYTE
	DCX	H		;POINT BACK AT 2ND INST BYTE
	POP	PSW		;RESTORE PSW
	RET			;DONE
;
;GET HERE FOR JMP, OUT, IN, XTHL, XCHG, EI, DI INSTRUCTIONS
;
LF4EF:	MOV	A,B		;GET WHOLE INST
	ANI	38H		;MASK
	JZ	LF4CD		;JUMP INST
	CPI	10H		;
	JZ	LF5F2		;OUT INST
	JC	LF589		;ILLEGAL OPCODE
	CPI	18H		;MASK AGAIN
	JZ	LF58F		;INPUT INST
	JMP	LF41B		;EI, DI, XTHL, XCHG
;
;COME HERE FOR CONDITIONAL CALL INST
;
LF505:	CALL	LF551		;EVALUATE CONDITION
	JNZ	LF4CD		;JUMP IF NOT MET
;
;GET HERE FOR CALL INST
;
LF50B:	CALL	LF4E1		;UPDATE DISPLAY INST
	CALL	LF57F		;CALLED ADDR ==> NXT INST
LF511:	INX	H		;POINT TO INST AFTR CALL
	XCHG			;SAVE RET ADDR IN D,E
	LDA	LD135		;GET REAL-TIME RUN FLAG
	ORA	A		;SET FLAGS
	JNZ	LF527		;JUMP IF SIMULATING
LF51A:	LHLD	LD140		;GET STACK POINTER
	DCX	H		;POINT TO NEXT ENTRY 1ST BYTE
	MOV	M,D		;PUT HIGH ORDER RET ADDR IN
	DCX	H		;NOW DO LOW ORDER BYTE
	MOV	M,E		;RET ADDR ON STACK
LF521:	SHLD	LD140		;UPDATE STACK POINTER
	JMP	LF66A		;SIMULATED CALL DONE
LF527:	LHLD	LD13E		;GET CALLED ADDR
	LDA	LD13A		;GET LOW ORDER R.T. RUN ADDR
	CMP	L		;SAME ?
	JNZ	LF51A		;NO - SIMULATE CALL
	LDA	LD13A+1		;GET HIGH ORDER R.T. RUN ADDR
	CMP	H		;SAME ?
	JNZ	LF51A		;NO - SIMULATE CALL
	SHLD	LD14C+1		;SAME - PUT CALL ADDR IN
	XCHG			;RET ADDR TO H,L
	SHLD	LD13E		;NEXT SIM. ADDR TO EXEC
	JMP	LF634		;EXECUTE CALL FOR REAL
;
;GET HERE FOR PUSH, CALL & ILLEGAL OPCODES
;
LF542:	MOV	A,B		;RESTORE INSTRUCTION
	ANI	8		;MASK
	JZ	LF41B		;PUSH, POP
	MOV	A,B		;RESTORE OPCODE AGAIN
	CPI	0CDH		;CALL ?
	JZ	LF50B		;YES - PROCESS IT
	JMP	LF589		;ILLEGAL OPCODE
;
;GET HERE TO EVALUATE CONDITION FOR CONDITIONAL JMP, CALL, RET
;
LF551:	MOV	A,B		;RESTORE OP CODE
	ANI	8		;MASK CNDX TRUE/FALSE BIT
	MOV	C,A		;SAVE TRUE/FALSE STATUS
	JZ	LF55A		;JUMP IF NZ,NC,PO,P
	MVI	C,0C5H		;PSW COND FLAG MASK
LF55A:	MOV	A,B		;RESTORE OPCODE AGAIN
	ANI	30H		;ZERO FLAG CONDITIONAL ?
	JNZ	LF565		;NO - TEST OTHERS
	MVI	D,40H		;PSW ZERO FLAG MASK
	JMP	LF579		;EVALUATE THE CONDITION
LF565:	CPI	20H		;PARITY/SIGN FLAG CONDITION ?
	JZ	LF572		;YES - PARITY FLAG CNDX
	JNC	LF577		;YES - SIGN FLAG CNDX
	MVI	D,1		;CARRY FLAG MASK
	JMP	LF579		;EVALUATE CONDITION
LF572:	MVI	D,4		;PARITY FLAG BIT MASK
	JMP	LF579		;EVALUATE THE CONDITION
LF577:	MVI	D,80H		;SIGN FLAG BIT MASK
LF579:	LDA	LD142		;GET SIMULATOR'S FLAG REGISTER
	XRA	C		;SET CNDX & T/F INTO ACC
	ANA	D		;MASK OUT PROPER FLAG BIT
	RET			;AND GO BACK W/ZERO FLAG SET
;
;SAVE ADDR POINTED TO BY H,L AS NEXT INST TO EXECUTE
;
LF57F:	MOV	A,M		;GET 1ST BYTE
	STA	LD13E		;SAVE IT AS NEXT INST LOW BYTE
	INX	H		;POINT TO 2ND BYTE
	MOV	A,M		;GET IT
	STA	LD13E+1		;SAVE AS HIGH BYTE
	RET			;DONE
;
;ROUTINE TO PROCESS ILLEGAL OPCODES
;
LF589:	CALL	LF6CA		;DISPLAY INST & ALL REGS
	CALL	LF949		;PRINT ?, RESTART (NEVER RET)
;
;ROUTINE TO PROCESS INPUT INST
;
LF58F:	INX	H		;POINT TO PORT
	MOV	A,M		;GET IT
	INX	H		;POINT TO NEXT INST
	SHLD	LD13E		;AND MAKE IT NEXT TO EXEC
	STA	LD14C+1		;PUT PORT INTO SIM'S INST REG
	CALL	LF8A1		;SEARCH INPUT PORT TABLE
	JNZ	LF5AE		;JUMP IF PORT NOT IN TABLE
	MOV	A,M		;GET PORT I/O TYPE
	ORA	A		;SET FLAGS
	JZ	LF5AE		;IF PORT SIMULATED
	JM	LF634		;TO REALLY EXEC I/O INST
	INX	H		;ELSE PRESET, POINT TO VALUE
	MOV	A,M		;GET IT
	STA	LD14A		;TO SIM'S ACCUM (WHERE ELSE ?)
	JMP	LF66A		;TO DISPLAY & DO NEXT INST
;
;COME HERE TO EXECUTE SIMULATED INPUT INST
;
LF5AE:	LXI	D,LF5D2		;POINT TO INPUT MESSAGE
	CALL	LF5D9		;PRINT PGM CTR & MESSAGE
	CALL	READ		;GET USER'S ANSWER
	CALL	ZBUF		;CLEAR ABUF
	LXI	H,IBUF		;POINT TO INPUT BUFFER
	CALL	SBL1		;SCAN PAST SPACES
	CALL	NUMS		;CONVERT TO BINARY
	JC	LF949		;IF ERROR IN ANSWER
	MOV	A,H		;GET HIGH ORDER BYTE
	ORA	A		;SET FLAGS
	JNZ	LF5AE		;MAKE USER DO IT AGAIN IF > 255
	MOV	A,L		;GET LOW ORDER BYTE
	STA	LD14A		;STUFF IT INTO SIM'S ACCUM
	JMP	LF626		;DO CR/LF & FINSIH UP
;
LF5D2:	DB	'INPUT '
	DB	0DH
;
;ROUTINE TO PRINT INPUT OR OUTPUT MESSAGE FOR SIMULATED I/O
;
LF5D9:	CALL	CRLF		;DO CR/LF
	PUSH	D		;SAVE D,E
	CALL	LF6B8		;PRINT PGM COUNTER & SPACES
	POP	D		;RESTORE REGS
	XCHG			;MESSAGE ADDR TO H,L
	CALL	SCRN		;PRINT INPUT OR OUTPUT MSG
	LHLD	LD13C		;GET SIM'S PGM CTR
	INX	H		;INCR, POINTING TO PORT
	MOV	A,M		;GET PORT IN ACCUM
	CALL	DUMO		;PRINT PORT
	MVI	B,'='		;FOLLOWED BY EQUALS SIGN
	JMP	OUT8		;AND THEN RETURN
;
;ROUTINE TO PROCESS OUTPUT INSTRUCTION
;
LF5F2:	INX	H		;POINT TO PORT
	MOV	A,M		;GET IT
	INX	H		;POINT TO NEXT INST
	SHLD	LD13E		;SAVE AS ADDR OF NEXT INST
	STA	LD14C+1		;PUT PORT IN SIM'S INST REG
	CALL	LF897		;SEARCH OUTPUT TABLE
	MVI	A,1		;ASSUME SIMULATED
	JNZ	LF604		;IF PORT NOT IN TABLE
	MOV	A,M		;GET TYPE OUTPUT
LF604:	ORA	A		;SET FLAGS
	JM	LF634		;TO REALLY EXECUTE OUT INST
	PUSH	PSW		;SAVE ACCUM & FLAGS
	LXI	D,LF62C		;POINT TO OUTPUT MESSAGE
	CALL	LF5D9		;PRINT IT
	POP	PSW		;RESTORE FLAGS & ACCUM
	ORA	A		;SET FLAGS
	LDA	LD14A		;GET CONTENTS OF SIM'S ACCUM
	MOV	B,A		;MOVE TO B
	JZ	LF61E		;ASCII MODE (UNLESS CNTL CHAR)
LF618:	CALL	LF747		;PRINT ACC USING CUR MODE
	JMP	LF626		;DO CR/LF, PRINT REGS & DO NEXT
LF61E:	CPI	20H		;TEST FOR CONTROL CHAR
	JC	LF618		;PRT USING CUR MODE, NOT ASCII
	CALL	OUT8		;NOT CNTL CHAR, OK TO OUTPUT
LF626:	CALL	CRLF		;NOW DO CR/LF TO MAKE IT PRETTY
	JMP	LF66A		;THEN PRINT REGS & DO NEXT INST
;
LF62C:	DB	'OUTPUT '
	DB	0DH
;
;COME HERE TO EXECUTE AN INST.
;LOAD REAL 8080 REGS FROM SIMULATORS REGS, EXEC INST
;AND THEN UNLOAD 8080'S REGS TO SIMULATORS REGS
;
LF634:	LXI	SP,LD140	;POINT STACK AT SIMULATORS REGS
	MVI	A,0C3H		;JUMP INST
	STA	LD14F		;STORE JUST AFTER INST TO SIMUL
	LXI	H,LF652		;RETURN POINT AFTER INST EXECUT
	SHLD	LD14F+1		;STORE IT JUST AFTER JUMP INST
	POP	H		;LOAD 8080 H,L FROM SIM STK PTR
	POP	PSW		;LOAD 8080 PSW FROM SIMULATOR
	INX	SP		;SKIP L FOR NOW
	INX	SP		;SKIP H FOR NOW
	POP	D		;LOAD 8080 D,E FROM SIMULATOR
	POP	B		;LOAD 8080 B,C FROM SIMULATOR
	SPHL			;MOVE SIM STACK TO 8080 STACK
	LHLD	LD144		;LOAD 8080 H,L FROM SIM H,L
	LDA	LD14A		;GET SIMULATED ACCUM
	JMP	LD14C		;EXECUTE INST TO BE SIMULATED
;
;RETURN HERE AFTER EXECUTING THE "SIMULATED" INST
;
LF652:	STA	LD14A		;SAVE 8080 ACCUM INTO SIMULTR
	SHLD	LD144		;SAVE 8080 H,L INTO SIMULATOR
	RAL			;SAVE CARRY FLAG DURING DAD
	LXI	H,0		;SETTING UP ....
	DAD	SP		;TO GET THE STACK POINTER
	LXI	SP,LD14A	;POINT CPU STACK TO REG AREA
	PUSH	B		;SAVE 8080 B,C INTO SIMULATOR
	PUSH	D		;SAVE 8080 D,E INTO SIMULATOR
	DCX	SP		;SKIP H (ALREADY STORED)
	DCX	SP		;SKIP L (ALREADY STORED)
	RAR			;RESTORE CARRY FLAG
	PUSH	PSW		;SAVE 8080 PSW INTO SIMULATOR
	PUSH	H		;SAVE 8080 STK PNTR INTO SIM
	LXI	SP,LD12B	;RELOAD 8080'S STACK POINTER
LF66A:	IN	0FFH		;GET SENSE SWITCHES
	ANI	80H		;MASK HIGH ORDER BIT
	JNZ	LF697		;FORCE RETURN TO COMMAND MODE
	CALL	STAT		;SEE IF KEYBOARD CHAR WAITING
	JZ	LF67F		;NO - CONTINUE PROCESSING
	CALL	IN8		;YES - GET CHAR
	CPI	'X'-40H		;CONTROL-X ?
	JZ	LF697		;YES - FORCE RET TO COMND MODE
LF67F:	LDA	LD134		;GET BREAKPOINT FLAG
	ORA	A		;SET FLAGS
	JZ	LF69D		;JMP IF NO BKPT SET
	LHLD	LD138		;BKPT ADDR TO H,L
	LDA	LD13C+1		;HIGH BYTE OF SIM P.C.
	CMP	H		;COMPARE TO BKPT
	JNZ	LF6AF		;BKPT NOT REACHED
	LDA	LD13C		;GET LOW BYTE OF P.C.
	CMP	L		;COMPARE TO BKPT
	JNZ	LF6AF		;BKPT NOT REACHED
;
;COME HERE WHEN BREAKPOINT IS REACHED
;
LF697:	CALL	LF6CA		;PRINT REGS, P.C., ETC.
	JMP	LF774		;RESTART SIMULATOR
;
;GET HERE AFTER EA. INST IN SIMULATED CONT. RUN MODE
;
LF69D:	CALL	LF6CA		;PRINT REGS, PC, ETC
	IN	0FFH		;GET SENSE SWITCHES
	ANI	40H		;MASK CONTINUOUS RUN BIT
	CZ	IN8		;IF CONT RUN, CK KYBD PORT
	CPI	'X'-40H		;CONTROL-X WAITING ?
	JZ	LF774		;YES - RETURN TO SIM COMND MODE
;
;SIMULATOR "GO" COMMAND
;
LF6AC:	CALL	CRLF		;DO CR/LF
LF6AF:	LHLD	LD13E		;GET ADDR OF INST TO SIMULATE
	SHLD	LD13C		;AND SAVE IT AS SIM PGM COUNTER
	JMP	LF400		;SIMULATE THE INSTRUCTION
;
;ROUTINE TO PRINT OUT SIMULATORS P.C. AND TWO SPACES
;
LF6B8:	LDA	LD13C+1		;GET HIGH ORDER SIM P.C. BYTE
	MOV	D,A		;TO D
	LDA	LD13C		;NOW LOW ORDER BYTE
	MOV	E,A		;D,E HAVE P.C.
	CALL	ADOUT		;PRINT IT IN HEX
	CALL	LE35C		;PRINT SPACE
	CALL	LE35C		;PRINT SPACE
	RET			;DONE
;
;ROUTINE TO PRINT OUT SIMULATORS PC AND ALL FLAGS & REGS
;
LF6CA:	CALL	LF6B8		;PRINT PC & SPACES
	LDA	LD142		;GET FLAG REGISTER
	MOV	C,A		;SAVE IT IN C
	ANI	01H		;MASK CARRY BIT
	CALL	LF73C		;PRINT A 0 OR 1
	ANI	80H		;MASK SIGN BIT
	CALL	LF73C		;PRINT A 0 OR 1
	ANI	10H		;MASK AUX CARRY BIT
	CALL	LF73C		;PRINT A 0 OR 1
	ANI	04H		;MASK PARITY BIT
	CALL	LF73C		;PRINT A 0 OR 1
	ANI	40H		;MASK ZERO BIT
	CALL	LF73C		;PRINT A 0 OR 1
	CALL	LE35C		;PRINT A SPACE
	LXI	D,LD14A		;POINT TO ACCUM
	LDAX	D		;GET IT
	CALL	LF756		;PRINT IT USING CUR. MODE
	CALL	LE35C		;PRINT SPACE
	MVI	C,04H		;NO OF REGS TO OUTPUT
LF6F9:	DCX	D		;POINT TO NEXT REG
	LDAX	D		;GET IT
	CALL	LF756		;PRINT IT USING CUR MODE
	DCR	C		;NO OF REGS LEFT
	JNZ	LF6F9		;DO NEXT IF NOT DONE
	CALL	LE35C		;PRINT SPACE
	DCX	D		;POINT TO H
	LDAX	D		;GET IT
	CALL	LF756		;PRINT IT
	DCX	D		;POINT TO L
	LDAX	D		;GET IT
	CALL	LF756		;PRINT IT
	LHLD	LD144		;GET H,L
	MOV	A,M		;GET "M" CHAR
	CALL	LF756		;PRINT IT
	CALL	LE35C		;SPACE
	LDA	LD140+1		;STACK PTR HIGH BYTE
	MOV	D,A		;TO D
	LDA	LD140		;STACK PTR LOW BYTE
	MOV	E,A		;D,E HAS STK PTR ADDR
	CALL	ADOUT		;PRINT STACK POINTER
	LXI	D,LD14C		;POINT TO CURRENT INST
	CALL	LE35C		;PRINT SPACE
	CALL	LF733		;PRINT BYTE & SPACE
	CALL	LF733		;PRINT BYTE & SPACE
	JMP	LF733		;A BIT OF SLOPPY CODE
LF733:	CALL	LE35C		;PRINT A SPACE
	LDAX	D		;GET BYTE POINTED TO BY D,E
	INX	D		;POINT TO NEXT
	CALL	LF747		;PRINT THE BYTE
	RET			;DONE
;
;PRINT A 1 OR A ZERO (USED TO PRINT FLAG BYTES)
;
LF73C:	MVI	B,'1'		;ASSUME 1
	JNZ	LF742		;MUST BE IF IT'S NOT ZERO
	DCR	B		;NOT 1, MAKE IT 0
LF742:	CALL	OUT8		;PRINT IT, WHATEVER
	MOV	A,C		;RESTORE THE FLAG BYTE IN A
	RET			;DONE
;
;PRINT A BYTE USING CURRENT SIMULATOR MODE
;
LF747:	LXI	H,LD14B		;POINT TO SIMULATOR MODE
	MOV	B,M		;GET IT
	DCR	B		;SETTING FLAGS
	JP	LF753		;IF MODE WASN'T ZERO
	CALL	DUMO		;USE ALS-8 MODE
	RET			;DONE
LF753:	JMP	DOUT		;USE DECIMAL
;
;ROUTINE TO PRINT BYTE FOLLOWED BY SPACE
;
LF756:	CALL	LF747		;PRINT THE BYTE
	JMP	LE35C		;THEN DO SPACE & RETURN
;
;THIS IS THE SIMULATOR MAIN ENTRY POINT
;
SIMU:	LDA	IBUF+4		;GET CHAR AFTER 'SIMU'
	CPI	' '+1		;COMPARE TO BLANK
	JNC	LF774		;SKIP INIT. IF NOT BLANK
	XRA	A		;ELSE GET A ZERO
	STA	LD136		;CLEAR INPUT PORT ASSIGN FLAG
	STA	LD14B		;CLEAR SIMULATOR MODE
	STA	LD137		;CLEAR OUTPUT PORT ASSIGN FLAGS
	STA	LD135		;CLEAR REAL TIME RUN FLAG
LF771:	STA	LD134		;CLEAR BRKPT FLAG
;
;WARM RESTART ENTRY POINT
;
LF774:	LXI	SP,SMODE	;SET STACK
	CALL	CRLF		;DO CR/LF
	MVI	B,'*'		;PROMPT
	CALL	OUT8		;PRINT IT
	CALL	READ		;GET A COMND LINE IN IBUF
	LDA	IBUF		;GET 1ST CHAR
	CPI	'P'		;SET PGM COUNTER ?
	JNZ	LF796		;NO - TRY OTHER COMMANDS
	CALL	LF932		;GET OPERAND VALUE TO H,L
	SHLD	LD13E		;? - THIS IS NOT THE SIM P.C.
	SHLD	LD13C		;THE SIMULATORS PGM. COUNTER
	JMP	LF774		;GET NEXT COMMAND
LF796:	CPI	'B'		;SET BREAKPOINT ?
	JNZ	LF7A4		;NO - TRY ANOTHER COMMAND
	CALL	LF932		;GET ADDR TO H,L
	SHLD	LD138		;SET BREAKPOINT ADDR
	JMP	LF771		;SET BKPT FLAG & RESTART
LF7A4:	CPI	'R'		;SET REAL-TIME RUN ADDR ?
	JNZ	LF7B7		;NO - TRY ANOTHER COMMAND
	CALL	LF932		;GET ADDR TO H,L
	SHLD	LD13A		;SET REAL-TIME RUN ADDR
	MVI	A,1		;GET A ONE
	STA	LD135		;AND USE IT TO SET R.T. RUN FLG
	JMP	LF774		;RESTART & GET NEXT COMMAND
;
;TEST FOR AND PROCESS THE CLEAR COMMANDS
;
LF7B7:	CPI	'C'		;CLEAR COMMAND ?
	JNZ	LF7DE		;NO - TRY OTHER COMMANDS
	LDA	IBUF+1		;YES - GET NEXT CHAR
	LXI	H,LD134		;POINT TO BKPT FLAG
	CPI	'B'		;CLEAR BREAKPOINT ?
	JZ	LF7D9		;YES - DO IT
	INX	H		;NO, POINT TO R.T. RUN FLAG
	CPI	'R'		;CLEAR R.T. RUN ADDR ?
	JZ	LF7D9		;YES - DO IT
	INX	H		;NO, POINT TO INPT PT ASGN FLAG
	CPI	'I'		;CLEAR INPUT PORT ASSIGNMENTS ?
	JZ	LF7D9		;YES - DO IT
	INX	H		;NO, POINT TO OUTP PT ASGN FLAG
	CPI	'O'		;CLEAR OUTPUT PORT ASSGNMENTS ?
	JNZ	LF949		;NO - INVALID CLEAR COMMAND
LF7D9:	MVI	M,0		;CLEAR FLG H,L POINT TO
	JMP	LF774		;AND RESTART SIMULATOR
LF7DE:	CPI	'G'		;GO COMMAND ?
	JZ	LF6AC		;YES - DO IT
	CPI	'D'		;DUMP COMMAND ?
	JNZ	LF7F1		;NO - TRY NEXT COMMAND
	CALL	LF932		;GET ADDR IN H,L
	CALL	DUMP+3		;AND USE ALS-8 DUMP CODE
	JMP	LF774		;THEN RESTART THE SIMULATOR
LF7F1:	CPI	'E'		;ENTER COMMAND ?
	JNZ	LF802		;NO, TEST OTHER COMMANDS
	CALL	LF932		;GET ADDRESS TO H,L
	CALL	ENTS		;USE ALS-8 ENTER CODE
	JC	LF949		;IF ERROR
	JMP	LF774		;ELSE RESTART
LF802:	CPI	'X'		;EXIT SIMULATOR COMMAND ?
	JZ	EORMS		;YES - RET TO ALS-8
	CPI	'M'		;MODE COMMAND ?
	JNZ	LF81F		;NO - TEST OTHER COMMANDS
	CALL	LF932		;GET VALUE IN H,L
	MOV	A,L		;NOW TO A
	MVI	B,1		;ASSUME HEX
	CPI	16		;HEX ?
	JZ	LF818		;YES - SKIP NEXT STMNT
	DCR	B		;MAKE IT 0 ==> OCTAL
LF818:	MOV	A,B		;GET FLAG TO A
	STA	LD14B		;AND UPDATE MODE
	JMP	LF774		;THEN RESTART SIMULATOR
;
;PROCESS THE VARIOUS INPUT COMMANDS
;
LF81F:	CPI	'I'		;SET INPUT COMMAND ?
	JNZ	LF863		;NO - TRY OTHER COMMANDS
	CALL	LF932		;GET VALUE TO H,L
	MOV	A,H		;HIGH ORDER BYTE TO A
	ORA	A		;SET FLAGS
	JNZ	LF949		;ERROR IF > 256
	MOV	A,L		;PORT TO A
	CALL	LF8A1		;SEARCH INPUT PORT TABLE
	MOV	A,C		;GET NO OF PORTS IN TABLE
	CPI	16		;TABLE FULL ?
	JNC	LF949		;ERROR THEN
	STA	LD136		;ELSE UPDATE # OF TABLE ENTRIES
	MVI	M,0FFH		;AND MAKE PORT REAL-TIME
	LDA	IBUF+1		;GET CHAR AFTER 'I'
	CPI	'S'		;PRESET ?
	JNZ	LF854		;NO - TRY REAL-TIME & CLEAR
	XCHG			;SAVE TABLE POINTER IN D,E
	LHLD	BBUF+2		;GET VALUE OF PRESET
	MOV	A,H		;GET HIGH BYTE
	ORA	A		;SET FLAGS
	JNZ	LF949		;ERROR IF > 255
	XCHG			;TABLE POINTER BACK TO H,L
	MVI	M,1		;SAY PRESET
	INX	H		;MOVE 1 BEYOND INPUT TYPE
	MOV	M,E		;AND STORE PRESET VALUE
	JMP	LF774		;THEN RESTART SIMULATOR
LF854:	CPI	'R'		;REAL-TIME INPUT ?
	JZ	LF774		;RESTART SIMULATR - ALREADY SET
	MVI	M,0		;ELSE ASSUME SIMULATED
	CPI	'C'		;TEST FOR SIMULATED
	JZ	LF774		;OK IF IT REALLY IS
	JMP	LF949		;ELSE ERROR
;
;TEST FOR AND PROCESS THE OUTPUT COMMANDS
;
LF863:	CPI	'O'		;SET OUTPUT INST ?
	JNZ	LF8BC		;NO - TRY OTHER COMMANDS
	CALL	LF932		;ELSE GET PORT NO IN H,L
	MOV	A,H		;HIGH BYTE TO A
	ORA	A		;SET FLAGS
	JNZ	LF949		;ERROR IF > 255
	MOV	A,L		;PORT TO A
	CALL	LF897		;LOOK UP PORT IN TABLE
	MOV	A,C		;GET NO OF PORTS IN TABLE
	CPI	16		;TABLE FULL ?
	JNC	LF949		;ERROR THEN
	STA	LD137		;ELSE UPDATE # OF TABLE ENTRIES
	MVI	B,0FFH		;ASSUME REAL-TIME
	LDA	IBUF+1		;GET NEXT CHAR OF COMMAND
	CPI	'R'		;REAL-TIME ?
	JZ	LF890		;ENTER R.T. IN TABLE & RESTART
	INR	B		;NOT R.T., ASSUME ASCII
	CPI	'A'		;ASCII ?
	JZ	LF890		;YES - PUT IN TABLE
	INR	B		;NOT R.T. OR ASCII - SIMULATED?
	CPI	'C'		;CLEAR (SIMULATED) ?
LF890:	MOV	M,B		;SET OUTPUT MODE
	JZ	LF774		;MODE SET, RESTART
	JMP	LF949		;ERROR, SIMULATED ASSUMED
LF897:	LXI	H,LD162		;POINT TO OUTPUT TABLE
	MOV	B,A		;PORT NO TO B
	LDA	LD137		;NO OF TABLE ENTRIES
	JMP	LF8A8		;SEARCH TABLE
LF8A1:	LXI	H,LD152		;POINT TO INPUT TABLE
	MOV	B,A		;PORT NO TO B
	LDA	LD136		;NO OF TABLE ENTRIES
LF8A8:	MOV	C,A		;TABLE ENTRIES TO C
	ORA	A		;SET FLAGS
	MOV	A,B		;PORT NO BACK TO A
	MOV	B,C		;NO OF ENTRIES TO B
	JZ	LF8B8		;IF TABLE CURRENTLY EMPTY
LF8AF:	CMP	M		;POINTING AT CORRECT PORT ?
	INX	H		;POINT TO I/O TYPE FOR PORT
	RZ			;IF WE HAVE PORT
	INX	H		;POINT TO I/O BYTE VALUE
	INX	H		;AND TO NEXT PORT
	DCR	B		;DCR NO OF TABLE ENTRIES LEFT
	JNZ	LF8AF		;AND CHECK REMAINING ENTRIES
LF8B8:	MOV	M,A		;PUT PORT IN TABLE
	INX	H		;AND POINT TO I/O TYPE
	INR	C		;INR NO OF ENTRIES IN TABLE
	RET			;AND RETURN DONE
;
;PROCESS THE SET REGISTER/FLAG COMMANDS
;
LF8BC:	CPI	'S'		;SET REGISTERS ?
	JNZ	LF949		;THERE AREN'T ANY COMMANDS LEFT
	LXI	H,IBUF+1	;POINT TO NEXT BYTE
	SHLD	PNTR		;AND SAVE CHAR POINTER
LF8C7:	CALL	ZBUF		;CLEAR ABUF
	CALL	SBLK		;SCAN TO TEXT
	JC	LF774		;RESTART IF C/R FOUND
	XCHG			;LINE PTR TO D,E
	MVI	C,10		;NO OF REGISTERS IN TABLE
	LXI	H,LF954		;POINT TO TABLE
LF8D6:	CMP	M		;SAME ?
	JZ	LF8E2		;FOUND REGISTER TO SET
	INX	H		;ELSE POINT TO NEXT REGISTER
	DCR	C		;AND DCR COUNT
	JNZ	LF8D6		;THEN TEST IT FOR MATCH
	JMP	LF949		;NO MATCH IN TABLE, ERROR
LF8E2:	MOV	A,C		;GET DISPLACEMENT INTO TABLE
	STA	TEMP		;AND SAVE IT
	XCHG			;POINTER TO H,L
	INX	H		;POINT TO NEXT CHAR
	MOV	A,M		;GET IT
	CPI	'='		;EQUALS SIGN ?
	JNZ	LF949		;ERROR IF NOT
	INX	H		;POINT TO ARGUMENT
	MOV	A,M		;GET IT
	LXI	D,ABUF		;POINT TO ABUF
	CALL	LF912		;CONVERT ARGUMENT TO BINARY
	JC	LF949		;IF ERROR
	LDA	TEMP		;GET DISP. INTO TABLE BACK
	CPI	1		;SETTING STACK POINTER ?
	JZ	LF92C		;HANDLE THAT SEPARATELY
	MOV	C,A		;DISPLACEMENT TO C
	MOV	A,H		;GET HIGH ORDER BYTE OF VALUE
	ORA	A		;SET FLAGS
	JNZ	LF949		;ERROR IF > 255
	MOV	A,L		;GET VALUE TO A
	LXI	H,LD140		;REGISTER TABLE IN RAM
	MVI	B,0		;B,C HAS DISPLACEMENT INTO TBL
	DAD	B		;H,L HAS ABSOLUTE ADDR
	MOV	M,A		;UPDATE SIM/8080 REGISTER
	JMP	LF8C7		;DO NEXT REGISTER(S) IF ANY
;
;ROUTINE TO CONVERT KEYED IN VALUE TO 16 BIT VALUE IN H,L
;
LF912:	CALL	ALPS		;PUT ARGUMENT INTO ABUF
	DCX	D		;POINT TO LAST CHAR
	LDAX	D		;GET IT
	LXI	B,ABUF		;POINT TO ARGUMENT
	CPI	'D'		;DECIMAL ?
	JZ	NUM1		;YES
	CPI	'Q'		;OCTAL ?
	JZ	NUM3		;YES
	CPI	'H'		;HEX ?
	JNZ	EMODE		;NO, USE STD MODE
	JMP	NUM2		;ELSE HEX
LF92C:	SHLD	LD140		;UPDATE SIM/8080 STACK PNTR
	JMP	LF8C7		;AND DO NEXT REGISTER(S) IF ANY
;
;ROUTINE TO SET SIMULATED PROGRAM COUNTER
;
LF932:	CALL	ETRA		;GET VALUES FROM COMMAND LINE
	JC	LF949		;IF ERROR
	CALL	LE31E		;VALUES TO BIN IN BBUF & BBUF+2
	JC	LF949		;ON ERROR
	LDA	ABUF		;GET FIRST CHAR OF VALUE
	ORA	A		;AND SET FLAGS
	JZ	LF949		;ERROR IF NO VALUE GIVEN
	LHLD	BBUF		;GET VALUE
	RET			;AND RETURN WITH IT IN H,L
;
;ERROR HANDLER ROUTINE
;
LF949:	CALL	CRLF		;DO CR/LF
	MVI	B,'?'		;GET QUESTION MARK
	CALL	OUT8		;AND PRINT IT
	JMP	LF774		;THEN RESTART SIMULATOR
;
;TABLE OF REGISTER NAMES FOR THE SET COMMANDS
;VALUES ARE STORED IN A TABLE IN MEMORY AT D143, BUT
;IN REVERSE ORDER.  THERE IS ONE ENTRY HERE FOR EACH
;ENTRY IN THAT TABLE.  NOTE THAT THE ACCUM. APPEARS
;TWICE, ONCE BY ITSELF & ONCE WITH THE FLAGS (AS PSW)
;
LF954:	DB	'A'
	DB	'B'
	DB	'C'
	DB	'D'
	DB	'E'
	DB	'H'
	DB	'L'
	DB	'A'
	DB	'F'
	DB	'S'
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
;
;COME HERE TO EXECUTE AUTO-NUMBER INPUT MODE
;
;WHAT THIS CODE ACTUALLY DOES IS TO MODIFY THE INPUT ROUTINE
;TO COME INTO A PRE-PROCESSOR AT F99A INSTEAD OF THE NORMAL
;IN8 INPUT ROUTINE.  THAT ROUTINE ACTUALLY DOES THE LINE
;NUMBER PROCESSING.
;
AUTO:	LHLD	IN8+1		;GET ADDR OF CUR INPUT DRIVER
	SHLD	BBUF+1		;AND SAVE IN BBUF
	LDA	ABUF		;SEE IF OPT PARAMETER GIVEN
	ORA	A		;SET FLAGS
	JZ	LF983		;NOT GIVEN, START WITH 1
	LHLD	MAXL		;GET HALF OF CUR MAX LINE NO
	SHLD	ABUF		;SAVE IT
	LHLD	MAXL+2		;GET OTHER HALF
	JMP	LF989		;SKIP INITIALIZATION
LF983:	LXI	H,3030H		;TWO ZERO'S
	SHLD	ABUF		;SAVE AS TWO HIGH DIGITS
LF989:	SHLD	ABUF+2		;AND SAVE H,L AS LOW ORDER DGTS
	MVI	A,0C3H		;JUMP INST
	STA	BBUF		;BBUF = JUMP INTO AUTO CODE NOW
	LXI	H,LF99A		;GET ADDR OF LINE NO PROCESSOR
	SHLD	IN8+1		;USE IT FOR NEW INPUT ROUTINE
	JMP	EORNS		;EVERYTHING'S SET UP
;
;HERE IS THE ROUTINE WHICH ACTUALLY PUTS LINE NOS. ON LINES.
;IT IS SUBSTITUTED FOR THE STANDARD ROUTINE BY THE CODE ABOVE.
;
LF99A:	CALL	BBUF		;CALL THE STD. INPUT ROUTINE
	MOV	A,L		;GET LOW BYTE ADDR OF CHAR PTR
	CPI	IBUF AND 0FFH	;AT 1ST CHAR OF INPUT BUFFER ?
	JNZ	LF9AE		;NO - SKIP BEG OF LINE PROC.
	MVI	A,1BH		;YES - SEE IF ESCAPE CHAR
	CMP	B		;
	JZ	EORMS		;IT IS ESC - DO COMPLETE RESET
	LXI	H,IBUF+5	;POINT TO NEW CHAR DEST
	MVI	E,7		;AND RESET LINE LENGTH
LF9AE:	MVI	A,0DH		;GET ASCII CAR. RET.
	CMP	B		;END OF LINE ?
	MOV	A,B		;PUT CHAR IN ACCUM.
	RNZ			;AND RETURN IF NOT END OF LINE
	PUSH	H		;ELSE SAVE IBUF POINTER
	PUSH	D		;AND LINE LENGTH
	LXI	D,ABUF		;POINT TO CUR LINE NO.
	LXI	H,ABUF+3	;AND TO END OF LINE NO.
LF9BB:	MOV	A,M		;GET RIGHT-HAND DIGIT
	INR	A		;INCREMENT IT
	CPI	'9'+1		;GONE PAST 9 ?
	JNC	LF9D8		;YES - FIX IT UP
	MOV	M,A		;ELSE PUT IT BACK
	LXI	H,IBUF		;POINT TO IBUF
	MVI	B,4		;LENGTH OF LINE NO
LF9C8:	LDAX	D		;GET CHAR FROM LINE NO.
	MOV	M,A		;AND PUT IT INTO IBUF
	INX	H		;INR IBUF POINTER
	INX	D		;INR LINE NO. POINTER
	DCR	B		;DCR COUNT
	JNZ	LF9C8		;AND CONTINUE TILL DONE
	MVI	M,' '		;THEN PUT A SPACE IN IBUF
	POP	D		;AND RESTORE REGISTERS
	MVI	B,0DH		;AND CHARACTER
	MOV	A,B		;WHICH READ WANTS IN ACCUM
	POP	H		;RESTORE REGS
	RET			;AND GO HOME, DONE
LF9D8:	MVI	A,'0'		;REPLACE DIGIT WITH A ZERO
	MOV	M,A		;AND PUT IT BACK
	DCX	H		;POINT TO HIGHER DIGIT
	JMP	LF9BB		;AND TRY TO INR IT
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
;
; ****END OF ALS8SIM MODULE
;
;
;THE TXT-2 TEXT EDITOR STARTS HERE BUT ENTRY IS AT TXT2 (FA0B)
;
;ROUTINE TO CREATE A ONE LINE FILE NECESSARY FOR THE
;EDITOR WHEN STARTING A NEW (E.G. NULL OR EMPTY) FILE
;
LFA00:	MVI	M,2		;LENGTH BYTE
	INX	H		;POINT TO NEXT BYTE
	MVI	M,0DH		;CARRIAGE RETURN
	INX	H		;POINT TO NEXT
	MVI	M,1		;END OF FILE MARK
	SHLD	EOFP		;NOW WE HAVE A NON-EMPTY FILE
;
;THIS IS THE EDITOR ENTRY POINT
;
TXT2:	LXI	SP,SMODE	;SET STACK POINTER
	LHLD	BOFP		;GET BEG OF FILE POINTER
	LXI	D,EOFP		;AND POINT TO END OF FILE PTR
	CALL	LFD42		;COMPARE THEM
	JZ	LFA00		;CREATE ONE LINE FILE IF EMPTY
	JC	WHAT		;ERROR IF BOFP > EOFP
	PUSH	H		;SAVE BEG. OF FILE POINTER
	CALL	LFD4E		;CLEAR SCREEN & INITIALIZE VARS
	SUB	A		;GET A ZERO
	MOV	B,A		;MAKE IT ROW
	CALL	LFF1A		;CALC CUR ADDR & TURN IT ON
	POP	H		;RESTORE BEG OF FILE PNTR
LFA27:	SHLD	LD19A		;
	CALL	LFAD9
;
;THIS IS THE BEGINNING OF THE MAIN EDITOR COMMAND LOOP
;
LFA2D:	CALL	LFA33		;GET AND EXECUTE A COMMAND
	JMP	LFA2D		;DO IT AGAIN
;
;AND THAT WAS THE END OF IT
;
LFA33:	CALL	LFF13		;CALC CUR ADDR & TURN CURSR ON
	CALL	IN8		;GET A CHAR OF COMMAND
LFA39:	CPI	' '		;CONTROL CHAR ?
	JNC	LFC04		;PROCESS PRINTING CHAR IF NOT
	CPI	'A'-40H		;CURSOR LEFT COMMAND ?
	JZ	LFB57		;PROCESS IF SO
	CPI	'S'-40H		;CURSOR RIGHT COMMAND ?
	JZ	LFC10		;PROCESS IF SO
	PUSH	PSW		;SAVE COMMAND
	CALL	LFCA4
	POP	B		;RESTORE COMMAND TO B
	LXI	H,LFA65		;EDITOR COMMAND TABLE
LFA50:	MOV	A,M		;GET TABLE COMMAND
	ORA	A		;END OF TABLE ?
	RZ			;YES
	CMP	B		;NO - SAME AS COMMAND ?
	INX	H		;POINT TO COMMAND ADDR
	JZ	LFA60		;DISPATCH TO IT ON MATCH
	INX	H		;NO MATCH - POINT PAST COMMAND
	INX	H		;TO NEXT COMMAND
	JMP	LFA50		;AND TEST NEXT COMMAND
;
;ROUTINE TO DISPATCH TO COMMAND IN TABLE
;
LFA5D:	LXI	H,LD1A1		;POINT TO UNDEFINED COMMAND
LFA60:	MOV	A,M		;COMMAND LOW BYTE TO A
	INX	H		;POINT TO HIGH BYTE
	MOV	H,M		;HIGH BYTE TO H
	MOV	L,A		;H,L NOW HAS COMPLETE ADDR
	PCHL			;DISPATCH TO COMMAND ROUTINE
;
;HERE IS THE COMMAND TABLE FOR THE EDITOR COMMANDS
;
LFA65:	DB	'W'-40H		;UP
	DW	LFACC
	DB	'Z'-40H		;DOWN
	DW	LFB62
	DB	'E'-40H		;SCROLL UP ONE LINE
	DW	LFB8E
	DB	'X'-40H		;SCROLL DOWN ONE LINE
	DW	LFAC6
	DB	'R'-40H		;SCROLL UP 1 PAGE
	DW	LFB12
	DB	'C'-40H		;SCROLL DOWN 1 PAGE
	DW	LFB21
	DB	'J'-40H		;ERASE EOF & SCROLL UP (L/F)
	DW	LFB7B
	DB	'B'-40H		;INSERT LINE
	DW	LFBC8
	DB	'M'-40H		;SCROLL UP & INSERT LINE (C/R)
	DW	LFB9D
	DB	'T'-40H		;TOGGLE INSERT MODE SW
	DW	LFB72
	DB	'P'-40H		;DELETE LINE
	DW	LFBD2
	DB	'H'-40H		;DELETE CHAR
	DW	LFC2E
	DB	'F'-40H		;EXIT TO ALS-8
	DW	LFAA5
	DB	'O'-40H		;EDITOR SEARCH
	DW	LFF58
	DB	'I'-40H		;CONTINUE SEARCH
	DW	LFF64
	DB	'Y'-40H		;REPEAT COMMAND
	DW	LFAAE
	DB	'Q'-40H		;HOME COMMAND
	DW	LFA9C
	DB	'U'-40H		;UNDEFINED COMMAND
	DW	LFA5D
	DB	0
;
;HOME CURSOR
;
LFA9C:	XRA	A		;GET A ZERO
	STA	NCHAR		;MAKE IT THE COLUMN
	MVI	A,6		;HOME=LINE 7 (START W/0 AT TOP)
	JMP	LFAD6		;PUT THE CURSOR THERE
;
;EXIT EDITOR TO ALS-8
;
LFAA5:	CALL	LFD4E		;CLEAR VDM-1 SCREEN
	CALL	FCHK		;FCHK FILE
	JMP	EORMS		;GO BACK TO ALS-8
;
;REPEAT COMMAND
;
LFAAE:	CALL	IN8		;GET COMMAND TO REPEAT
	STA	BBUF		;SAVE COMMAND
	CALL	IN8		;GET REPEAT COUNT
	SUI	30H		;CONVERT TO BINARY
LFAB9:	PUSH	PSW		;SAVE COUNT
	LDA	BBUF		;GET COMMAND
	CALL	LFA39		;EXECUTE IT ONE TIME
	POP	PSW		;RESTORE COUNT
	DCR	A		;DECREMENT COUNT
	RZ			;DONE IF COUNT=0
	JMP	LFAB9		;ELSE DO IT AGAIN
;
;SCROLL DOWN 1 LINE
;
LFAC6:	CALL	LFC72
	JNZ	LFAD9
;
;CURSOR UP
;
LFACC:	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	DCR	A
	JP	LFAD6
	LDA	LD199
LFAD6:	STA	SLINE
LFAD9:	LHLD	LD19A
	SHLD	LD19C
	XRA	A
	STA	LD198		;CLEAR INSERT MODE
	PUSH	PSW
LFAE4:	STA	LD199
	XCHG
	LXI	H,SLINE
	CMP	M
	XCHG
	JNZ	LFAF3
	SHLD	LD19E
LFAF3:	CALL	LFE07
LFAF6:	POP	PSW
	INR	A
	CPI	16
	RZ
	MOV	B,A
	CALL	LFC5F
	XCHG
	MOV	A,B
	PUSH	PSW
	JNZ	LFAE4
	MVI	B,0
	MVI	C,'#'
	LXI	H,4001H
	CALL	LFE4E
	JMP	LFAF6
;
;SCROLL UP 1 PAGE (16 LINES)
;
LFB12:	MVI	A,16
LFB14:	PUSH	PSW
	CALL	LFC5F
	CNZ	LFB94
	POP	PSW
	DCR	A
	JNZ	LFB14
	RET
;
;SCROLL DOWN 1 PAGE (16 LINES)
;
LFB21:	MVI	A,16
LFB23:	PUSH	PSW
	CALL	LFC72
	CNZ	LFAD9
	POP	PSW
	DCR	A
	JNZ	LFB23
	RET
;
;ROUTINE TO GIVE WARNING WHEN TEXT BUFFER GETS FULL
;
LFB30:	LXI	D,LFB46		;POINT TO WARNING MESSAGE
	MVI	C,17		;LENGTH OF MESSAGE
	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	CALL	LFE0C		;PRINT MESSAGE
LFB3B:	CALL	IN8		;GET CHAR FROM CONSOLE
	CPI	'Q'-40H		;CONTROL-Q ?
	JNZ	LFB3B		;NO - WAIT INDEFINATELY
	JMP	TXT2		;YES - RESTART EDITOR
;
LFB46:	DB	'FULL--TYPE CTRL Q'
;
;CURSOR LEFT COMMAND
;
LFB57:	CALL	LFF2D		;CURSOR OFF
	MOV	A,B		;COLUMN TO A
	DCR	A		;DECREMENT IT
LFB5C:	ANI	3FH		;KEEP IT TO 0-63
	MOV	M,A		;PUT IT BACK AS NEW COLUMN
	JMP	LFF16		;TURN CURSOR ON & RET
;
;CURSOR DOWN
;
LFB62:	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	LXI	H,LD199
	CMP	M
	JNZ	LFB6E
	MVI	A,0FFH
LFB6E:	INR	A
	JMP	LFAD6
;
;TOGGLE CHAR INSERT MODE
;
LFB72:	LDA	LD198		;GET INSERT MODE SWITCH
	XRI	1		;TOGGLE LOW ORDER BIT
	STA	LD198		;PUT IT BACK
	RET			;DONE
;
;ERASE TO THE END OF LINE AND SCROLL UP
;
LFB7B:	CALL	LFDED		;CALC CURSOR ADDR
LFB7E:	MVI	M,' '		;MOVE SPACE TO LINE
	INR	L		;INR LINE POINTER
	MOV	A,L		;MOVE IT TO A
	ANI	3FH		;END OF LINE YET ?
	JNZ	LFB7E		;MORE SPACES IF NOT
	CALL	LFCA4		;YES - NOW UPDATE FILE
	SUB	A		;GET A ZERO
	STA	NCHAR		;AND MAKE IT NEW COLUMN
;
;SCROLL UP 1 LINE
;
LFB8E:	CALL	LFC5F
	JZ	LFB62
LFB94:	LXI	H,LD19A
	CALL	LFC62
	JMP	LFAD9
;
;SCROLL UP AND INSERT 1 LINE
;
LFB9D:	LXI	H,LD19E
	CALL	LFC62
	JNZ	LFBAC
	LHLD	EOFP
	SHLD	LD19E
LFBAC:	CALL	LFC51
	XRA	A
	STA	NCHAR
	LDA	LD199
	CPI	0FH
	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	JNZ	LFB6E
	LXI	H,LD19A
	CALL	LFC62
	JMP	LFAD9
;
	DB	01H		;THIS IS A FOOL'S BYTE
;
;INSERT LINE COMMAND
;
LFBC8:	CALL	LFC51
	XRA	A
	STA	NCHAR
	JMP	LFAD9
;
;DELETE LINE COMMAND
;
LFBD2:	SUB	A		;GET A ZERO
	STA	LD198		;USE IT TO CLEAR INSERT MODE
	LHLD	BOFP
	MOV	A,M
	CALL	LFD32
	MOV	A,M
	CPI	1
	RZ
	CALL	LFC5F
	JNZ	LFBEA
	CALL	LFC72
LFBEA:	PUSH	PSW
	LHLD	LD19E
	MOV	A,M
	CMA
	INR	A
	CALL	LFCD1
	POP	PSW
	JNZ	LFAD9
	LHLD	LD19E
	MOV	A,M
	CPI	1
	JZ	LFACC
	JMP	LFAD9
;
;
;
LFC04:	MOV	C,A
	LDA	LD198		;GET INSERT MODE FLAG
	ORA	A		;SET CPU FLAGS
	JNZ	LFC18		;JUMP IF IN INSERT MODE
	CALL	LFDED
	MOV	M,C
;
;CURSOR RIGHT COMMAND
;
LFC10:	CALL	LFF2D		;TURN CURSOR OFF
	MOV	A,B		;COLUMN TO A
	INR	A		;INCREMENT IT
	JMP	LFB5C		;CURSOR BACK ON & RET
;
;
;
LFC18:	CALL	LFDED
	MOV	A,C
	ORI	80H
	MOV	C,A
LFC1F:	MOV	A,M
	ANI	7FH
	MOV	M,C
	MOV	C,A
	INR	L
	MOV	A,L
	ANI	3FH
	JNZ	LFC1F
	JMP	LFC10
;
;DELETE CHARACTER
;
LFC2E:	CALL	LFDED		;CALC CURSOR POSITION
	LDA	NCHAR		;GET CURRENT COLUMN
	CPI	3FH		;COLUMN 63 (LAST) ?
	JC	LFC3C		;NO - DELETE CHAR
	MVI	M,' '+80H	;MAKE LAST COL SPACE W/CURSOR
	RET			;DONE
;
;ROUTINE TO DELETE A CHAR FROM MIDDLE OF LINE
;
LFC3C:	MOV	A,L		;GET LINE POINTER
	MOV	E,A		;SAVE IT
	ORI	3FH		;MAKE IT POINT TO LAST COL
	MOV	L,A		;PUT IT BACK
	MOV	A,E		;RESTORE ORIG PTR TO A
	MVI	C,' '		;SPACE TO C
LFC44:	MOV	B,M		;GET CHAR FROM LINE
	MOV	M,C		;REPL WITH CHAR ON IT'S RIGHT
	MOV	C,B		;AND MAKE IT NXT CHAR ON RIGHT
	DCR	L		;DECR COLUMN POINTER
	CMP	L		;AND COMPARE TO INITIAL COL
	JNZ	LFC44		;AND KEEP UP IF NOT DONE
	MOV	A,B		;GET LAST CHAR TO STORE IN A
;
;TURN ON THE CURSOR
;
LFC4D:	ORI	80H		;MAKE CURSOR BIT HIGH
	MOV	M,A		;PUT CHAR W/CURSOR ON SCREEN
	RET			;DONE, CURSOR ON
;
;
;
LFC51:	MVI	A,2
	CALL	LFCD1
	LHLD	LD19E
	MVI	M,2
	INX	H
	MVI	M,0DH
	RET
;
;
;
LFC5F:	LXI	H,LD19C
LFC62:	MOV	E,M
	INX	H
	MOV	D,M
	LDAX	D
	XCHG
	CALL	LFD32
	XCHG
	LDAX	D
	DCR	A
	RZ
	MOV	M,D
	DCX	H
	MOV	M,E
	RET
;
;
;
LFC72:	LHLD	LD19A
	CALL	LFC95
	RZ
	DCX	H
LFC7A:	DCX	H
	CALL	LFC95
	JZ	LFC90
	MOV	A,M
	CPI	0DH
	JNZ	LFC7A
	DCX	H
	MOV	A,M
	CPI	0DH
	JZ	LFC8F
	INX	H
LFC8F:	INX	H
LFC90:	INR	A
	SHLD	LD19A
	RET
;
;
;
LFC95:	LDA	BOFP
	SUB	L
	LDA	BOFP+1
	SBB	H
	RNZ
	LDA	BOFP
	SUB	L
	ORA	A
	RET
;
;
;
LFCA4:	CALL	LFF2D		;TURN ON THE CURSOR
	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	CALL	LFE33		;BACK UP TO LAST NON BLANK CHAR
	INR	C
	INR	C
	MOV	A,C
	CPI	6
	JNC	LFCB8
	MVI	A,6
	MOV	C,A
LFCB8:	LHLD	LD19E
	SUB	M
	CALL	LFCD1
	LHLD	LD19E
	MOV	M,C
	DCR	C
	DCR	C
	INX	H
	XCHG
	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	CALL	LFE24
	XCHG
	MVI	M,0DH
	RET
;
;
;
LFCD1:	MOV	B,A
	ORA	A
	RZ
	JM	LFD1A
	LHLD	EOFP
	CALL	LFD32
	LXI	D,LD191		;POINT TO ESET BUFFER LIMIT
	CALL	LFD42
	JC	LFB30
	XCHG
	LHLD	LD19E
	DCX	H
	MVI	M,81H
	LHLD	EOFP
LFCF0:	MOV	A,M
	CPI	81H
	JZ	LFCFC
	STAX	D
	DCX	H
	DCX	D
	JMP	LFCF0
;
;
;
LFCFC:	MVI	M,0DH
LFCFE:	LHLD	EOFP
	MOV	A,B
	CALL	LFD32
	SHLD	EOFP
	LHLD	LD19C
	LXI	D,LD19E
	CALL	LFD42
	RZ
	MOV	A,B
	CALL	LFD32
	SHLD	LD19C
	RET
;
;
;
LFD1A:	CMA
	INR	A
	LHLD	LD19E
	CALL	LFD32
	XCHG
	LHLD	LD19E
LFD26:	LDAX	D
	MOV	M,A
	CPI	01H
	JZ	LFCFE
	INX	H
	INX	D
	JMP	LFD26
;
;
;
LFD32:	ORA	A
	JM	LFD3B
	ADD	L
	MOV	L,A
	RNC
	INR	H
	RET
;
;
;
LFD3B:	ADD	L
	MOV	L,A
	MVI	A,0FFH
	ADC	H
	MOV	H,A
	RET
;
;
;
LFD42:	LDAX	D
	SUB	L
	INX	D
	LDAX	D
	SBB	H
	DCX	D
	RC
	RNZ
	LDAX	D
	SUB	L
	ORA	A
	RET
;
;ROUTINE TO CLEAR ALL OR PART OF VDM-1 DISPLAY SCREEN
;
LFD4E:	LXI	H,VDM1		;ENTER HERE TO CLR WHOLE 
SCREEN
LFD51:	MVI	M,' '		;FILL WITH SPACES
	INX	H		;POINT TO NEXT CHAR POSITION
	MOV	A,H		;GET HIGH ORDER BYTE
	CPI	0D0H		;PAST END OF SCREEN ?
	JC	LFD51		;CONTINUE IF NOT
	XRA	A		;ELSE GET A ZERO TO CLEAR:
	STA	BOSL		;BEGINNING OF SCREEN LINE (0-F)
	STA	BOTL		;BEGINNING OF TEXT LINE (0-F)
	STA	NCHAR		;CURRENT COLUMN POSITION
	MVI	A,0FH		;THEN GET A 15
	STA	SLINE		;TO PUT US ON THE BOTTOM LINE
;
;THIS ROUTINE OUTPUTS A PROPER COMMAND BYTE TO THE VDM-1/SOL-
20
;VIDEO DISPLAY GENERATOR BASED ON SCREEN PARAMTETERS
;
LFD69:	LDA	BOSL		;BEGINNING OF SCREEN LINE (0-F)
	RLC			;SHIFT LEFT TO HIGH NIBBLE
	RLC			;
	RLC			;
	RLC			;
	LXI	H,BOTL		;BEGINNING OF TEXT LINE (0-F)
	ORA	M		;A NOW HAS VDM CONTROL BYTE
	OUT	0C8H		;FOR VDM-1
	OUT	0FEH		;FOR SOL'S
	RET			;DONE
;
;
;
LFD79:	INR	L
	MOV	A,L
	ANI	3FH
	RNZ
	MOV	A,L
	ADI	0C0H
	MOV	L,A
	RET
;
;THIS ROUTINE IS PART OF THE VDM-1 DRIVER USED TO DISPLAY
;NORMAL CHARS AFTER CHECKING FOR SPEED CNTL HAS BEEN DONE
;
LFD83:	ANI	7FH		;CLEAR PARITY BIT
	MOV	C,A		;SAVE IN C
	LXI	H,NCHAR		;CURRENT COLUMN
	MOV	B,M		;COL IN B
	CPI	0DH		;IS CHAR A C/R ?
	JZ	LFDB1		;PROCESS IT SEPERATELY
	CPI	5FH		;BACKSPACE ?
	JZ	LFEED		;IT GET'S SPECIAL TREATMENT TOO
	CPI	'A'-40H		;CURSOR ON-OFF TOGGLE ?
	JZ	LFF06		;ANOTHER SPECIAL
	CPI	'Z'-40H		;CLEAR SCREEN ?
	JZ	LFD4E		;LAST SPECIAL CHAR
	CPI	20H		;TESTING FOR CONTROL CHAR
	RC			;SKIP THEM IF FOUND
	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	CALL	VDAD		;AND CALCULATE CHAR ADDRESS
	MOV	M,C		;PUT CHAR ON SCREEN
	LDA	NCHAR		;NOW GET COLUMN
	INR	A		;AND INCREMENT IT
	CPI	64		;GONE OFF END OF LINE ?
	JNZ	LFDBD		;NO - OK THEN
;
;COME HERE TO PROCESS CARRIAGE RETURN
;
LFDB1:	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	CALL	LFE46		;TURN CURSOR OFF
	MVI	A,1
	CALL	LFDCD		;CLEAR TO END OF LINE & SCROLL
	SUB	A		;GET A ZERO
LFDBD:	STA	NCHAR		;PUT UPDATED COL. POSITION BACK
	MOV	B,A		;AND MOVE IT TO B
	LDA	LD197		;GET CURSOR ON-OFF FLAG
	CPI	0		;SET FLAGS
	RZ			;DONE IF CURSOR OFF
	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	JMP	LFF1A		;TURN CURSOR ON & RETURN
;
;
;
LFDCD:	LXI	H,BOTL		;BEGINNING OF TEXT LINE (0-F)
	ORA	A
	JZ	LFDD9
	MOV	A,M
	INR	M
	JMP	LFDDD
LFDD9:	DCR	M
	MOV	A,M
	ANI	0FH
LFDDD:	SUB	M
	MVI	C,0
	CALL	LFE0C
	LXI	H,BOTL		;BEGINNING OF TEXT LINE (0-F)
	MOV	A,M
	ANI	0FH
	MOV	M,A
	JMP	LFD69
;
;
;
LFDED:	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	LXI	H,NCHAR		;GET COLUMN POSITION
	MOV	B,M		;TO B
;
;FOLLOWING ROUTINE CALCULATES ADDR OF CHAR AT LINE
;IN "A" AND COL "B"
;
VDAD:	MOV	L,A		;LINE NO. (0-F) TO L
	LDA	BOTL		;BEGINNING OF TEXT LINE (0-F)
	ADD	L		;ADD OFFSET TO LINE
	RRC			;DIVIDE BY TWO
	RRC			;AGAIN, NOW /4
	MOV	L,A		;SAVE # PAGES (256) OFFSET
	ANI	3		;MAKE IT 0-3 ONLY
	ADI	(VDM1 SHR 8) AND 0FFH
	MOV	H,A		;H NOW HI SCREEN ADDR
	MOV	A,L		;RESTORE # 256 BYTE PGS. OFFSET
	ANI	0C0H		;CHG TO # LINES FROM PG BOUNDRY
	ADD	B		;ADD IN COL ON LINE
	MOV	L,A		;H,L NOW COMPLETE ADDR
	RET			;DONE
;
;
;
LFE07:	MOV	C,M
	DCR	C
	DCR	C
	INX	H
	XCHG
LFE0C:	MVI	B,0
	CALL	VDAD
	MVI	B,64
LFE13:	XRA	A
	CMP	C
	MVI	A,' '
	JZ	LFE1D
	LDAX	D
	INX	D
	DCR	C
LFE1D:	MOV	M,A
	INR	L
	DCR	B
	JNZ	LFE13
	RET
;
;
;
LFE24:	MVI	B,0
	CALL	VDAD
	INR	C
LFE2A:	DCR	C
	RZ
	MOV	A,M
	STAX	D
	INX	H
	INX	D
	JMP	LFE2A
;
;
;
LFE33:	MVI	B,3FH
	CALL	VDAD
	MVI	C,40H
LFE3A:	MOV	A,M
	ANI	7FH
	CPI	20H
	RNZ
	DCX	H
	DCR	C
	JNZ	LFE3A
	RET
;
;ROUTINE TO TURN CURSOR OFF
;
LFE46:	CALL	VDAD		;CALCULATE SCREEN ADDR
	MOV	A,M		;GET CHAR UNDER CURSOR
	ANI	7FH		;TURN CURSOR BIT OFF
	MOV	M,A		;PUT IT BACK
	RET			;DONE, CURSOR OFF
;
;
;
LFE4E:	XCHG
LFE4F:	PUSH	PSW
	PUSH	D
	CALL	VDAD
LFE54:	MOV	M,C
	CALL	LFD79
	DCR	D
	JNZ	LFE54
	POP	D
	POP	PSW
	DCR	E
	RZ
	INR	A
	JMP	LFE4F
;
;
;
LFE64:	CPI	1BH		;ESCAPE CHAR ?
	JZ	EORMS		;BACK TO ALS-8 THEN
	CPI	20H		;SPACE BAR ?
	JNZ	LFEC1		;NO - CLEAR CHRR AND RETURN
LFE6E:	CALL	STAT		;YES - CHAR TYPED ?
	JZ	LFE6E		;NO - WAIT FOREVER IF NECESSARY
	JMP	LFEC2		;THEN SAVE THAT CHAR AS CHRR
;
;VDM-1 DRIVER STARTS HERE
;
LFE77:	MOV	A,B		;GET CHAR TO A
	CPI	7FH		;DELETE CHAR ?
	RZ			;RETURN IF SO
	PUSH	H		;ELSE SAVE REGISTERS
	PUSH	D		;
	PUSH	B		;
	LDA	SPEED		;GET SPEED CONTROL BYTE
	MOV	H,A		;TO H
	MVI	L,80H		;COUNTER NOW SET
	CALL	LFE9D		;SEE IF CHAR WAITING
	XRA	A		;MAKE ACC. ZERO
LFE88:	DCX	H		;DCR TIMER COUNTER
	CMP	H		;H = 0 YET ?
	JNZ	LFE88		;NO - THEN DELAY SOME MORE
	POP	B		;RESTORE CHAR TO B
	PUSH	B		;AND RE-SAVE B,C
	MOV	A,B		;GET CHAR AGAIN
	CPI	'S'-40H		;CONTROL-S ?
	CZ	LFEC6		;CALL SPEED SET ROUTINE
	CALL	LFD83		;PUT CHAR ON SCREEN
	POP	B		;RESTORE REGS
	POP	D		;
	POP	H		;
	MOV	A,B		;PUT CHAR IN ACC ON EXIT
	RET			;DONE
;
;ROUTINE TO CHECK FOR KEYBOARD INPUT & SCREEN CONTROL VALUE
;
LFE9D:	LDA	CHRR		;DEFAULT SPEED
	MOV	B,A		;SAVE IT IN B
	CALL	STAT		;KEYBOARD CHAR WAITING ?
	CNZ	IN8		;YES - THEN GET IT
	MOV	A,B		;DEFAULT SPEED OR CHAR TO A
LFEA8:	ORA	A		;SET FLAGS
	RZ			;NO CHG IF CHR/DEFAULT=0
	CPI	'9'+1		;NUMERIC ?
	JNC	LFE64		;NO, NOT NUMERIC
	CPI	'1'		;NUMERIC ?
	JC	LFE64		;NO, NOT NUMERIC
	ANI	0FH		;CONVERT TO BINARY
	MOV	C,A		;SAVE IN C
	XRA	A		;CLEAR ACC & FLAGS
	STC			;SET CARRY
LFEB9:	STA	SPEED		;SPEED CONTROL BYTE
	RAL			;MOVE ACCUM/CARRY 1 BIT LEFT
	DCR	C		;DCR SPEED COUNT
	JNZ	LFEB9		;IF SPEED COUNT <> 0, CONTINUE
LFEC1:	XRA	A		;GET A ZERO
LFEC2:	STA	CHRR		;MAKE IT ZERO FOR NEXT TIME
	RET			;DONE
;
;ROUTINE TO SET SPEED
;
LFEC6:	MVI	B,0		;COLUMN = 0
	CALL	LFDB1		;CLEAR LINE
	LXI	H,LFEE6		;POINT TO "SPEED ?" MESSAGE
LFECE:	MOV	A,M		;GET CHAR FROM MSG
	PUSH	H		;SAVE H,L
	CALL	LFD83		;PRINT MESSAGE
	POP	H		;RESTORE H,L
	INX	H		;POINT TO NEXT CHAR
	MOV	A,M		;GET IT
	ORA	A		;SET FLAGS
	JNZ	LFECE		;PRINT IT IF NOT ZERO
	CALL	IN8		;GET CHAR
	CALL	LFEA8		;TEST NUMERIC & SET SPEED
	CALL	CRLF		;DO CR/LF
	JMP	EORNS		;THEN BACK TO ALS-8
;
LFEE6:	DB	'SPEED?'
	DB	0
;
;
;ROUTINE TO PROCESS BACKSPACE (5FH)
;
LFEED:	LDA	NCHAR		;GET COLUMN
	MOV	B,A		;TO B
	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	CALL	LFE46		;TURN CURSOR OFF
	DCX	H		;POINT TO PREV CHAR
	MVI	M,' '		;REPLACE IT WITH SPACE
	MOV	A,B		;OLD COLUMN ADDR TO A
	ORA	A		;SET FLAGS
	JZ	LFF00		;DON'T BACK INTO PREV LINE
	DCR	B		;DECREMENT COLUMN
LFF00:	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	JMP	LFF1A		;UPDATE ROW, COL, CUR ON & RET
;
;CURSOR ON-OFF TOGGLE ROUTINES
;
LFF06:	LDA	LD197		;GET CURSOR ON-OFF FLAG
	XRI	01H		;TOGGLE LOW ORDER BIT
	STA	LD197		;PUT IT BACK
	ANI	01H		;MASK LOW ORDER BIT
	JNZ	LFF2A		;JUMP IF CURSOR OFF
LFF13:	LDA	NCHAR		;GET COLUMN
LFF16:	MOV	B,A		;TO A
	LDA	SLINE		;GET CURRENT LINE NO (0-F)
LFF1A:	ANI	0FH		;KEEP IT TO 0-15
	STA	SLINE		;UPDATE IT
	CALL	VDAD		;CALCULATE CURSOR ADDRESS
	MOV	A,B		;COLUMN TO A
	STA	NCHAR		;UPDATE IT
	MOV	A,M		;GET CHAR TO A
	JMP	LFC4D		;TURN ON CURSOR & RETURN
LFF2A:	STA	LD197		;UPDATE CURSOR FLAG
LFF2D:	LXI	H,NCHAR		;POINT TO COLUMN
	MOV	B,M		;GET IT TO B
	LDA	SLINE		;GET CURRENT LINE NO (0-F)
	CALL	LFE46		;TURN CURSOR OFF
	LXI	H,NCHAR		;FOR PROPER EXIT
	RET			;DONE, CURSOR OFF
;
;THIS IS THE ALS-8 (NOT TXT-2) FIND COMMAND
;
FIND2:	CALL	CRLF		;DO CR/LF
	CALL	LFF80		;GET SEARCH STRING
	LHLD	BOFP		;LOAD SEARCH STARTING POINT
LFF44:	CALL	LFFC2		;SEARCH FOR STRING
	CPI	1		;EOF FOUND ?
	RZ			;DONE IF YES
	LHLD	INSP		;ELSE POINT TO LINE W/STRING
	INX	H		;POINT PAST LENGTH BYTE
	CALL	SCRN		;PRINT LINE
	CALL	CRLF		;CAR. RET AT END OF LINE
	INX	H		;INR TO NEXT LINE
	JMP	LFF44		;AND CONTINUE SEARCH
;
;EDITOR STRING SEARCH
;
LFF58:	CALL	LFD4E		;CLEAR SCREEN
	CALL	LFF80		;GET SEARCH STRING
	LHLD	BOFP		;POINT TO BEGINNING OF FILE
	SHLD	LD19C		;SAVE AS SEARCH STARTING POINT
;
;CONTINUE SEARCH
;
LFF64:	LXI	SP,SMODE	;RESET STACK POINTER
	LHLD	LD19C		;GET SEARCH STARTING PT.
	CALL	LFFC2		;SEARCH FROM H,L FOR STRING
	CPI	1		;END OF FILE FOUND ?
	JZ	TXT2		;RESTART EDITOR THEN
	CALL	LFD4E		;
	XRA	A		;GET A ZERO
	MOV	B,A		;MAKE IT THE ROW
	CALL	LFF1A		;TURN CURSOR ON
	LHLD	INSP		;GET POINTER TO LINE W/STRING
	JMP	LFA27		;PUT TEXT ON SCRN & RET
;
;ROUTINE TO FIND STRING
;
LFF80:	MVI	B,':'		;GET PROMPT
	CALL	OUT8		;PRINT IT
	MVI	E,0		;INITIALIZE STRING LENGTH
	LXI	H,IBUF+81	;POINT TO STRING LOCATION
LFF8A:	CALL	IN8		;GET STRING CHAR
	CPI	7FH		;DELETE ?
	JNZ	LFFA1		;NO - MUST BE CHAR
	MOV	A,E		;ELSE MOVE LENGTH TO A
	ORA	A		;ZERO ?
	JZ	LFF8A		;NO ACTION IF ZERO
	DCR	E		;ELSE DCR STRING LENGTH
	DCX	H		;AND STRING POINTER
	MVI	B,5FH		;GET A BACKSPACE CHAR
LFF9B:	CALL	OUT8		;AND PRINT IT
	JMP	LFF8A		;THEN GET THE NEXT CHAR
LFFA1:	CPI	0DH		;CARRIAGE RETURN ?
	JNZ	LFFB6		;NO - MUST BE CHAR
	MOV	A,E		;ELSE GET LENGTH TO A
	ORA	A		;SET FLAGS
	JNZ	LFFB1		;IF NOT ZERO, DONE
	CALL	CRLF		;ELSE PRINT CRLF
	JMP	LFF80		;AND GET STRING (AGAIN)
LFFB1:	MOV	M,B		;MOVE C/R TO STRING BUFFER
	CALL	CRLF		;PRINT CR/LF
	RET			;AND RETURN W/STRING IN BUFFER
LFFB6:	CPI	20H		;IS CHAR A CNTL CHAR ?
	JC	LFF8A		;IGNORE IT THEN
	INR	E		;ELSE INR LENGTH
	MOV	M,B		;PUT CHAR IN STRING
	INX	H		;INR POINTER
	JMP	LFF9B		;AND DO NEXT CHAR
;
;ROUTINE TO SEARCH FOR STRING
;
LFFC1:	INX	H		;POINT PAST LENGTH BYTE
LFFC2:	SHLD	INSP		;AND SAVE AS POINTER
	MVI	C,0		;INITIALIZE COUNTER
LFFC7:	LXI	D,IBUF+81	;GET STRING LENGTH
	MOV	A,M		;GET CHAR FROM LINE
	CPI	1		;END OF FILE ?
	RZ			;IF SO, RETURN
LFFCE:	INX	H		;ELSE INCR LINE POINTER
	INR	C		;AND COUNT OF CHARS TESTED
	LDAX	D		;GET CHAR FROM STRING
	CMP	M		;STRING & LINE AGREE ?
	INX	D		;INR STRING POINTER
	JZ	LFFE7		;AND KEEP TESTING
	CPI	0DH		;WAS NON-MATCH DUE TO C/R ?
	RZ			;YES - STRING MATCHED THEN
	MOV	A,M		;ELSE MOVE LINE CHAR TO A
	CPI	0DH		;AND SEE IF END OF LINE
	JZ	LFFC1		;IT WAS - GO TO NEXT LINE
LFFDF:	DCR	C		;ELSE DCR MATCH COUNT
	JZ	LFFC7		;BACK TO WHERE WE STARTED ?
	DCX	H		;NO - DCR LINE POINTER
	JMP	LFFDF		;AND TEST AGAIN
LFFE7:	CPI	0DH		;MATCH - END OF STRING TOO ?
	RZ			;THAT'S STILL A MATCH
	MOV	A,M		;ELSE GET LINE CHAR
	CPI	0DH		;AND SEE IF END OF LINE
	JZ	LFFC1		;IF SO TEST NEXT LINE
	JMP	LFFCE		;ELSE GO ON WITH TEST
;
;ESET COMMAND TO SET UPPER LIMIT ON EDITOR TEXT BUFFER
;
LFFF3:	LHLD	BBUF		;GET VALUE OF UPPER LIMIT
	SHLD	LD191		;SAVE IT
	JMP	EORMS		;AND GO BACK TO ALS-8
;
; **** END OF ALS8TXT MODULE
;
;
	ORG	DATA		;START OF SYSTEM GLOBAL
;
;SYSTEM GLOBAL AREA
;
UDATA	EQU	1		;DATA PORT NUMBER
DAV	EQU	40H		;DATA AVAILABLE AT BIT 6
TBE	EQU	80H		;TRANS. BUFFER EMPTY AT BIT 7
USTA	EQU	0		;UART STATUS PORT
UDAI	EQU	1		;UART DATA
UDAO	EQU	1		;UART DATA
SWCH	EQU	0FFH		;SENSE SWITCH
;
;FILE AREA PARAMETERS
;
MAXFIL	EQU	6		;MAX # OF FILES
NMLEN	EQU	5		;NAME LENGTH
FELEN	EQU	NMLEN+8		;DIRECTORY ENTRY LENGTH
;
;FILE TABLE
;
;FILE 0 IS THE "CURRENT FILE" ALL OTHER FILES
;ARE STORED IN THE FILE TABLE IN THIS FORMAT
;
FILE0	DS	NMLEN		;CURRENT FILE LOCATION
BOFP	DS	2		;BEGINNING OF FILE POINTER
EOFP	DS	2		;END OF FILE POINTER
MAXL	DS	4		;MAXIMUM LINE NUMBER IN FILE
;
FILTB	DS	(MAXFIL-1)*FELEN;REST OF FILE TABLE
;
;I/O DRIVER TABLES
;
IOFLE	DS	(MAXFIL-1)*FELEN
SYSIO	DS	NMLEN
SYSIN	DS	2
SYSOT	DS	2		;OUTPUT DRIVER ADDRESS
;
;THE INPUT DRIVER
;
INDR	DS	OUTP8-INP8
;
;THE OUTPUT DRIVER
;
OUTDR	DS	CRLF-OUTP8	;OUTPUT DRIVER
IN8	DS	3		;DRIVER JUMP POINTS
OUT8	DS	3
STAT	EQU	INDR+12
NOCHR	EQU	OUTDR+0FH
;
;SYSTEM PARAMETERS
;
INSP	DS	2		;INSERT LINE POSITION
DELP	EQU	INSP		;DELETE LINE POSITION
ASCR	EQU	13
ESC	EQU	1BH
COMCHR	EQU	'*'		;ASSEMBLER COMMENT CHARACTER
HCON	DS	3		;CONVERSION AREA
ADDS	EQU	HCON		;FIND ADDRESS
FBUF	DS	NMLEN		;FILE NAME BUFFER
FREAD	DS	2		;FREE ADDRESS IN DIRECTORY
FEF	DS	1		;FREE ENTRY FOUND FLAG
FOCNT	EQU	FEF		;OUTPUT COUNTER
ABUF	DS	16		;ASCII BUFFER AREA
BBUF	DS	4		;BINARY BUFFER
SCNT	DS	1		;SYMBOL COUNT
DCNT	DS	1		;DUMP ROUTINE COUNTER
TABA	DS	2		;SYMBOL TABLE END ADDRESS
ASPC	DS	2		;ASSEMBLER PROGRAM COUNTER
PASI	DS	1		;PASS INDICATOR
LFMT	DS	1		;FORMAT CONTROL
NOLIN	DS	1
IOSWC	DS	1		;I/O SWITCH INDICATOR
SWCH1	DS	1
SWCH2	DS	1
XOUT	DS	1		;SCRN PARAMETER
ASMTY	DS	1		;ASSEMBLY TYPE FLAG
PNTR	DS	2		;LINE POINTER STORAGE
NOLA	DS	1		;NUMBER OF LABELS
SIGN	DS	1		;SIGN STORAGE FOR SCAN
OPRD	DS	2
OPRI	DS	1
GTLT	DS	1
TEMP	DS	1
APNT	EQU	INSP
AERR	EQU	DCNT
ALST	DS	1
OIND	DS	2
LLAB	EQU	5
	DS	16
AREA	DS	14
LD12B	DS	4
SMODE	DS	1
SYMSV	DS	2
CCNT	EQU	SCNT
SYMX	EQU	AERR
SYMADD	DS	2
LD134	DS	1		;SIM. BREAKPOINT FLAG
LD135	DS	1		;SIM. REAL-TIME RUN FLAG
LD136	DS	1		;SIM. INPUT PORT ASSIG. FLAG
LD137	DS	1		;SIM. OUTPUT PORT ASSIG. FLAG
LD138	DS	2		;SIM. BREAKPOINT ADDR.
LD13A	DS	2		;SIM. REAL TIME RUN ADDR
LD13C	DS	2		;SIM. PROGRAM COUNTER
LD13E	DS	2		;ADDR FOR NEXT INST TO EXECUTE
LD140	DS	2		;SIM. STACK POINTER
LD142	DS	2		;SIM. FLAG REGISTER & ACCUM.
LD144	DS	1		;SIM. "L" REGISTER
LD145	DS	1		;SIM. "H" REGISTER
LD146	DS	1		;SIM. "E" REGISTER
LD147	DS	1		;SIM. "D" REGISTER
LD148	DS	1		;SIM. "C" REGISTER
LD149	DS	1		;SIM. "B" REGISTER
LD14A	DS	1		;SIM. ACCUM (2ND COPY)
LD14B	DS	1		;SIM. MODE
LD14C	DS	3		;STORAGE FOR INST TO BE SIM.
LD14F	DS	3		;STORAGE FOR JMP RETN TO SIM.
LD152	DS	16		;SIMULATOR'S INPUT TABLE
LD162	DS	16		;SIMULATOR'S OUTPUT TABLE
	ORG	DATA+18FH
TERMW	DS	1
CHRR	DS	1
LD191	DS	2		;ESET UPPER TEXT BUFFER LIMIT
BOTL	DS	1		;BEGINNING OF TEXT LINE (0-F)
BOSL	DS	1		;BEGINNING OF SCREEN LINE (0-F)
SLINE	DS	1		;CURRENT LINE (0-F)
NCHAR	DS	1		;CURRENT COLUMN POSITION (0-63)
LD197	DS	1		;CURSOR ON-OFF FLAG
LD198	DS	1		;INSERT MODE FLAG
LD199	DS	1
LD19A	DS	2
LD19C	DS	2
LD19E	DS	2
SPEED	DS	1		;DISPLAY DRIVER SPEED BYTE
LD1A1	DS	2		;UNDEFINED COMMAND ADDRESS
USARE	DS	38		;USER AREA
OBUF	DS	22
	DS	5
IBUF	DS	120		;INPUT BUFFER
EDIT	EQU	0FA0EH
SAVL	EQU	OBUF
CUCOM	DS	70		;CUSTOM COMMAND TABLE
	ORG	DATA+300H
SYSYM	DS	2		;START OF SYSTEM SYMBOL TABLE
SYMT	EQU	CODE
;
	END
;
; **** END OF EVERYTHING
;



