;
;	   8080A Microprocessor Instruction Set Emulator
;   by Jeff Sheese, RETS Tech Center, Centerville, Ohio 45459
;
;			     8-18-82
;
;    The 8080A Instruction Set Emulator is a teaching tool used to 
;demonstrate  the operation of the assembly language commands  and 
;how  they affect the memory and microprocessor register contents.  
;The  emulator was designed to operate the computer in	a  machine 
;language  'direct' mode.   In BASIC,  the 'direct' mode is when a 
;person  types in a command such as PRINT and watches the  results 
;of   the  command.    The  emulator  will  speed   learning   and 
;comprehension in a positive and instructive atmosphere.
;
;    When the emulator is run, a sign-on message is printed on the 
;screen, and immediately following is the prompt:
;
;Initial status:
;PC    S Z A P C  A  B	C  D  E  H  L  M  SP	STACK
;2000  0 0 0 0 0  00 00 00 00 00 00 00 00 0000	0000
;
;Instruction?_
;
;    The  first line is a description of the type of registers	in 
;the microprocessor.  Under each description is the actual content 
;of the register.   The letters S,  Z,	A, P, and C are the status 
;flags.   They change as the microprocessor status changes.  Their 
;functions and descriptions follow:
;
;    Sign  flag  - This flag shows whether the result of the  last 
;operation was positive or negative.   The sign flag will be a one 
;if negative,  or a zero if positive.	It will be the same as the 
;most significant bit in the accumulator.
;
;    Zero  flag - This flag shows whether the result of  the  last 
;operation was zero.  If the result is zero, the flag will be one.  
;If it was not zero, the flag will be zero.
;
;    Auxiliary	carry  flag - If the result of the last  operation 
;caused  a  carry from bit three to bit four,  this will  be  one.  
;This flag is only used for the DAA instruction.
;
;    Parity flag - This flag shows whether the result of the  last 
;operation  resulted  in  an  even or odd number of  ones  in  the 
;resulting byte.  This flag will be one if there is an even number 
;one of bits, or odd if there is an odd number of one bits.
;
;    Carry  flag - This flag shows whether the result of the  last 
;operation  caused a carry or a borrow from the  last  significant 
;bit  of  the result.	It will be one if a carry or a borrow  did 
;occur, or it will be zero if it did not occur.
;
;    The  rest of the line will show the different  registers.	 A 
;description of the registers follow:
;
;    PC  - This  will  show the current  address  of  the  program 
;counter.   Do not let this go below 2000H.   If it does,  you may 
;accidentally  alter memory that is essential for the emulator	or 
;the operating system of your computer.
;
;    A	- This will show the contents of the accumulator after the 
;last instruction typed.
;
;    B	- This will show the contents of the B register after  the 
;last instruction typed.
;
;    C	- This will show the contents of the C register after  the 
;last instruction typed.
;
;    D	- This will show the contents of the D register after  the 
;last instruction typed.
;
;    E	- This will show the contents of the E register after  the 
;last instruction typed.
;
;    H	- This will show the contents of the H register after  the 
;last instruction typed.
;
;    L	- This will show the contents of the L register after  the 
;last instruction typed.
;
;    M - This will show the contents of the memory address pointed 
;to by the H-L register pair.
;
;    SP  - This will show the address that is the current  top	of 
;the stack.
;
;    STACK  - This will show the last two bytes that were actually 
;entered on the stack.	This is data, not a memory address.
;
;
;    The  next	thing  to  do is to  actually  type  in  an  8080A 
;mnemonic.   If you have a copy of the 8080A instruction set,  you 
;type  in  the	mnemonic  the same as if  you  were  executing	an 
;assembly  language program.   This emulator does not support  the 
;use  of labels.   All numbers that are input and displayed are in 
;hexidecimal  format.	After  typing in  the  instruction,  press 
;return, and the emulator will display the new status.
;
;    WARNING:
;    DO  NOT  ALTER ANY MEMORY LOCATIONS BELOW	2000  HEX.   THESE 
;MEMORY  LOCATIONS ARE ESSENTIAL FOR THE EMULATOR PROGRAM AND  THE 
;OPERATING  SYSTEM OF YOUR COMPUTER.   THE MNEMONICS  AND  COMMAND 
;THAT ARE TYPED IN ARE ACTUALLY EXECUTED.
;
;
CR	EQU	0DH		;CARRIAGE RETURN
LF	EQU	0AH		;LINE FEED
CONOUT	EQU	2		;CONSOLE OUTPUT
CONIN	EQU	1		;CONSOLE INPUT
BDOS	EQU	5		;BDOS CALL
BEL	EQU	7		;BELL CODE
DEL	EQU	7FH		;DELETE CHARACTER
FALSE	EQU	0FFFFH		;FALSE CONDITION
BSPACE	EQU	8		;BACKSPACE CHARACTER
wboot	equ	0
;
; DISPLAY HEADING ON CRT
;
	ORG	0100H		;START OF TPA
