"Z80"

* Demo program for the HP 64753 Z80 Emulator. This program is used in
* the manual examples. It simulates a simple command interpreter. You
* can enter either an A or B as a command. The program writes a message
* to an output area indicating the command you used. If you enter an 
* invalid command, an appropriate message is written.
*
* (c) Copyright 1990, Hewlett-Packard Company. All Rights Reserved.

                    GLB       MESSAGES,INIT,CMD_INPUT,OUTPUT_BUFFER

* Define the stack pointer value, set up the command input buffer space,
* and the space for the output messages.

STACK_POINTER       EQU       3000H
                    
                    ORG       2400H
CMD_INPUT           DEFS      1

                    ORG       2500H
OUTPUT_BUFFER       DEFS      20     
                         

* Define the three messages used by the program. The END_MESSAGES
* label allows us to do math on the location counter for ease in 
* coding.

                    ORG       2600H
MESSAGES

MESSAGE_A           ASCII     "This is message A"
MESSAGE_B           ASCII     "This is message B"
INVALID_INPUT       ASCII     "Invalid command"

END_MESSAGES

* Start the program at 2000 hex. Load the stack pointer.

                    ORG       2000H

INIT                LD        SP,STACK_POINTER

* Set up an index to the command input buffer, and clear the buffer.

CLEAR               LD        HL,CMD_INPUT
                    LD        [HL],00H

* Keep reading the buffer until we get something other than zero.

READ_INPUT          LD        A,[HL]
                    CP        00H
                    JR        Z,READ_INPUT

* If we get here, we got some non-zero command. We need to clear the
* output buffer of old messages. Since we'll need the command value later
* to decide which message to write, push it on the stack. Then load DE
* with the output buffer's address, BC with the length count, and write
* zeros to the buffer. Then get the command value back by popping the
* accumulator from the stack.

CLEAR_OLD           PUSH      AF
                    LD        DE,OUTPUT_BUFFER
                    LD        BC,0020H
                    LD        A,00H
CLEAR_LOOP          LD        [DE],A
                    INC       DE
                    DEC       C
                    JR        NZ,CLEAR_LOOP
                    POP       AF

* Now we figure out which command we got by a series of compares.

PROCESS_COMM        CP        41H
                    JR        Z,COMMAND_A
                    CP        42H
                    JR        Z,COMMAND_B
                    JR        UNRECOGNIZED

* These routines set up for a Z80 block move instruction by loading the 
* message length into BC and the message source pointer into HL.

COMMAND_A           LD        BC,MESSAGE_B-MESSAGE_A
                    LD        HL,MESSAGE_A
                    JR        OUTPUT

COMMAND_B           LD        BC,INVALID_INPUT-MESSAGE_B
                    LD        HL,MESSAGE_B
                    JR        OUTPUT

UNRECOGNIZED        LD        BC,END_MESSAGES-INVALID_INPUT
                    LD        HL,INVALID_INPUT

* Now, we load the destination pointer into DE and use a Z80 block move
* to write the message to the output buffer. When finished, return to the
* clear routine to write the next command.

OUTPUT              LD        DE,OUTPUT_BUFFER
                    LDIR          
                    JP        CLEAR
                    
DONE                END       INIT                    