BEGIN	LXI	SP,STACK	;SET UP STACK POINTER
	CALL	SHOTEL		;PRINT THE FOLLOWING
	DB	cr,lf,lf,'            8080 INSTRUCTION '
	DB	'SET EMULATOR',CR,LF,LF
	DB	CR,LF,'Initial Status:',CR,LF,0
;
;ZERO PROGRAM STASHES
;
	MVI	B,0CH		;COUNTER FOR 12 LOCATIONS
	LXI	H,PCSTOR+2	;START OF STORAGE AREA
;
	MVI	M,00H		;PUT 1000H IN PC COUNT
	INX	H		;
	MVI	M,10		;
	INX	H		;
	DCR	B		;
ZLOOP	MVI	M,0		;PUT 0 AT H-L ADDRESS
	INX	H		;SET H-L TO NEXT LOCATION
	DCR	B		;COUNT 1 LOCATION DONE
	JNZ	ZLOOP		;DO SOME MORE UNTIL B=0
;
;DISPLAY EMULATOR CPU STATUS
;
	JMP	SPREAD		;ROUTINE FOR HEADING AND STATUS
;
;INPUT A LINE OF TYPING
;
NEXT1	LXI	H,BUFFER	;SET H-L TO STORAGE AREA
	LXI	SP,STACK	;RESET STACK POINTER
;
INLOOP	CALL	INPUT		;GET KEYBOARD CHARACTER
	CPI	bspace		;IS IT DELETE?
	JZ	ERASE		;YES, ERASE IT
	cpi	7bh		;'z' or less?
	jnc	inloop2 	;no, continue
	cpi	61h		;'a' or greater?
	jc	inloop2 	;no, continue
	ani	0dfh		;yes, convert lower to upper case
inloop2
	cpi	03h		;is it ctrl-c?
	jz	wboot		;yes, warm boot
	MOV	M,A		;NO,STORE IT
	INX	H		;SET H-L TO NEXT ADDRESS
	CPI	CR		;IS IT CR?
	JZ	DONEIN		;YES, FINISHED
	JMP	INLOOP		;NO, GET NEXT CHARACTER
;
ERASE	DCX	H		;NO, BACK UP
;	MVI	A,BSPACE	;GET BACKUP CODE
;	CALL	OUTPUT		;DISPLAY IT
	JMP	INLOOP		;RETURN FOR MORE
;
;FIND MNEMONIC IN TABLE
;
DONEIN	LXI	H,TABLE 	;SET H-L TO START OF TABLE
	MVI	B,0		;INITIALIZE COUNTER
;
FINDIT	LXI	D,BUFFER-1	;SET D-E TO ONE BEFORE BUFFER
;
KEEPON	INX	D		;NEXT BUFFER CHARACTER
	LDAX	D		;GET CHARACTER FROM BUFFER
	CMP	M		;SAME AS CHARACTER IN TABLE?
	MOV	A,M		;GET CHARACTER FROM TABLE
	INX	H		;SET H-L TO NEXT TABLE CHARACTER
	JZ	KEEPON		;KEEP LOOKING IF CHARS MATCH
	CPI	20H		;IS IT LOWER THAN ASCII SPACE?
	JC	FOUND		;CARRY MEANS ENTRY FOUND
;
PASSBY	MOV	A,M		;GET NEXT CHARACTER
	INX	H		;SET H-L TO NEXT TABLE CHAR.
	CPI	20H		;IS IT A TYPE BYTE?
	JNC	PASSBY		;NO, KEEP GOING
	INR	B		;ADD ONE TO COUNTER
	JNZ	FINDIT		;CHECK NEXT CHAR IF STILL OK
	MVI	A,1		;INVALID-LOAD A WITH TYPE 1
;
;SET UP OPCODES AND ARGUMENTS
;
FOUND	PUSH	PSW		;SAVE TYPE BYTE ON STACK
	MOV	A,B		;CODE TO REG. A
	STA	OPCODE		;STORE THE BYTE
	STA	CONDTN		;STORE AT "CONDTN" ALSO
	LXI	H,0000H 	;TWO NOP'S IN H-L
	SHLD	ARGMNT		;STORE THEM AT ARGUMENT
	SHLD	ADDRES		;STORE AT "ADDRES" ALSO
;
;SKIP TO APPROPRIATE HANDLER ROUTINE AND EXECUTE
;
	POP	PSW		;GET TYPE BYTE BACK IN A
	DCR	A		;MAKES IT 00 IF TYPE 1
	JNZ	TYPE2		;TRY NEXT TYPE IF NOT 0
;
;ROUTINE FOR TYPE 1 INSTRUCTIONS
;
	CALL	SHOTEL		;DISLAY ERR MESSAGE
	DB	CR,LF,'    ***Invalid Mnemonic***',BEL,0
	JMP	NEXT2		;GET PROPER MNEMONIC
;
TYPE2	DCR	A		;MAKES IT 0 IF TYPE 2
	JNZ	TYPE3		;TRY NEXT TYPE IF NOT 0
;
;ROUTINE FOR TYPE 2 INSTRUCTIONS
;
	MVI	C,1		;THESE ARE ONE-BYTE INSTRUCTIONS
	LDAX	D		;GET CHARACTER AFTER MNEMONIC
	CPI	CR		;MAKE SURE ITS 0DH
	JZ	DOINST		;GO EMULATE IF ALL IS OK
;
BADOP	CALL	SHOTEL		;DISPLAY ERR MESSAGE IF NOT
	DB	CR,LF,'    ***Bad Operand***',BEL,0
	JMP	NEXT2		;GET PROPER ENTRY
;
TYPE3	DCR	A		;MAKES IT 0 IF TYPE 3
	JNZ	TYPE4		;TRY NEXT TYPE IF NOT 0
;
;ROUTINE FOR TYPE 3 INSTRUCTION
;
	LDAX	D		;GET CHARACTER AFTER MNEMONIC
	CPI	CR		;MAKE SURE ITS CR
	JNZ	BADOP		;DISPLAY ERR IF NOT
	LHLD	SPSTOR		;GET EMULATOR STACK POINTER
	SPHL			;MAKE IT THE REAL ONE
	LHLD	PCSTOR		;GET EMULATOR PROGRAM COUNTER
	INX	H		;POINT TO NEXT INSTRUCTION
	PUSH	H		;WRITE RETURN ADDRESS ON STACK
	LXI	H,0000H 	;ZERO H-L
	DAD	SP		;ADD NEW STACK POINTER
	SHLD	SPSTOR		;UPDATE STACK POINTER STASH
	LXI	SP,STACK	;MAKE OUR STACK POINTER REAL
	MOV	A,B		;GET INTRUCTION CODE
	ANI	38H		;STRIP NON-UNIQUE BITS
	MOV	L,A		;MOVE NEW VALUE TO L
	MVI	H,0000H 	;MAKE H ZERO
	SHLD	PCSTOR		;STORE ADDRESS AS PROGRAM COUNTER
	JMP	SPREAD		;SHOW NEW EMULATOR STATUS
;
TYPE4	DCR	A		;MAKES IT 0 IF TYPE 4
	JNZ	TYPE5		;TRY NEXT TYPE IF NOT 0
;
;ROUTINE FOR TYPE 4 INSTRUCTION
;
	LDAX	D		;GET NEXT CHAR AFTER MNEMONIC
	CPI	CR		;MAKE SURE ITS A CR
	JNZ	BADOP		;DISPLAY ERR IF NOT
	CALL	SHOTEL		;DISPLAY EXIT MESSAGE
	DB	CR,LF,'  ***Reboot Disk***',BEL,0
	JMP	WBOOT
;
TYPE5	DCR	A		;MAKES IT 0 IF TYPE 5
	JNZ	TYPE6		;TRY NEXT TYPE IF NOT 0
;
;ROUTINE FOR TYPE 5 INSTRUCTION
;
	LDAX	D		;GET CHARACTER AFTER MNEMONIC
	CPI	CR		;MAKE SURE ITS A CR
	JNZ	BADOP		;DISPLAY ERR IF NOT
	LHLD	HSTOR		;GET EMULATOR H-L DATA
	SHLD	PCSTOR		;MAKE IT PROGRAM COUNTER
	JMP	SPREAD		;SHOW NEW EMULATOR STATUS
;
TYPE6	DCR	A		;MAKES IT 0 IF TYPE 6
	JNZ	TYPE7		;TRY NEXT TYPE IF NOT 0
;
;ROUTINE FOT TYPE 6 INSTRUCTION
;
	LDAX	D		;GET CHARACTER AFTER MNEMONIC
	CPI	CR		;MAKE SURE ITS A CR
	JNZ	BADOP		;DISPLAY ERR IF NOT
	MVI	C,1		;RETURNS ARE 1 BYTE
	CALL	UPDATE		;UPDATE PROGRAM COUNTER
	CALL	CTEST		;CALL CONDITIONAL TEST
;
;RETURN HERE IF CONDITION MET
;
	LHLD	SPSTOR		;GET EMULATOR STACK POINTER
	SPHL			;MAKE IT REAL
	POP	H		;GET LAST ENTRY ON STACK
	SHLD	PCSTOR		;MAKE IT THE PROGRAM COUNTER
	LXI	H,0000H 	;ZERO H-L REGISTERS
	DAD	SP		;ADD THE STACK POINTER
	SHLD	SPSTOR		;STORE IN STACK POINTER STASH
	LXI	SP,STACK	;MAKE OUR STACK POINTER REAL
	JMP	SPREAD		;DISPLAY NEW EMULATOR STATUS
;
;GET NUMERICAL ARGUMENTS FOR REST OF INSTRUCTION TYPES
;
TYPE7	PUSH	PSW		;SAVE INSTRUCTION TYPE
	LXI	B,0000H 	;ZERO B-C REGISTERS
	LXI	H,0000H 	;ZERO H-L REGISTERS
	LDAX	D		;DID WE GET AN ARGUMENT?
	CPI	CR		;WON'T BE CR IF SO
	JNZ	HLOOP		;ITS OK IF NOT CR
	CALL	SHOTEL		;SAY ITS A BADDIE
	DB	CR,LF,'    ***Missing Argument***',BEL,0
	JMP	NEXT2		;GO DO IT AGAIN
;
HLOOP	LDAX	D		;GET NEXT CHAR FROM BUFFER
	INX	D		;SET D-E TO NEXT BUFFER ADDRESS
	CPI	CR		;END OF HEX VALUE?
	JZ	NOMORE		;CONVERSION FINISHED IF SO
	SUI	30H		;REMOVE ASCII BIAS
	JC	ERROR		;NO GOOD IF GET A CARRY
	CPI	0AH		;IS IT 0 THRU 9?
	JC	HEXOK		;IT'S OK IF SO
	SUI	7		;TRY HEX LETTERS
	CPI	0AH		;IS IT LESS THAN 0AH?
	JC	ERROR		;NO GOOD IF SO
	CPI	10H		;HIGHER THAN OF HEX?
	JNC	ERROR		;NO GOOD IF SO
;
HEXOK	DAD	H		;H-L = H-L TIMES TWO
	DAD	H		;H-L = H-L TIMES FOUR
	DAD	H		;H-L = H-L TIMES EIGHT
	DAD	H		;H-L = H-L TIMES SIXTEEN
	MOV	C,A		;NEW UNIT VALUE TO C
	DAD	B		;ADD UNIT VALUE TO TOTAL
	JMP	HLOOP		;LOOP FOR NEXT DIGIT
;
ERROR	CALL	SHOTEL		;DISPLAY ERROR MESSAGE
	DB	CR,LF,'    ***Bad Character in Operand***',BEL,0
	JMP	NEXT2		;START OVER
;
NOMORE	SHLD	ARGMNT		;STORE VALUE AS ARGUMENT
	POP	PSW		;GET INSTRUCTION TYPE BACK
;
	DCR	A		;MAKES IT 0 IF TYPE 7
	JNZ	TYPE8		;TRY NEXT TYPE IF NOT 0
;
;ROUTINE FOR TYPE 7 INSTRUCTIONS
;
	MVI	C,2		;THESE ARE TWO BYTE INSTRUCTIONS
	MOV	A,H		;GET HIGH BYTE OF ARGUMENT
	ORA	A		;MUST BE ZERO FOR TWO BYTE TYPES
	JZ	DOINST		;GO EMULATE IF ALL OK
	CALL	SHOTEL		;DISPLAY ERR MESSAGE
	DB	CR,LF,'    ***Argument too Large***',BEL,0
	JMP	NEXT2		;START OVER
;
TYPE8	DCR	A		;MAKES IT 0 IF TYPE 8
	JNZ	TYPE9		;TRY NEXT TYPE IF NOT 0
;
;ROUTINE FOR TYPE 8 INSTRUCTION
;
	XCHG			;SAVE TYPED IN ARGUMENT
	MVI	C,3		;JUMPS ARE THREE BYTES
	CALL	UPDATE		;UPDATE PROGRAM COUNTER
	LXI	H,JBACK 	;LOAD H-L WITH ADDRESS OF JBACK
	SHLD	ADDRES		;STORE AS ARGUMENT OF COND INSTR
	JMP	CTEST		;GO TO CONDITIONAL TEST
;
JBACK	XCHG			;GET TYPED-IN ARGUMENT BACK
	SHLD	PCSTOR		;STORE NEW PROGRAM COUNT
	JMP	SPREAD		;DISPLAY NEW EMULATOR STATUS
;
TYPE9	DCR	A		;MAKES IT 0 IF TYPE 9
	JNZ	TYPE10		;DO TYPE 10 IF NOT 0
;
;ROUTINE FOR TYPE 9 INSTRUCTIONS
;
	XCHG			;SAVE TYPED IN ARGUMENT
	MVI	C,3		;CALLS ARE THREE BYTES
	CALL	UPDATE		;UPDATE PROGRAM COUNTER
	LXI	H,CBACK 	;LOAD H-L ADDRESS WITH CBACK
	SHLD	ADDRES		;STORE AS ARGMNT OF COND INSTR
	JMP	CTEST		;GO DO COND TEST
;
CBACK	LHLD	SPSTOR		;GET EMULATOR STACK POINTER
	SPHL			;MAKE IT THE REAL ONE
	LHLD	PCSTOR		;GET EMULATOR PROGRAM COUNTER
	PUSH	H		;WRITE RETURN ADDRESS ON STACK
	LXI	H,0000H 	;ZERO H-L REG.
	DAD	SP		;ADD NEW STACK POINTER
	SHLD	SPSTOR		;UPDATE STACK POINTER STASH
	LXI	SP,STACK	;MAKE OUR STACK POINTER REAL
	XCHG			;GET TYPED IN ARGUMENT
	SHLD	PCSTOR		;MAKE IT THE PROGRAM COUNTER
	JMP	SPREAD		;DISPLAY NEW EMULATOR STATUS
;
;ROUTINE FOR TYPE 10 INSTRUCTIONS
;
TYPE10	MVI	C,3		;THESE ARE THREE BYTE INSTRUCTIONS
;
;DO INSTRUCTIONS THAT CAN BE EXECUTED
;
DOINST	CALL	UPDATE		;UPDATE PROGRAM COUNTER
	LHLD	PSWSTR		;GET EMULATOR PSW
	PUSH	H		;PUSH ONTO STACK
	POP	PSW		;POP OFF STACK INTO PLACE
	LHLD	BSTOR		;GET EMULATOR B-C
	PUSH	H		;PUSH ONTO STACK
	POP	B		;POP OFF STACK INTO PLACE
	LHLD	DSTOR		;GET EMULATOR D-E
	PUSH	H		;PUSH ONTO STACK
	POP	D		;POP OFF STACK INTO PLACE
	LHLD	SPSTOR		;GET EMULATOR STACK POINTER
	SPHL			;MAKE IT REAL
	LHLD	HSTOR		;GET EMULATOR H-L
;
OPCODE	DS	1		;CPU CODE GOES HERE
ARGMNT	DS	2		;NUMERICAL ARGUMENTS GO HERE
;
	STA	PSWSTR		;SAVE ACCUMULATOR FOR NOW
	RAR			;ROTATE CARRY FLAG TO ACCUMULATOR
	SHLD	HSTOR		;H-L TO STASH
	LXI	H,0		;ZERO H-L REGISTERS
	DAD	SP		;ADD IN STACK POINTER
	SHLD	SPSTOR		;STACK POINTER TO STASH
	LXI	SP,STACK	;MAKE STACK POINTER REAL
	RAL			;ROTATE CARRY FLAG INTO PLACE
	LDA	PSWSTR		;GET ACCUMULATOR BACK
	PUSH	PSW		;PUSH PSW ONTO STACK
	POP	H		;POP IT INTO H-L
	SHLD	PSWSTR		;PSW TO STASH
	PUSH	B		;PUSH B-C ONTO STACK
	POP	H		;POP IT INTO H-L
	SHLD	BSTOR		;B-C TO STASH
	PUSH	D		;PUSH D-E ONTO STASH
	POP	H		;POP IT INTO H-L
	SHLD	DSTOR		;D-E TO STASH
;
;DISPLAY THE HEADING AND THE EMULATOR STATUS
;
SPREAD	CALL	SHOTEL		;DISPLAY THE HEADING
	DB	CR,LF,lf,'PC    S Z A P C  A  B  C  D  E  H'
	DB	'  L  M   SP    STACK',CR,LF,0
	LHLD	PCSTOR		;GET PROGRAM COUNTER
	XCHG			;MOVE ADDRESS TO D-E
	CALL	HWORD		;DISPLAY AS HEX WORD
	CALL	BLANK2		;PRINT TWO SPACES
	LHLD	PSWSTR		;GET PROCESSOR STATUS WORD
	MOV	A,L		;FLAG REGISTER TO A
	CALL	AFLAG		;DISPLAY THE SIGN FLAG
	CALL	AFLAG		;DISPLAY THE ZERO FLAG
	RLC			;PASS BY UNUSED BIT
	CALL	AFLAG		;DISPLAY THE AUX CARRY FLAG
	RLC			;PASS BY UNUSED BIT
	CALL	AFLAG		;DISPLAY PARITY FLAG
	RLC			;PASS BY UNUSED BIT
	CALL	AFLAG		;DISPLAY CARRY FLAG
	CALL	BLANK1		;PRINT ONE SPACE
	MOV	E,H		;GET REGISTER A DATA
	CALL	HBYTE		;DISPLAY AS HEX
	CALL	BLANK1		;PRINT ONE SPACE
	LHLD	BSTOR		;GET B-C REGISTER DATA
	CALL	SHOREG		;DISPLAY THE REGISTERS IN HEX
	LHLD	DSTOR		;GET D-E REGISTER DATA
	CALL	SHOREG		;DISPLAY THE REGISTERS IN HEX
	LHLD	HSTOR		;GET H-L REGISTER DATA
	CALL	SHOREG		;DISPLAY THE REGISTERS IN HEX
	MOV	E,M		;GET MEMORY DATA AT H-L ADDRESS
	CALL	HBYTE		;DISPLAY IN HEX
	CALL	BLANK2		;PRINT TWO SPACES
	LHLD	SPSTOR		;GET STACK POINTER DATA
	XCHG			;PUT STACK POINTER IN D-E
	CALL	HWORD		;DISPLAY AS HEX
	CALL	BLANK2		;PRINT TWO SPACES
	XCHG			;STACK POINTER BACK TO H-L
	MOV	E,M		;LOW BYTE OF DATA ON STACK TOP
	INX	H		;SET H-L TO NEXT ADDRESS
	MOV	D,M		;HIGH BYTE OF DATA ON STACK TOP
	CALL	HWORD		;DISPLAY AS HEX
;
NEXT2	CALL	SHOTEL		;DISPLAY MESSAGE
	DB	CR,LF,lf,'Instruction:  ',0
	JMP	NEXT1		;GET NEXT INSTRUCTION TO EMULATE
;
;DISPLAY "0" OR "1" FOR FLAG STATUS
;
AFLAG	RLC			;MOVE LEFTMOST BIT INTO CARRY
	MOV	L,A		;SAVE MODIFIED BIT
	MVI	A,'1'		;ANTICIPATE FLAG IS SET
	JC	FLAGON		;DISPLAY "1" IF SET
	MVI	A,'0'		;DISPLAY "0" IF RESET
;
FLAGON	CALL	OUTPUT		;DISPLAY "1" OR "0"
	CALL	BLANK1		;PRINT ONE SPACE
	MOV	A,L		;GET THE FLAG BYTE BACK
	RET
;
;DISPLAY H-L AS INDIVIDUAL REGISTERS
;
SHOREG	MOV	E,H		;DO HIGH BYTE FIRST
	CALL	HBYTE		;DISPLAY AS HEX
	CALL	BLANK1		;PRINT ONE SPACE
	MOV	E,L		;DO LOW BYTE NEXT
	CALL	HBYTE		;DISPLAY AS HEX
	JMP	BLANK1		;PRINT ONE SPACE
;
;PRINT ONE OR TWO BLANK SPACES
;
BLANK2	CALL	BLANK1		;PRINT TWO BLANK SPACES
;
BLANK1	MVI	A,' '		;PRINT ONE SPACE
	JMP	OUTPUT		;DISPLAY THE SPACE
;
;TEST CONDITIONAL INSTRUCTIONS
;
CTEST	LHLD	PSWSTR		;GET CONDITION FLAGS
	PUSH	H		;PUSH THEM ONTO STACK
;
CONDTN	DS	1		;HEX CPU CODE GOES HERE
ADDRES	DS	2		;ADDRESS ARGUMENT GOES HERE
	JMP	SPREAD		;DISPLAY OLD STATUS IF CONDITION FAILS
;
;UPDATE THE PROGRAM COUNTER
;
UPDATE	LHLD	PCSTOR		;GET PROGRAM COUNTER
	MVI	B,0		;ZERO REGISTER B
	DAD	B		;ADD INSTRUCTION LENGTH TO PC
	SHLD	PCSTOR		;STORE NEW PROGRAM COUNTER
	RET			;RETURN
;
;OUTPUT A MESSAGE
;
SHOTEL	XTHL			;GET ADDRESS OF MESSAGE FROM STACK
DISPL	MOV	A,M		;GET CHARACTER TO DISPLAY
	INX	H		;SET H-L TO NEXT ADDRESS
	ORA	A		;TEST FOR DELIMITER
	JZ	EXIT		;FINISH IF END OF MESSAGE
	CALL	OUTPUT		;DISPLAY THE CHARACTER
	JMP	DISPL		;LOOP FOR NEXT CHARACTER
;
EXIT	XTHL			;FIX H-L AND STACK
	RET			;RETURN
;
;OUTPUT A BYTE IN HEX
;
HWORD	MOV	A,D		;DO HIGH BYTE FIRST
	CALL	DOHEX
;
HBYTE	MOV	A,E		;DO LOW BYTE
;
DOHEX	PUSH	PSW		;SAVE THE BYTE ON THE STACK
	RRC			;ROTATE LEFT 4 BITS INTO PLACE
	RRC			;
	RRC			;
	RRC			;
	CALL	HEXOUT		;MAKE ASCII AND DISPLAY
	POP	PSW		;GET THE BYTE BACK
;
HEXOUT	ANI	0FH		;KEEP ONLY RIGHT FOUR BITS
	ADI	30H		;ADD ASCII OFFSET
	CPI	':'		;IS IT A NUMBER?
	JC	OUTPUT		;YES, DISPLAY IT
	ADI	7		;MAKE IT A LETTER
	JMP	OUTPUT		;DISPLAY THE LETTER ON THE CRT
;
;KEYBOARD INPUT
;
INPUT	PUSH	B		;SAVE B-C
	PUSH	D		;SAVE D-E
	PUSH	H		;SAVE H-L
	MVI	C,CONIN 	;SET UP FOR INPUT
	CALL	BDOS		;
	POP	H		;RECALL H-L
	POP	D		;RECALL D-E
	POP	B		;RECALL BC
	RET			;RETURN
;
;CRT OUTPUT
;
OUTPUT	PUSH	B		;SAVE B-C
	PUSH	D		;SAVE D-E
	PUSH	H		;SAVE H-L
	MOV	E,A		;PUT CHARACTER IN REGISTER E
	MVI	C,CONOUT	;SET UP FOR OUTPUT
	CALL	BDOS		;
	POP	H		;RECALL H
	POP	D		;RECALL D
	POP	B		;RECALL B
	RET			;RETURN
;
BOOT	JMP	BOOT		;HANG HERE UNTIL RESET
;
;MNEMONIC LOOK-UP TABLE
;
TABLE	DB	'NOP',2 	;INSTRUCTION MNEMONIC AND TYPE
	DB	'LXI B,',10
	DB	'STAX B',2
	DB	'INX B',2
	DB	'INR B',2
	DB	'DCR B',2
	DB	'MVI B,',7
	DB	'RLC',2
	DB	'*',1
	DB	'DAD B',2
	DB	'LDAX B',2
	DB	'DCX B',2
	DB	'INR C',2
	DB	'DCR C',2
	DB	'MVI C,',7
	DB	'RRC',2
	DB	'*',1
	DB	'LXI D,',10
	DB	'STAX D',2
	DB	'INX D',2
	DB	'INR D',2
	DB	'DCR D',2
	DB	'MVI D,',7
	DB	'RAL',2
	DB	'*',1
	DB	'DAD D',2
	DB	'LDAX D',2
	DB	'DCX D',2
	DB	'INR E',2
	DB	'DCR E',2
	DB	'MVI E,',7
	DB	'RAR',2
	DB	'*',1
	DB	'LXI H,',10
	DB	'SHLD ',10
	DB	'INX H',2
	DB	'INR H',2
	DB	'DCR H',2
	DB	'MVI H,',7
	DB	'DAA',2
	DB	'*',1
	DB	'DAD H',2
	db	'LHLD ',10
;	DB	'LHLD',10
	DB	'DCX H',2
	DB	'INR L',2
	DB	'DCR L',2
	DB	'MVI L,',7
	DB	'CMA',2
	DB	'*',1
	DB	'LXI SP,',10
	DB	'STA ',10
	DB	'INX SP',2
	DB	'INR M',2
	DB	'DCR M',2
	DB	'MVI M,',7
	DB	'STC',2
	DB	'*',1
	DB	'DAD SP',2
	DB	'LDA ',10
	DB	'DCX SP',2
	DB	'INR A',2
	DB	'DCR A',2
	DB	'MVI A,',7
	DB	'CMC',2
	DB	'MOV B,B',2
	DB	'MOV B,C',2
	DB	'MOV B,D',2
	DB	'MOV B,E',2
	DB	'MOV B,H',2
	DB	'MOV B,L',2
	DB	'MOV B,M',2
	DB	'MOV B,A',2
	DB	'MOV C,B',2
	DB	'MOV C,C',2
	DB	'MOV C,D',2
	DB	'MOV C,E',2
	DB	'MOV C,H',2
	DB	'MOV C,L',2
	DB	'MOV C,M',2
	DB	'MOV C,A',2
	DB	'MOV D,B',2
	DB	'MOV D,C',2
	DB	'MOV D,D',2
	DB	'MOV D,E',2
	DB	'MOV D,H',2
	DB	'MOV D,L',2
	DB	'MOV D,M',2
	DB	'MOV D,A',2
	DB	'MOV E,B',2
	DB	'MOV E,C',2
	DB	'MOV E,D',2
	DB	'MOV E,E',2
	DB	'MOV E,H',2
	DB	'MOV E,L',2
	DB	'MOV E,M',2
	DB	'MOV E,A',2
	DB	'MOV H,B',2
	DB	'MOV H,C',2
	DB	'MOV H,D',2
	DB	'MOV H,E',2
	DB	'MOV H,H',2
	DB	'MOV H,L',2
	DB	'MOV H,M',2
	DB	'MOV H,A',2
	DB	'MOV L,B',2
	DB	'MOV L,C',2
	DB	'MOV L,D',2
	DB	'MOV L,E',2
	DB	'MOV L,H',2
	DB	'MOV L,L',2
	DB	'MOV L,M',2
	DB	'MOV L,A',2
	DB	'MOV M,B',2
	DB	'MOV M,C',2
	DB	'MOV M,D',2
	DB	'MOV M,E',2
	DB	'MOV M,H',2
	DB	'MOV M,L',2
	DB	'HLT',4
	DB	'MOV M,A',2
	DB	'MOV A,B',2
	DB	'MOV A,C',2
	DB	'MOV A,D',2
	DB	'MOV A,E',2
	DB	'MOV A,H',2
	DB	'MOV A,L',2
	DB	'MOV A,M',2
	DB	'MOV A,A',2
	DB	'ADD B',2
	DB	'ADD C',2
	DB	'ADD D',2
	DB	'ADD E',2
	DB	'ADD H',2
	DB	'ADD L',2
	DB	'ADD M',2
	DB	'ADD A',2
	DB	'ADC B',2
	DB	'ADC C',2
	DB	'ADC D',2
	DB	'ADC E',2
	DB	'ADC H',2
	DB	'ADC L',2
	DB	'ADC M',2
	DB	'ADC A',2
	DB	'SUB B',2
	DB	'SUB C',2
	DB	'SUB D',2
	DB	'SUB E',2
	DB	'SUB H',2
	DB	'SUB L',2
	DB	'SUB M',2
	DB	'SUB A',2
	DB	'SBB B',2
	DB	'SBB C',2
	DB	'SBB D',2
	DB	'SBB E',2
	DB	'SBB H',2
	DB	'SBB L',2
	DB	'SBB M',2
	DB	'SBB A',2
	DB	'ANA B',2
	DB	'ANA C',2
	DB	'ANA D',2
	DB	'ANA E',2
	DB	'ANA H',2
	DB	'ANA L',2
	DB	'ANA M',2
	DB	'ANA A',2
	DB	'XRA B',2
	DB	'XRA C',2
	DB	'XRA D',2
	DB	'XRA E',2
	DB	'XRA H',2
	DB	'XRA L',2
	DB	'XRA M',2
	DB	'XRA A',2
	DB	'ORA B',2
	DB	'ORA C',2
	DB	'ORA D',2
	DB	'ORA E',2
	DB	'ORA H',2
	DB	'ORA L',2
	DB	'ORA M',2
	DB	'ORA A',2
	DB	'CMP B',2
	DB	'CMP C',2
	DB	'CMP D',2
	DB	'CMP E',2
	DB	'CMP H',2
	DB	'CMP L',2
	DB	'CMP M',2
	DB	'CMP A',2
	DB	'RNZ',6
	DB	'POP B',2
	DB	'JNZ ',8
	DB	'JMP ',8
	DB	'CNZ ',9
	DB	'PUSH B',2
	DB	'ADI ',7
	DB	'RST 0',3
	DB	'RZ',6
	DB	'RET',6
	DB	'JZ ',8
	DB	'*',1
	DB	'CZ ',9
	DB	'CALL ',9
	DB	'ACI ',7
	DB	'RST 1',3
	DB	'RNC',6
	DB	'POP D',2
	DB	'JNC ',8
	DB	'OUT ',7
	DB	'CNC ',9
	DB	'PUSH D',2
	DB	'SUI ',7
	DB	'RST 2',3
	DB	'RC',6
	DB	'*',1
	DB	'JC ',8
	DB	'IN ',7
	DB	'CC ',9
	DB	'*',1
	DB	'SBI ',7
	DB	'RST 3',3
	DB	'RPO',6
	DB	'POP H',2
	DB	'JPO ',8
	DB	'XTHL',2
	DB	'CPO ',9
	DB	'PUSH H',2
	DB	'ANI ',7
	DB	'RST 4',3
	DB	'RPE',6
	DB	'PCHL',5
	DB	'JPE ',8
	DB	'XCHG',2
	DB	'CPE ',9
	DB	'*',1
	DB	'XRI ',7
	DB	'RST 5',3
	DB	'RP',6
	DB	'POP PSW',2
	DB	'JP ',8
	DB	'DI',2
	DB	'CP ',9
	DB	'PUSH PSW',2
	DB	'ORI ',7
	DB	'RST 6',3
	DB	'RM',6
	DB	'SPHL',2
	DB	'JM ',8
	DB	'EI',1
	DB	'CM ',9
	DB	'*',1
	DB	'CPI ',7
	DB	'RST 7',3
;
;STORAGE SECTION
;
PCSTOR	DW	2000H		;PROGRAM COUNTER (DEFAULT)
PSWSTR	DS	2		;FLAGS AND A REGISTER
BSTOR	DS	2		;B AND C REGISTERS
DSTOR	DS	2		;D AND E REGISTERS
HSTOR	DS	2		;H AND L REGISTERS
SPSTOR	DS	2		;STACK POINTER
	DS	64H		;PROGRAM STACK
STACK	DS	1		;START OF STACK
BUFFER	EQU	$		;TYPE IN BUFFER
;
;END OF PROGRAM
;
	END
ACK POINTER