1        TITLE           'IMSAI SCS-1 REV. 2 06 OCT. 1976'
2;
3;       PAGE    62
4;
5; MODIFIED TO ASSEMBLE WITH INTEL 8080 CROSS ASSEMBLER
6; OCTOBER 2008, UDO MUNK
7;
8TTS     EQU     03H
9TTI     EQU     02H
10TTO     EQU     02H
11TTYDA   EQU     02H
12TTYTR   EQU     01H
13;
14        ORG     0H
15        JMP     INITA           ;DEAD START
16        JMP     EOR             ;RESTART MONITOR
17;
18        ORG     08H
19        JMP     BRKP            ;BREAKPOINT RESTART
20;
21        ORG     40H;
22;
23; THIS ROUTINE SETS UP THE SIO BOARD
24;
25INITA:  MVI     A,0AAH          ;GET DUMMY MODE WORD
26        OUT     TTS             ;OUTPUT IT
27        MVI     A,40H           ;GET RESET BIT
28        OUT     TTS             ;RESET SIO BOARD
29        MVI     A,0CEH          ;GET REAL MODE WORD
30        OUT     TTS             ;SET THE MODE FOR REAL
31        MVI     A,37H           ;GET THE COMMAND
32        OUT     TTS             ;OUTPUT IT
33;
34; THIS ROUTINE INITIALIZES THE FILE AREAD FOR SUBSEQUENT
35; PROCESSING
36;
37        LXI     H,FILE0
38        MVI     C,MAXFIL*FELEN
39        XRA     A
40INIT2:  MOV     M,A
41        INX     H
42        DCR     C
43        JNZ     INIT2
44;
45; CLEAR THE BREAKPOINT TABLE
46;
47        MVI     B,NBR*3
48        LXI     H,BRT
49INIT3:  MOV     M,A
50        INX     H
51        DCR     B
52        JNZ     INIT3
53;
54; THIS IS THE STARTING POINT OF THE SELF CONTAINED
55; SYSTEM ONCE THE SYSTEM HAS BEEN INITIALIZED.  COMMANDS
56; ARE READ FROM THE USER, EXECUTED, AND CONTROL RETURNS
57; BACK TO THIS POINT TO READ ANOTHER COMMAND.
58;
59EOR:    LXI     SP,AREA+18
60        CALL    CRLF            ;PRINT C/R, LINE FEED
61        CALL    READ            ;READ INPUT LINE
62        INX     H
63        MOV     A,M             ;FETCH FIRST CHARACTER
64        CPI     '9'+1           ;COMMAND OR LINE NUMBER?
65        JC      LINE            ;JUMP IF LINE FOR FILE
66        CALL    VALC
67        CALL    COMM
68        JMP     EOR
69;
70; THIS ROUTINE READS IN A LINE FROM THE TTY AND PLACES
71; IT IN AN INPUT BUFFER.
72; THE FOLLOWING ARE SPECIAL CHARACTERS
73;   CR          TERMINATES READ ROUTINE
74;   LF          NOT RECOGNIZED BY ROUTINE
75;   CTRL X      DELETES CURRENT LINE
76;   DEL         DELETES CHARACER
77; ALL DISPLAYABLE CHARACTERS BETWEEN BLANK & Z AND THE
78; ABOVE ARE RECOGNIZED BY THE READ ROUTINE, ALL OTHERS
79; ARE SKIPPED OVER.  THE ROUTINE WILL NOT ACCEPT MORE
80; CHARACTERS THAN THE INPUT BUFFER WILL HOLD.
81;
82READ:   LXI     H,IBUF          ;GET INPUT BUFFER ADDRESS
83        SHLD    ADDS            ;SAVE ADDRESS
84        MVI     E,2             ;INITIALIZE CHARACTER COUNT
85NEXT:   CALL    IN8             ;READ A LINE
86        MOV     A,B
87        CPI     24              ;CHECK FOR CTRL X
88        JNZ     CR
89        CALL    CRLF            ;OUTPUT A CRLF
90        JMP     READ
91CR:     CPI     ASCR            ;GET AN ASCII CR
92        JNZ     DEL
93        MOV     A,L
94        CPI     IBUF AND 00FFH  ;CHECK FOR FIRST CHAR
95        JZ      READ
96        MVI     M,ASCR          ;PLACE CR AT END OF LINE
97        INX     H
98        MVI     M,1             ;PLACE EOF INDICATOR IN LINE
99        INX     H
100        MVI     A,IBUF+83 AND 00FFH
101        CALL    CLER            ;CLEAR REMAINING BUFFER
102        LXI     H,IBUF-1
103        MOV     M,E             ;SAVE CHARACTER COUNT
104        RET
105DEL:    CPI     127             ;CHECK FOR DELETE CHARACTER
106        JNZ     CHAR
107        MVI     A,IBUF AND 00FFH
108        CMP     L               ;IS IT 1ST CHARACTER
109        JZ      NEXT
110        DCX     H               ;DECREMENT POINTER
111        DCR     E               ;DECREMENT COUNT
112BSPA:   MVI     B,5FH
113        CALL    OUT8
114        JMP     NEXT
115CHAR:   CPI     ' '             ;CHECK FOR LEGAL CHARACTER
116        JC      NEXT
117        CPI     'Z'+1
118        JNC     NEXT
119        MOV     B,A
120        CALL    OUT8            ;ECHO CHARACTER
121        MOV     M,B
122        MVI     A,IBUF+81 AND 00FFH
123        CMP     L               ;CHECK FOR END OF LINE
124        JZ      BSPA
125        INX     H
126        INR     E               ;INCREMENT CHARACTER COUNT
127        JMP     NEXT
128;
129; THIS ROUTINE IS USED TO BLANK OUT A PORTION OF MEMORY
130;
131CLER:   CMP     L
132        RZ
133        MVI     M,' '           ;PLACE BLANK IN MEMORY
134        INX     H
135        JMP     CLER
136;
137; SEE IF TTY INPUT READY AND CHECK FOR CTRL X.
138;
139INK:    IN      TTS             ;GET TTY STATUS
140        CMA                     ;INVERT STATUS
141        ANI     TTYDA           ;IS DATA AVAILABLE?
142        RNZ                     ;RETURN IF NOT
143        IN      TTI             ;GET THE CHAR
144        ANI     07FH            ;STRIP OFF PARITY
145        CPI     'X'-40H         ;IS IT A CTRL X?
146        RET
147;
148; THIS ROUTINE READS A BYTE OF DATA FROM THE USART
149;
150IN8:    IN      TTS             ;READ USART STATUS
151        ANI     TTYDA
152        JZ      IN8
153        IN      TTI             ;READ DATA
154        ANI     127             ;STRIP OFF PARITY
155        MOV     B,A
156        RET
157
158;
159; THIS ROUTINE OUTPUTS A BYTE OF DATA TO THE USART
160;
161OUT8:   IN      TTS             ;READ STATUS
162        ANI     TTYTR
163        JZ      OUT8
164OK:     MOV     A,B
165        OUT     TTO             ;TRANSMIT DATA
166        RET
167;
168; THIS ROUTINE WILL OUTPUT A CARRIAGE RETURN AND
169; LINE FEED FOLLOWED BY TWO DELETE CHARACTERS WHICH
170; PROVIDE TIME FOR PRINT HEAD TO RETURN.
171;
172CRLF:   MVI     B,13            ;CR
173        CALL    OUT8
174LF:     MVI     B,10            ;LF
175        CALL    OUT8
176        MVI     B,127
177        CALL    OUT8
178        CALL    OUT8
179        RET
180;
181; THIS ROUTINE JUMPS TO A LOCATION IN MEMORY GIVEN BY
182; THE INPUT COMMAND AND BEGINS EXECUTION OF PROGRAM
183; THERE.
184;
185EXEC:   CALL    VCHK            ;CHECK FOR PARAMETERS
186        CALL    CRLF
187        LHLD    BBUF            ;FETCH ADDRESS
188        PCHL                    ;JUMP TO PROGRAM
189;
190; THIS ROUTINE CHECKS THE INPUT COMMAND AGAINS ALL
191; LEGAL COMMANDS STORED IN A TABLE.  IF A LEGAL COMMAND
192; IS FOUND, A JUMP IS MADE TO THAT ROUTINE.  OTHERWISE
193; AN ERROR MESSAGE IS OUTPUT TO THE USER.
194;
195COMM:   LXI     D,CTAB          ;COMMAND TABLE ADDRESS
196        MVI     B,NCOM          ;NUMBER OF COMMANDS
197        MVI     A,4             ;LENGTH OF COMMAND
198        STA     NCHR            ;SAVE
199        CALL    COMS            ;SEARCH TABLE
200        JNZ     WHAT            ;JUMP IF ILLEGAL COMMAND
201        PCHL                    ;BE HERE NOW
202;
203; THIS ROUTINE CHECKS TO SEE IF A BASE CHARACTER STRING
204; IS EQUAL TO ANY OF THE STRINGS CONTAINED IN A TABLE
205; POINTED TO BY D,E.  tHE TABLE CONSISTS OF ANY NUMBER
206; OF CHARS, WITH 2 BYTES CONTAINING VALUES ASSOCIATED
207; WITH IT.  REG B CONTAINS THE # OF STRINGS TO COMPARE.
208; THIS ROUTINE CAN BE USED TO SEARCH THROUGH A COMMAND
209; OR SYMBOL TABLE.  ON RETURN, IF THE ZERO FLAG IS SET,
210; A MATCH WAS FOUND; IF NOT, NO MATCH WAS FOUND.  IF
211; A MATCH WAS FOUND, D,E POINT TO THE LAST BYTE
212; ASSOCIATED WITH THE CHARACTER STRING.  iF NOT, D,E
213; POINT TO THE NEXT LOCATION AFTER THE END FO THE TABLE.
214;
215COMS:   LHLD    ADDS            ;FETCH COMPARE ADDRESS
216        LDA     NCHR            ;GET LENGTH OF STRING
217        MOV     C,A
218        CALL    SEAR            ;COMPARE STRINGS
219        LDAX    D               ;FETCH VALUE
220        MOV     L,A
221        INX     D
222        LDAX    D               ;FETCH VALUE
223        MOV     H,A
224        RZ
225        INX     D               ;SET TO NEXT STRING
226        DCR     B               ;DECREMENT COUNT
227        JNZ     COMS
228        INR     B               ;CLEAR ZERO FLAG
229        RET
230;
231; THIS ROUTINE CHECKS TO SEE IF TWO CHARACTER STRINGS IN
232; MEMORY ARE EQUAL.  tHE STRINGS ARE POINTED TO BY D,E
233; AND H,L.  ON RETURN, THE ZERO FLAG SET INDICATES A
234; MATCH.  REG C INDICATES THE LENGTH OF THE STRINGS.  ON
235; RETURN, THE POINTERS POINT TO THE NEXT ADDRESS AFTER
236; THE CHARACTER STRINGS.
237;
238SEAR:   LDAX    D               ;FETCH CHARACTER
239        CMP     M               ;COMPARE CHARACTERS
240        JNZ     INCA
241        INX     H
242        INX     D
243        DCR     C               ;DECREMENT CHARACTER COUNT
244        JNZ     SEAR
245        RET
246INCA:   INX     D
247        DCR     C
248        JNZ     INCA
249        INR     C               ;CLEAR ZERO FLAG
250        RET
251;
252; THIS ROUTINE ZEROES OUT A BUFFER IN MEMORY WHICH IS
253; THEN USED BY OTHER SCANNING ROUTINES
254;
255ZBUF:   XRA     A               ;GET A ZERO
256        LXI     D,ABUF+12       ;BUFFER ADDRESS
257        MVI     B,12            ;BUFFER LENGTH
258ZBU1:   DCX     D               ;DECREMENT ADDRESS
259        STAX    D               ;ZERO BUFFER
260        DCR     B
261        JNZ     ZBU1
262        RET
263;
264; THIS ROUTINE CALLS ETRA TO OBTAIN THE INPUT PARAMETER
265; VALUES AND CALLS AN ERROR ROUTINE IF AN ERROR OCCURED
266; IN THAT ROUTINE
267;
268VALC:   CALL    ETRA            ;GET INPUT PARAMETERS
269        JC      WHAT            ;JUMP IF ERROR
270        RET
271;
272; THIS ROUTINE EXTRACTS THE VALUES ASSOCIATED WITH A
273; COMMAND FROM THE INPUT STREAM AND PLACES THEM IN THE
274; ASCII BUFFER (ABUF).  IT ALSO CALLS A ROUTINE TO
275; CONVERT THE ASCII HEXADECIMALS TO BINARY AND STORES
276; THEM IN THE BINARY BUFFER (BBUF).  ON RETURN, CARRY
277; SET INDICATES AN ERROR IN INPUT PARAMETERS.
278;
279ETRA:   LXI     H,0             ;GET A ZERO
280        SHLD    BBUF+2          ;ZERO VALUE
281        SHLD    FBUF            ;SET NO FILE NAME
282        CALL    ZBUF            ;ZERO BUFFER
283        LXI     H,IBUF-1
284VAL1:   INX     H
285        MOV     A,M             ;FETCH INPUT CHARACTER
286        CPI     ' '             ;LOOK FOR FIRST CHARACTER
287        CMC
288        RNC                     ;RETURN IF NO CARRY
289        JNZ     VAL1            ;JUMP IF NO BLACK
290        SHLD    PNTR            ;SAVE POINTER
291        CALL    SBLK            ;SCAN TO FIRST PARAMETER
292        CMC
293        RNC                     ;RETURN IF CR
294        CPI     '/'
295        JNZ     VAL5            ;NO FILE NAME
296        LXI     D,FBUF          ;NAME FOLLOWS PUT IN FBUF
297        MVI     C,NMLEN
298VAL2:   INX     H
299        MOV     A,M
300        CPI     '/'
301        JZ      VAL3
302        DCR     C
303        JM      WHAT
304        STAX    D               ;STORE FILE NAME
305        INX     D
306        JMP     VAL2
307VAL3:   MVI     A,' '           ;GET AN ASCII SPACE
308VAL4:   DCR     C
309        JM      DONE
310        STAX    D               ;FILL IN WITH SPACES
311        INX     D
312        JMP     VAL4
313DONE:   CALL    SBL2
314        CMC
315        RNC
316VAL5:   LXI     D,ABUF
317        CALL    ALPS            ;PLACE PARAMETER IN BUFFER
318        MOV     A,B             ;GET DIGIT COUNT
319        CPI     5               ;CHECK NUMBER OF DIGITS
320        CMC
321        RC                      ;RETURN IF TOO MANY DIGITS
322        LXI     B,ABUF
323        CALL    AHEX            ;CONVERT VALUE
324        RC                      ;ILLEGAL CHARACTER
325        SHLD    BBUF            ;SAVE IN BINARY BUFFER
326        LXI     H,ABUF
327        CALL    NORM            ;NORMALIZE ASCII VALUE
328        CALL    SBLK            ;SCAN TO NEXT PARAMETER
329        CMC
330        RNC                     ;RETURN IF cr
331        LXI     D,ABUF+4
332        CALL    ALPS            ;PLACE PARAMETERS IN BUFFER
333        MOV     A,B             ;GET DIGIT COUNT
334        CPI     5               ;CHECK NUMBER OF DIGITS
335        CMC
336        RC                      ;RETURN IF TOO MANY DIGITS
337        LXI     B,ABUF+4
338        CALL    AHEX            ;CONVERT VALUE
339        RC                      ;ILLEGAL VALUE
340        SHLD    BBUF+2          ;SAVE IN BINARY BUFFER
341        LXI     H,ABUF+4
342        CALL    NORM            ;NORMALIZE ASCII VALUE
343        ORA     A               ;CLEAR CARRY
344        RET
345;
346; THIS ROUTINE FETCHES DIGITS FROM THE BUFFER ADDRESSED
347; BY B,C AND CONVERTS THE ASCII DECIMAL DIGITS INTO
348; BINARY.  UP TO A 16-BIT VALUE CAN BE CONVERTED.  THE
349; SCAN STOPS WHEN A BINARY ZERO IS FOUND IN THE BUFFER.
350;
351ADEC:   LXI     H,0             ;GET A 16 BIT ZERO
352ADE1:   LDAX    B               ;FETCH ASCII DIGIT
353        ORA     A               ;SET ZERO FLAG
354        RZ                      ;RETURN IFF FINISHED
355        MOV     D,H             ;SAVE CURRENT VALUE
356        MOV     E,L             ;SAVE CURRENT VALUE
357        DAD     H               ;TIMES TWO
358        DAD     H               ;TIMES TWO
359        DAD     D               ;ADD IN ORIGINAL VALUE
360        DAD     H               ;TIMES TWO
361        SUI     48              ;ASCII BIAS
362        CPI     10              ;CHECK FOR LEGAL VALUE
363        CMC
364        RC                      ;RETURN IF ERROR
365        MOV     E,A
366        MVI     D,0
367        DAD     D               ;ADD IN NEXT DIGIT
368        INX     B               ;INCREMENT POINTER
369        JMP     ADE1
370;
371; THIS ROUTINE FETCHES DIGITS FROM THE BUFFER ADDRESSED
372; BY B,C AND CONVERTS THE ASCII HEXADECIMAL DIGITS INTO
373; BINARY.  UP TO A 16-BIT VALUE CAN BE CONVERTED.  THE
374; SCAN STOPS WHEN A BINARY ZERO IS FOUNDIN THE BUFFER.
375;
376AHEX:   LXI     H,0             ;GET A 16 BIT ZERO
377AHE1:   LDAX    B               ;FETCH ASCII DIGIT
378        ORA     A               ;SET ZERO FLAG
379        RZ                      ;RETURN IF DONE
380        DAD     H               ;LEFT SHIFT
381        DAD     H               ;LEFT SHIFT
382        DAD     H               ;LEFT SHIFT
383        DAD     H               ;LEFT SHIFT
384        CALL    AHS1            ;CONVERT TO BINARY
385        CPI     10H             ;CHECK FOR LEGAL VALUE
386        CMC
387        RC                      ;RETURN IF ERROR
388        ADD     L
389        MOV     L,A
390        INX     B               ;INCREMENT POINTER
391        JMP     AHE1
392;
393; THIS ROUTINE CONVERTS ASCII HEX DIGITS INTO BINARY
394;
395AHS1:   SUI     48              ;ASCII BIAS
396        CPI     10              ;DIGIT 0-10
397        RC
398        SUI     7               ;ALPHA BIAS
399        RET
400;
401; THIS ROUTINE CONVERTS A BINARY VALUE TO ASCII
402; HEXADECIMAL AND OUTPUTS THE CHARACTERS TO THE TTY.
403;
404HOUT:   CALL    BINH
405        LXI     H,HCON
406CHOT:   MOV     B,M
407        CALL    OUT8
408        INX     H
409        MOV     B,M
410        CALL    OUT8
411        RET
412;
413; THIS ROUTINE DOES THE SAME AS ABOVE BUT OUTPUTS A
414; BLANK AFTER THE LAST CHARACTER
415;
416HOTB:   CALL    HOUT            ;CONVERT AND OUTPUT
417        CALL    BLK1            ;OUTPUT A BLANK
418        RET
419;
420; THIS ROUTINE CONVERTS A BINARY VALUE TO ASCII
421; DECIMAL DIGITS AND OPTPUTS THE CHARACTERS TO THE TTY
422;
423
424DOUT:   CALL    BIND            ;CONVERT VALUE
425        CALL    HOUT+3          ;OUTPUT VALUE (2 DIGITS)
426        INX     H
427        MOV     B,M             ;GET LAST DIGIT
428        CALL    OUT8            ;OUTPUT
429        RET
430;
431; THIS ROUTINE OUTPUTS A BLANK
432;
433BLK1:   MVI     B,' '           ;GET A BLANK
434        CALL    OUT8
435        RET
436;
437; THIS ROUTINE IS USED BY OTHER ROUTINES TO INCREMENT
438; THE STARTING ADDRESS IN A COMMAND AND COMPARE IT WITH
439; THE FINAL ADDRESS IN THE COMMAND.  ON RETURN, THE
440; CARRY FLAG SET INDICATES THAT THE FINAL ADDRESS HAS
441; BEEN REACHED.
442;
443ACHK:   LHLD    BBUF            ;FETCH START ADDRESS
444        LDA     BBUF+3          ;STOP ADDRESS (HIGH)
445        CMP     H               ;COMPARE ADDRESSES
446        JNZ     ACH1
447        LDA     BBUF+2          ;STOP ADDRESS (LOW)
448        CMP     L               ;COMPARE ADDRESSES
449        JNZ     ACH1
450        STC                     ;SET CARRY IF EQUAL
451ACH1:   INX     H               ;INCREMENT START ADDRESSES
452        SHLD    BBUF            ;STORE START ADDRESS
453        RET
454;
455; THIS ROUTINE OUTPUTS CHARACTER OF A STRING
456; UNTIL A CARRIAGE RETURN IS FOUND
457;
458SCRN:   MOV     B,M             ;FETCH CHARACTER
459        MVI     A,13            ;CARRIAGE RETURN
460        CMP     B               ;CHARACTER = CR?
461        RZ
462        CALL    OUT8
463        INX     H
464        JMP     SCRN
465;
466; THIS ROUTINE CONVERTS THE BINARY VALUE IN REG A INTO
467; ASCII HEXADECIMAL DIGITS AND STORES THEM IN MEMORY
468;
469BINH:   LXI     H,HCON          ;CONVERSION
470        MOV     B,A             ;SAVE VALUE
471        RAR
472        RAR
473        RAR
474        RAR
475        CALL    BIN1
476        MOV     M,A
477        INX     H
478        MOV     A,B
479        CALL    BIN1            ;CONVERT TO ASCII
480        MOV     M,A
481        RET
482;
483; THIS ROUTINE CONVERTS A VALUE TO HEXADECIMAL
484;
485BIN1:   ANI     0FH             ;LOW 4 BITS
486        ADI     48              ;CONVERT TO ASCII
487        CPI     58              ;DIGIT 0-9
488        RC
489        ADI     7               ;MODIFY FOR A-F
490        RET
491;
492; THIS ROUTINE CONVERTS THE BINARY VALUE IN REG A INTO
493; ASCII DECIMAL DIGITS AND STORES THEM IN MEMORY
494;
495BIND:   LXI     H,HCON          ;CONVERSION ADDRESS
496        MVI     B,100
497        CALL    BID1            ;CONVERT HUNDREDS DIGIT
498        MVI     B,10
499        CALL    BID1            ;CONVERT TENS DIGIT
500        ADI     '0'             ;GET UNITS DIGIT
501        MOV     M,A             ;STORE IN MEMORY
502        RET
503;
504; THIS ROUTINE CONVERTS A VALUE TO DECIMAL
505;
506BID1:   MVI     M,'0'-1         ;INITIALIZE DIGIT COUNT
507        INR     M
508        SUB     B               ;CHECK DIGIT
509        JNC     BID1+2
510        ADD     B               ;RESTORE VALUE
511        INX     H
512        RET
513;
514; LEGAL COMMAND TABLE
515;
516CTAB:   DB      'DUMP'
517        DW      DUMP
518        DB      'EXEC'
519        DW      EXEC
520        DB      'ENTR'
521        DW      ENTR
522        DB      'FILE'
523        DW      FILE
524        DB      'LIST'
525        DW      LIST
526        DB      'DELT'
527        DW      DELL
528        DB      'ASSM'
529        DW      ASSM
530        DB      'PAGE'
531        DW      PAGEMOV
532        DB      'CUST'
533        DW      2000H
534        DB      'BREK'
535        DW      BREAK
536        DB      'PROC'
537        DW      PROC
538;
539; THIS ROUTINE CHECKS IF ANY PARAMETERS WERE ENTERED
540; WITH THE COMMAND, IF NOT AN ERROR MESSAGE IS ISSUED
541;
542VCHK:   LDA     ABUF            ;FETCH PARAMETER BYTE
543        ORA     A               ;SET FLAGS
544        JZ      WHAT            ;NO PARAMETER
545        RET
546;
547; THIS ROUTINE DUMPS OUT THE FONTENTS OF MEMORY FROM
548; THE START TO FINAL ADDRESSES GIVEN IN THE COMMAND.
549;
550DUMP:   CALL    VCHK            ;CHECK FOR PARAMETERS
551DUMS:   CALL    CRLF            ;START NEW LINE
552DUM1:   LHLD    BBUF            ;FETCH MEMORY ADDRESS
553        MOV     A,M
554        CALL    HOTB            ;OUTPUT VALUE
555        CALL    ACHK            ;CHECK ADDRESS
556        RC                      ;RETURN IF FINISHED
557        MOV     A,L             ;IS NEXT ADDRESS
558        ANI     0FH             ; DIVISIBLE BY 16?
559        JNZ     DUM1
560        JMP     DUMS
561;
562; THIS ROUTINE WILL MOVE 256 BYTES FROM 1ST ADDRESS
563; GIVEN IN COMMAND TO 2ND ADDRESS IN COMMAND.
564;
565PAGEMOV:CALL    VCHK            ;CHECK FOR PARAMETER
566        LDA     ABUF+4          ;FETCH 2ND PARAMETER
567        ORA     A               ;DOES 2ND PARAMETER EXIST?
568        JZ      WHAT
569        LHLD    BBUF            ;FETCH MOVE TO ADDRESS
570        XCHG
571        LHLD    BBUF+2          ;FETCH MOVE TO ADDRESS
572        MVI     B,0             ;SET COUNTER
573PAG1:   LDAX    D
574        MOV     M,A
575        INX     H
576        INX     D
577        DCR     B               ;DECREMENT COUNTER
578        JNZ     PAG1
579        RET
580;
581; THIS COMMAND INITIALIZES THE BEGINNING OF FILE ADDRESS
582; AND END OF FILE ADDRESS AS WELL AS THE FILE AREA
583; WHEN THE FILE COMMAND IS USED
584;
585FILE:   CALL    CRLF
586; CHECK FOR FILE PARAMETERS
587        LDA     FBUF
588        ORA     A
589        JZ      FOUT            ;NO ? GO LIST
590        CALL    FSEA            ;LOOK UP FILE
591        XCHG                    ;PNTR IN DE
592        JNZ     TEST
593; NO ENTRY
594        LDA     ABUF            ;CHECK FOR PARAM
595        ORA     A
596        JZ      WHA1            ;NO?? - ERROR
597; CHECK FOR ROOM IN DIRECTORY
598        LDA     FEF
599        ORA     A
600        JNZ     ROOM
601        LXI     H,EMES1
602        JMP     MESS
603; ENTRY FOUND ARE THESE PARAMETERS
604TEST:   LDA     ABUF
605        ORA     A
606        JZ      SWAPS
607        LHLD    BBUF
608        MOV     A,H
609        ORA     L
610        JZ      SWAPS
611        LXI     H,EMES2         ;NO-NO CAN?T DO
612        JMP     MESS            ;IT - DELETE FIRST
613; MOVE FILE NAME TO BLOCK POINTED TO BY FREAD
614ROOM:   LHLD    FREAD
615        XCHG
616        LXI     H,FBUF          ;FILE NAME POINTER IN H,L
617        PUSH    D
618        MVI     C,NMLEN         ;NAME LENGTH COUNT
619MOV23:  MOV     A,M
620        STAX    D
621        INX     D
622        DCR     C               ;TEST COUNT
623        INX     H
624        JNZ     MOV23
625        POP     D               ;RESTORE ENTRY POINTER
626; MAKE FILE POINTED TO BY D,E CURRENT
627SWAPS:  LXI     H,FILE0
628        MVI     C,FELEN         ;ENTRY LENGTH
629SWAP:   LDAX    D
630        MOV     B,M
631        MOV     M,A             ;EXCHANGE
632        MOV     A,B
633        STAX    D
634        INX     D
635        INX     H               ;BUMP POINTER
636        DCR     C               ;TEST COUNT
637        JNZ     SWAP
638
639; CHECK FOR 2ND PARAMETER
640            LDA ABUF
641        ORA     A
642        JZ      FOOT            ;NO SECOND PARAMETER
643; PROCESS 2ND PARAMETER
644        LHLD    BBUF            ;GET ADDRESS
645        SHLD    BOFP            ;SET BEGIN
646        SHLD    EOFP            ;SET END
647        MOV     A,L             ;IS ADDRESS ZERO
648        ORA     H
649        JZ      FIL35           ;YES
650FIL30:  MVI     M,1             ;NON-ZERO ? SET EOF
651FIL35:  XRA     A               ;AND MAX LINE #
652        STA     MAXL
653        JMP     FOOT            ;OUTPUT PARAMETERS
654FOUT:   LDA     IBUF+4
655        CPI     'S'             ;IS COMMAND FILES?
656        MVI     C,MAXFIL
657        JZ      FOUL
658FOOT:   MVI     C,1
659; OUTPUT THE # OF ENTRIES IN C
660FOUL:   LXI     H,FILE0
661        MOV     A,C
662FINE:   STA     FOCNT           ;SAVE COUNT
663        PUSH    H
664        LXI     D,NMLEN
665        DAD     D
666        MOV     A,M
667        ORA     A
668        JNZ     FOOD
669        INX     H
670        ADD     M
671        INX     H
672        JNZ     FOOD            ;NON ZERO, OK TO OUTPUT
673        INX     SP
674        INX     SP
675        INX     H
676        INX     H
677        JMP     FEET
678; HAVE AN ENTRY TO OUTPUT
679FOOD:   POP     H               ;PTR
680        MVI     C,NMLEN
681FAST:   MOV     B,M             ;LOAD CHARACTER TO B
682        CALL    OUT8
683        DCR     C
684        INX     H
685        JNZ     FAST            ;DO THE REST
686; NOW OUTPUT BEGIN-END PTRS
687        CALL    FOOL            ;OUTPUT BEGIN
688        CALL    FOOL            ;OUTPUT END
689        CALL    CRLF            ;AND C/R
690; TEST COUNT, H,L POINTS PAST EOFP
691FEET:   LXI     D,FELEN-NMLEN-4
692        DAD     D               ;MOVE TO NEXT ENTRY
693        LDA     FOCNT
694        DCR     A               ;TEST COUNT
695        JNZ     FINE            ;MORE TO DO
696        RET                     ;DONE!
697; OUTPUT NUMBER POINTED TO BY H,L
698; ON RET, H,L POINT 2 WORDS LATER
699FOOL:   CALL    BLK1            ;SPACE
700        INX     H
701        MOV     A,M
702        DCX     H
703        PUSH    H
704        CALL    HOUT            ;OUTPUT
705        POP     H
706        MOV     A,M
707        INX     H
708        INX     H
709        PUSH    H
710        CALL    HOTB            ;OUTPUT
711        POP     H               ;RESTORE H,L
712        RET
713;
714; SEARCH THE FILE DIRECTORY FOR THE FILE
715; WHOSE NAME IS IN FBUF.
716; RETURN IF FOUND, ZERO IF OFF, H,L POINT TO
717; ENTRY WHILE SEARCHING, ON ENTRY FOUND WITH ADDR
718; ZERO, SET FEF TO >0 AND FREAD TO THE ADDR OF ENTRY
719;
720FSEA:   XRA     A
721        STA     FEF             ;CLAIM NO FREE ENTRIES
722        MVI     B,MAXFIL        ;COUNT OF ENTRIES
723        LXI     D,FILE0         ;TABLE ADDRESS
724FSE10:  LXI     H,FBUF
725        MVI     C,NMLEN
726        CALL    SEAR            ;TEST STRINGS
727        PUSH    PSW             ;SAVE FLAG
728        PUSH    D
729        LDAX    D               ;GET BOFP
730        ORA     A               ;EMPTY ENTRY?
731        JNZ     FSE20
732        INX     D               ;STORE OTHER WORD
733        LDAX    D
734        ORA     A
735        JNZ     FSE20           ;NOPE-GO TEST FOR MATCH
736        XCHG
737        LXI     D,-NMLEN-1
738        DAD     D               ;MOVE TO BEGINNING
739        SHLD    FREAD           ;SAVE ADDR
740        MOV     A,D
741        STA     FEF             ;SET FREE ENTRY FOUND
742        POP     H               ;RESTORE INTERIM PTR
743        POP     PSW             ;UNJUNK STACK
744; MOVE TO NEXT ENTRY
745FSE15:  LXI     D,FELEN-NMLEN
746        DAD     D
747        XCHG                    ;NEXT ENTRY IN DE
748        DCR     B               ;TEST COUNT
749        RZ                      ;DONE--NOPE
750        JMP     FSE10           ;TRY NEXT
751; ENTRY WASN?T FREE, TEST FOR MATCH
752FSE20:  POP     H
753        POP     PSW
754        JNZ     FSE15           ;IF ZERO CLEAR, NO MATCH
755; ENTRY FOUND
756        LXI     D,-NMLEN        ;BACKUP
757        DAD     D               ;H,L POINTS TO ENTRY
758        MOV     A,D
759        ORA     A               ;CLEAR ZERO
760        RET                     ;THAT?S ALL
761;
762; OUTPUT ERROR MESSAGE FOR ILLEGAL COMMAND
763;
764WHAT:   CALL    CRLF            ;OUT CRLF
765WHA1:   LXI     H,EMES          ;MESSAGE ADDRESS
766MESS:   CALL    SCRN
767        JMP     EOR
768;
769EMES:   DB      'WHAT'
770        DB      13
771EMES1:  DB      'FULL',13
772EMES2:  DB      'NO NO',13
773;
774; CALL ROUTINE TO ENTER DATA INTO MEMORY
775; AND CHECK FOR ERROR ON RETURN
776;
777; THIS ROUTINE IS USED TO ENTER DATA VALUES INTO MEMORY.
778; EACH VALUE IS ONE BYTE AND IS WRITTEN IN HEXADECIMAL
779; VALUES GREATER THAN 255 WILL CAUSE CARRY TO BE SET
780; AND RETURN TO BE MADE TO CALLING PROGRAM
781;
782ENTR:   CALL    VCHK            ;CHECK FOR PARAMETERS
783        CALL    ENTS
784        JC      WHAT
785        CALL    CRLF
786        RET
787;
788EEND    EQU     '/'             ;TERMINATION CHARACTER
789ENTS:   CALL    CRLF
790        CALL    READ            ;READ INPUT DATA
791        LXI     H,IBUF          ;SET LINE POINTER
792        SHLD    PNTR            ;SAVE POINTER
793ENT1:   CALL    ZBUF            ;CLEAR BUFFER
794        CALL    SBLK            ;SCAN TO FIRST VALUE
795        JC      ENTS            ;JUMP IF CR FOUND
796        CPI     EEND
797        RZ                      ;RETURN CARRY IS ZERO
798        CALL    ALPS            ;PLACE VALUE IN BUFFER
799        MOV     A,B             ;GET DIGIT COUNT
800        CPI     3               ;CHECK NMBR OF DIGITS
801        CMC
802        RC                      ;RETURN IF MORE THAN 2 DIGITS
803        LXI     B,ABUF          ;CONVERSION ADDRESS
804        CALL    AHEX            ;CONVERT VALUE
805        RC                      ;ERROR IN HEX CHARACTER
806        MOV     A,L
807        LHLD    BBUF            ;FETCH MEMORY ADDRESS
808        MOV     M,A             ;PUT IN MEMORY
809        CALL    ACH1            ;INCREMENT MEMORY LOCATION
810        JMP     ENT1
811;
812; THIS ROUTINE IS USED TO ENTER LINES INTO THE FILE
813; AREA.  THE LINE NUMBER IS FIRST CHECKED TO SEE IF IT IS
814; A VALID NUMBER (0000-9999).  NEXT IT IS CHECKED TO SEE
815; IF IT IS GREATER THAN THE MAXIMUM CURRENT LINE NUMBER.
816; IF IT IS, THE NEXT LINE IS INSERTED AT THE END OF THE
817; CURRENT FILE AND THE MAXIMUM LINE NUMBER IS UPDATED AS
818; WELL AS THE END OF FILE POSITION.  LINE NUMBERS THAT
819; ALREADY EXIST ARE INSERTED INTO THE FILE AREA AT THE
820; APPROPRIATE PLACE AND ANY EXTRA CHARACTERS IN THE OLD
821; LINE ARE DELETED.
822;
823LINE:   LDA     FILE0           ;IS A FILE DEFINED?
824        ORA     A
825        JZ      WHAT            ;ABORT IF NOT
826        MVI     C,4             ;NO OF DIGITS TO CHECK
827        LXI     H,IBUF-1                ;INITIALIZE ADDRESS
828LICK:   INX     H
829        MOV     A,M             ;FETCH LINE DIGIT
830        CPI     '0'             ;CHECK FOR VALID NUMBER
831        JC      WHAT
832        CPI     '9'+1
833        JNC     WHAT
834        DCR     C
835        JNZ     LICK
836        SHLD    ADDS            ;FIND ADDRESS
837        LXI     D,MAXL+3                ;GET ADDRESS
838        CALL    COM0
839        JNC     INSR
840; GET HERE IF NEW LINE IS GREATER THAN MAXIMUM LINE #
841        INX     H
842        CALL    LODM            ;GET NEW LINE NUMBER
843        LXI     H,MAXL+3
844        CALL    STOM            ;MAKE IT MAXIMUM LINE NUMBER
845        LXI     D,IBUF-1
846        LHLD    EOFP            ;END OF FILE POSITION
847        MVI     C,1
848        CALL    LMOV            ;PLACE LINE IN FILE
849SEOF:   MVI     M,1             ;END OF FILE INDICATOR
850        SHLD    EOFP            ;END OF FILE ADDRESS
851        JMP     EOR
852; GET HERE IF NEW LINE MUST BE INSERTED INTO ALREADY
853; EISTING FILE AREA
854INSR:   CALL    FIN1            ;FIND LINE IN FILE
855        MVI     C,2
856        JZ      EQUL
857        DCR     C               ;NEW LN NOT EQUAL TO SOME OLD LN
858EQUL:   MOV     B,M
859        DCX     H
860        MVI     M,2             ;MOVE LINE INDICATOR
861        SHLD    INSP            ;INSERT LINE POSITION
862        LDA     IBUF-1          ;NEW LINE COUNT
863        DCR     C
864        JZ      LESS            ;NEW LN NOT = OLD LN
865        SUB     B               ;COUNT DIFFERENCE
866        JZ      ZERO            ;LINE LENGTHS EQUAL
867        JC      MORE
868; GET HERE IF # OF CHARS IN OLD LINE > # OF CHARS IN
869; NEW LINE OR NEW LINE # WAS NOT EQUAL TO SOLD OLD
870; LINE #
871LESS:   LHLD    EOFP            ;END OF FILE ADDRESS
872        MOV     D,H
873        MOV     E,L
874        CALL    ADR             ;MOVE TO ADDRESS
875        SHLD    EOFP            ;NEW END OF FILE ADDRESS
876        MVI     C,2
877        CALL    RMOV            ;OPEN UP FILE AREA
878        JMP     ZERO
879; GET HERE IF # OF CHARS IN OLD LINE < # OF CHARS IN
880; NEW LINE
881MORE:   CMA
882        INR     A               ;COUNT DIFFERENCE
883        MOV     D,H
884        MOV     E,L
885        CALL    ADR
886        XCHG
887        CALL    LMOV            ;DELETE EXCESS CHAR IN FILE
888        MVI     M,1             ;E-O-F INDICATOR
889        SHLD    EOFP            ;E-O-F ADDRESS
890; GET HERE TO INSERT LINE INTO FILE AREA
891ZERO:   LHLD    INSP            ;INSERT ADDRESS
892        MVI     M,ASCR
893        INX     H
894        LXI     D,IBUF-1                ;NEW LINE ADDRESS
895        MVI     C,1             ;CHECK VALUE
896        CALL    LMOV            ;PLACE LINE IN FILE
897        JMP     EOR
898;
899; THIS ROUTINE IS USED TO FIND A LN IN THE FILE AREA
900; WHICH IS GREATER THAN OR EQUAL TO THE CURRENT LINE #
901;
902FIND:   LXI     H,ABUF+3                ;BUFFER ADDRESS
903        SHLD    ADDS            ;SAVE ADDRESS
904FIN1:   LHLD    BOFP            ;BEGIN FILE ADDRESS
905        MOV     A,H             ;RETURN TO MONITOR IF
906        ORA     L               ;  FILE IS EMPTY...
907        JZ      EOR
908FI1:    CALL    EO1             ;CHECK FOR END OF FILE
909        XCHG
910        LHLD    ADDS            ;FETCH FIND ADDRESS
911        XCHG
912        MVI     A,4
913        CALL    ADR             ;BUMP LINE ADDRESS
914        CALL    COM0            ;COMPARE LINE NUMBERS
915        RC
916        RZ
917FI2:    MOV     A,M
918        CALL    ADR             ;NEXT LINE ADDRESS
919        JMP     FI1
920;
921; WHEN SEARCHING THROUGH THE FILE AREA, THIS ROUTINE
922; CHECKS TO SEE IF THE CURRENT ADDRESS IS THE END OF
923; FILE
924;
925EOF:    INX     H
926EO1:    MVI     A,1             ;E-O-F INDICATOR
927        CMP     M
928        RNZ
929        JMP     EOR
930;
931; THIS ROUTINE IS USED TO ADD A VALUE TO AN ADDRESS
932; CONTAINED IN REGISTER H,L
933;
934ADR:    ADD     L
935        MOV     L,A
936        RNC
937        INR     H
938        RET
939;
940; THIS ROUTINE WILL MOVE CHARACTER STRINGS FROM ONE
941; LOCATION OF MEMORY TO ANOTHER
942; CHARACTERS ARE MOVED FROM LOCATION ADDRESSED BY D,E
943; TO LOCATION ADDRESSED BY H,L.  ADDITIONAL CHARACTERS
944; ARE MOVED BY BUMPING POINTERS UNTIL THE CHARACTER IN
945; REG C IS FETCHED.
946;
947LMOV:   LDAX    D               ;FETCH CHARACTER
948        INX     D               ;INCREMENT FETCH ADDRESS
949        CMP     C               ;TERMINATION CHARACTER
950        RZ
951        MOV     M,A             ;STORE CHARACTER
952        INX     H               ;INCREMENT STORE ADDRESS
953        JMP     LMOV
954;
955; THIS ROUTINE IS SIMILAR TO ABOVE EXCEPT THAT THE
956; CHARACTER ADDRESS IS DECREMENTED AFTER EACH FETCH
957; AND STORE
958;
959RMOV:   LDAX    D               ;FETCH CHARACTER
960        DCX     D               ;DECREMENT FETCH CHARACTER
961        CMP     C               ;TERMINATION CHARACTER
962        RZ
963        MOV     M,A             ;STORE CHARACTER
964        DCX     H               ;DECREMENT STORE ADDRESS
965        JMP     RMOV
966;
967; THIS ROUTINE IS USED TO LOAD FOUR CHARACTERS FROM
968; MEMORY INTO REGISTERS
969;
970
971LODM:   MOV     B,M             ;FETCH CHARACTER
972        INX     H
973        MOV     C,M             ;FETCH CHARACTER
974        INX     H
975        MOV     D,M             ;FETCH CHARACTER
976        INX     H
977        MOV     E,M             ;FETCH CHARACTER
978        RET
979;
980; THIS ROUTINE STORES FOUR CHARACTERS FROM THE REGISTERS
981; INTO MEMORY
982;
983STOM:   MOV     M,E             ;STORE CHARACTER
984        DCX     H
985        MOV     M,D             ;STORE CHARACTER
986        DCX     H
987        MOV     M,C             ;STORE CHARACTER
988        DCX     H
989        MOV     M,B             ;STORE CHARACTER
990        RET
991;
992; THIS ROUTINE IS USED TO COMPARE TWO CHARACTER STRINGS
993; OF LENGTH 4, ON RETURN ZERO FLAG SET MEANS BOTH
994; STRINGS ARE EQUAL.  CARRY FLAG =0 MEANS STRING ADDRESS
995; BY D,E WAS GREATER THAN OR EQUAL TO CHARACTER STRING
996; ADDRESSED BY H,L
997;
998COM0:   MVI     B,1             ;EQUAL COUNTER
999        MVI     C,4             ;STRING LENGTH
1000        ORA     A               ;CLEAR CARRY
1001CO1:    LDAX    D               ;FETCH CHARACTER
1002        SBB     M               ;COMPARE CHARACTERS
1003        JZ      CO2
1004        INR     B               ;INCREMENT EQUAL COUNTER
1005CO2:    DCX     D
1006        DCX     H
1007        DCR     C
1008        JNZ     CO1
1009        DCR     B
1010        RET
1011;
1012; THIS ROUTINE IS SIMILAR TO THE ABOVE ROUTINE EXCEPT ON
1013; RETURN CARRY FLAG = 0 MEANS THAT CHARACTER STRING
1014; ADDRESSED BY D,E IS ONLY > STRING ADDRESSED BY H,L.
1015;
1016COM1:   MVI     C,4             ;STRING LENGTH
1017        LDAX    D               ;TCH CHARACTER
1018        SUI     1
1019        JMP     CO1+1
1020;
1021; THIS ROUTINE WILL TAKE ASCII CHARACTERS AND ADD ANY
1022; NECESSARY ASCII ZEROES SO THE RESULT IS A 4 CHARACTER
1023; ASCII VALUE
1024;
1025NORM:   CALL    LODM            ;LOAD CHARACTERS
1026        XRA     A               ;FETCH A ZERO
1027        CMP     B
1028        RZ
1029NOR1:   CMP     E
1030        CNZ     STOM            ;STORE VALUES
1031        RNZ
1032        MOV     E,D             ;NORMALIZE VALUE
1033        MOV     D,C
1034        MOV     C,B
1035        MVI     B,'0'
1036        JMP     NOR1
1037;
1038; THIS ROUTINE IS USED TO LIST THE CONTENTS OF THE FILE
1039; AREA STARTING AT THE LINE NUMBER GIVEN IN THE COMMAND
1040;
1041LIST:   CALL    CRLF
1042        CALL    FIND            ;FIND STARTING LINE NUMBER
1043LIST0:  INX     H               ;OUTPUT LINE...
1044        CALL    SCRN
1045        CALL    CRLF
1046        CALL    EOF             ;CHECK FOR END OF FILE
1047        CALL    INK             ;CHECK FOR ?X
1048        JNZ     LIST0           ;LOOP IF NO ?X
1049        RET
1050;
1051; THIS ROUTINE IS USED TO DELETE LINES FROM THE
1052; FILE AREA.  THE REMAINING FILE AREA IS THEN MOVED IN
1053; MEMORY SO THAT THERE IS NO EXCESS SPACE.
1054;
1055DELL:   CALL    VCHK            ;CHECK FOR PARAMETER
1056        CALL    FIND            ;FIND LINE IN FILE AREA
1057        SHLD    DELP            ;SAVE DELETE POSITION
1058        LXI     H,ABUF+7
1059        MOV     A,M             ;CHECK FOR 2ND PARAMETER
1060        ORA     A               ;SET FLAGS
1061        JNZ     DEL1
1062        LXI     H,ABUF+3                ;USE FIRST PARAMETER
1063DEL1:   SHLD    ADDS            ;SAVE FIND ADDRESS
1064        XCHG
1065        LXI     H,MAXL+3
1066        CALL    COM0            ;COMPARE LINE NUMBERS
1067        LHLD    DELP            ;LOAD DELETE POSITION
1068        JC      NOVR
1069; GET HERE IF DELETION INVOLVES END OF FILE
1070        SHLD    EOFP            ;CHANGE E-O-F POSITION
1071        MVI     M,1             ;SET E-O-F INDICATOR
1072        XCHG
1073        LHLD    BOFP
1074        XCHG
1075        MVI     B,13            ;SET SCAN SWITCH
1076        DCX     H               ;CHECK FOR BOFP
1077DEL2:   MOV     A,L
1078        SUB     E
1079        MOV     A,H
1080        SBB     D
1081        MVI     A,ASCR          ;LOOK FOR CR
1082        JC      DEL4            ;DECREMENTED PAST BOF
1083        DCR     B
1084        DCX     H
1085        CMP     M               ;FIND NEW MAX LN
1086        JNZ     DEL2
1087        DCX     H
1088        MOV     A,L
1089        SUB     E
1090        MOV     A,H
1091        SBB     D
1092        JC      DEL5
1093        CMP     M               ;END OF PREVIOUS LINE
1094        INX     H
1095        INX     H
1096        JZ      DEL3
1097        INX     H
1098DEL3:   CALL    LODM            ;LOAD NEW MAX LN
1099        LXI     H,MAXL+3                ;SET ADDRESS
1100        CALL    STOM            ;STORE NEW MAX LN
1101        RET
1102DEL4:   CMP     B               ;CHECK SWITCH
1103DEL5:   XCHG
1104        JNZ     DEL3-1
1105        STA     MAXL            ;MAKE MAX LN A SMALL NUMBER
1106        RET
1107; GET HERE IF DELETION IS IN THE MIDDLE OF FILE AREA
1108NOVR:   CALL    FI1             ;FIND END OF DELETE AREA
1109        CZ      FI2             ;NEXT LINE IF THIS LN EQUAL
1110NOV1:   XCHG
1111        LHLD    DELP            ;CHAR MOVE TO POSITION
1112        MVI     C,1             ;MOVE TERMINATOR
1113        CALL    LMOV            ;COMPACT FILE AREA
1114        SHLD    EOFP            ;SET EOF POSITION
1115        MVI     M,1             ;SET EOF INDICATOR
1116        RET
1117;
1118; STARTING HERE IS THE SELF ASSEMBLER PROGRAM
1119; THIS PROGRAM ASSEMBLES PROGRAMS WHICH ARE
1120; IN THE FILE AREA
1121;
1122ASSM:   CALL    VCHK            ;CHECK FOR PARAMETERS
1123        LDA     ABUF+4          ;GET 2ND PARAMETER
1124        ORA     A               ;CHECK FOR PRARMETERS
1125        JNZ     ASM4
1126        LHLD    BBUF            ;FETCH 1ST PARAMETER
1127        SHLD    BBUF+2          ;STORE INTO 2ND PARAMETER
1128ASM4:   LDA     IBUF+4          ;FETCH INPUT CHARACTER
1129        SUI     'E'             ;RESET a IF ERRORS ONLY
1130        STA     AERR            ;SAVE ERROR FLAG
1131        XRA     A               ;GET A ZERO
1132        STA     NOLA            ;INITIALIZE LABEL COUNT
1133ASM3:   STA     PASI            ;SET PASS INDICATOR
1134        CALL    CRLF            ;INDICATE START OF PASS
1135        LHLD    BBUF            ;FETCH ORIGIN
1136        SHLD    ASPC            ;INITIALIZE PC
1137        LHLD    BOFP            ;GET START OF FILE
1138        SHLD    APNT
1139ASM1:   LHLD    APNT            ;FETCH LINE POINTER
1140        LXI     SP,AREA+18
1141        MOV     A,M             ;FETCH CHARACTER
1142        CPI     1               ;END OF FILE?
1143        JZ      EASS            ;JUMP IF END OF FILE
1144        XCHG
1145        INX     D               ;INCREMENT ADDRESS
1146        LXI     H,OBUF          ;BLANK START ADDRESS
1147        MVI     A,IBUF-5 AND 0FFH       ;BLANK END ADDRESS
1148        CALL    CLER            ;BLANK OUT BUFFER
1149        MVI     C,ASCR          ;STOP CHARACTER
1150        CALL    LMOV            ;MOVE LINE INTO BUFFER
1151        MOV     M,C             ;PLACE CR IN BUFFER
1152        XCHG
1153        SHLD    APNT            ;SAVE ADDRESS
1154        LDA     PASI            ;FETCH PASS INDICATOR
1155        ORA     A               ;SET FLAGW
1156        JNZ     ASM2            ;JUMP IF PASS 2
1157        CALL    PAS1
1158        JMP     ASM1
1159;
1160ASM2:   CALL    PAS2
1161        LXI     H,OBUF          ;OUTPUT BUFFER ADDRESS
1162        CALL    AOUT            ;OUTPUT LINE
1163        JMP     ASM1
1164;
1165; THIS ROUTINE IS USED TO OUTPUT THE LISTING FOR
1166; AN ASSEMBLY.  IT CHECKS THE ERROR SWITCH TO SEE IF
1167; ALL LINES ARE TO BE PRINTED OR JUST THOSE WITH
1168; ERRORS.
1169;
1170AOUT:   LDA     AERR            ;FETCH ERROR SWITCH
1171        ORA     A               ;SET FLAGS
1172        JNZ     AOU1            ;OUTPUT ALL LINES
1173AOU2:   LDA     OBUF            ;FETCH ERROR INDICATOR
1174        CPI     ' '             ;CHECK FOR AN ERROR
1175        RZ                      ;RETURN IF NO ERROR
1176AOU1:   LXI     H,OBUF          ;OUTPUT BUFFER ADDRESS
1177        CALL    SCRN            ;OUTPUT LINE...
1178        CALL    CRLF
1179        RET
1180;
1181; PASS 1 OF ASSEMBLER, USED TO FORM SYMBOL TABLE
1182;
1183PAS1:   CALL    ZBUF            ;CLEAR BUFFER
1184        STA     PASI            ;SET FOR PASS1
1185        LXI     H,IBUF          ;INITIALIZE LINE POINTER
1186        SHLD    PNTR
1187        MOV     A,M             ;FETCH CHARACTER
1188        CPI     ' '             ;CHECK FOR A BLANK
1189        JZ      OPC             ;JUMP IF NO LABLE
1190        CPI     '*'             ;CHECK FOR COMMENT
1191        RZ                      ;RETURN IF COMMENT
1192;
1193; PROCESS LABEL
1194;
1195        CALL    SLAB            ;GET AND CHECK LABEL
1196        JC      OP5             ;ERROR IN LABEL
1197        JZ      ERRD            ;DUPLICATE LABEL
1198        CALL    LCHK            ;CHECK CHARACTER AFTER LABEL
1199        JNZ     OP5             ;ERROR IF NO BLANK
1200        MVI     C,LLAB          ;LENGTH OF LABELS
1201        LXI     H,ABUF          ;SET BUFFER ADDRESS
1202MLAB:   MOV     A,M             ;FETCH NEXT CHARACTER
1203        STAX    D               ;STORE IN SYMBOL TABLE
1204        INX     D
1205        INX     H
1206        DCR     C
1207        JNZ     MLAB
1208        XCHG
1209        SHLD    TABA            ;SAVE TABLE ADDRESS FOR EQU
1210        LDA     ASPC+1          ;FETCH PC (HIGH)
1211        MOV     M,A
1212        INX     H
1213        LDA     ASPC            ;FETCH PC (LOW)
1214        MOV     M,A             ;STORE IN TABLE
1215        LXI     H,NOLA
1216        INR     M               ;INCREMENT NUMBER OF LABELS
1217;
1218; PROCESS OPCODE
1219;
1220OPC:    CALL    ZBUF            ;ZERO WORKING BUFFER
1221        CALL    SBLK            ;SCAN TO OPCODE
1222        JC      OERR            ;FOUND CARRIAGE RETURN
1223        CALL    ALPS            ;PLACE OPCODE IN BUFFER
1224        CPI     ' '             ;CHECK FOR BLANK AFTER OPCODE
1225        JC      OPCD            ;CR AFTER OPCODE
1226        JNZ     OERR            ;ERROR IF NO BLANK
1227        JMP     OPCD            ;CHECK OPCODE
1228;
1229; THIS ROUTINE CHECKS THE CHARACTER AFTER A LABEL
1230; FOR A BLANK OR COLON
1231;
1232LCHK:   LHLD    PNTR
1233        MOV     A,M             ;GET CHARACTER AFTER LABEL
1234        CPI     ' '             ;CHECK FOR BLANK
1235        RZ                      ;RETURN IF A BLANK
1236        CPI     ':'             ;CHECK FOR COLON
1237        RNZ
1238        INX     H
1239        SHLD    PNTR            ;SAVE POINTER
1240        RET
1241;
1242; PROCESS ANY PSEUDO OPS THAT NEED TO BE IN PASS 1
1243;
1244PSU1:   CALL    SBLK            ;SCAN TO OPERAND
1245        LDAX    D               ;FETCH VALUE
1246        ORA     A               ;SET FLAGS
1247        JZ      ORG1            ;ORG OPCODE
1248        JM      DAT1            ;DATA STATEMENT
1249        JPO     EQU1            ;EQU OPCODE
1250        CPI     5
1251        JC      RES1            ;RES OPCODE
1252        JNZ     EASS            ;JUMP IF END
1253; DO DW PSEUDO/OP
1254ACO1:   MVI     C,2             ;2 BYTE INSTRUCTION
1255        XRA     A               ;GET A ZERO
1256        JMP     OCN1            ;ADD VALUE TO PROGRAM COUNTER
1257; DO ORG PSUEDO OP
1258ORG1:   CALL    ASCN            ;GET OPERAND
1259        LDA     OBUF            ;FETCH ERROR INDICATOR
1260        CPI     ' '             ;CHECK FOR AN ERROR
1261        RNZ
1262        SHLD    ASPC            ;STORE NEW ORIGIN
1263        LDA     IBUF            ;GET FIRST CHARACTER
1264        CPI     ' '             ;CHECK FOR AN ERROR
1265        RZ                      ;NO LABEL
1266        JMP     EQUS            ;CHANGE LABEL VALUE
1267; DO EQU PSUEDO-OP
1268EQU1:   CALL    ASCN            ;GET OPERAND
1269        LDA     IBUF            ;FETCH 1ST CHARACTER
1270        CPI     ' '             ;CHECK FOR LABEL
1271        JZ      ERRM            ;MISSING LABEL
1272EQUS:   XCHG
1273        LHLD    TABA            ;SYMBOL TABLE ADDRESS
1274        MOV     M,D             ;STORE LABEL VALUE
1275        INX     H
1276        MOV     M,E
1277        RET
1278; DO DS PSEUDO-OP
1279RES1:   CALL    ASCN            ;GET OPERAND
1280        MOV     B,H
1281        MOV     C,L
1282        JMP     RES21           ;ADD VALUE TO PROGRAM COUNTER
1283;
1284; DO DB PSEUDO-OP
1285;
1286DAT1:   JMP     DAT2A
1287;
1288; PERFORM PASS 2 OF THE ASSEMBLER
1289;
1290PAS2:   LXI     H,OBUF+2                ;SET OUTPUT BUFFER ADDRESS
1291        LDA     ASPC+1          ;FETCH PC (HIGH)
1292        CALL    BINH+3          ;CONVERT FOR OUTPUT
1293        INX     H
1294        LDA     ASPC            ;FETCH PC(LOW)
1295        CALL    BINH+3          ;CONVERT FOR OUTPUT
1296        INX     H
1297        SHLD    OIND            ;SAVE OUTPUT ADDRESS
1298        CALL    ZBUF            ;CLEAR BUFFER
1299        LXI     H,IBUF          ;INITIALIZE LINE POINTER
1300PABL:   SHLD    PNTR            ;SAVE POINTER
1301        MOV     A,M             ;FETCH FIRST CHARACTER
1302        CPI     ' '             ;CHECK FOR LABEL
1303        JZ      OPC             ;GET OPCODE
1304        CPI     '*'             ;CHECK FOR COMMENT
1305        RZ                      ;RETURN IF COMMENT
1306        CALL    SLAB            ;SCAN OFF LABEL
1307        JC      ERRL            ;ERROR IN LABEL
1308        CALL    LCHK            ;CHECK FOR A BLANK OR COLON
1309        JNZ     ERRL            ;ERROR IF NOT A BLANK
1310        JMP     OPC
1311;
1312; PROCESS PSEUDO OPS FOR PASS2
1313;
1314PSU2:   LDAX    D
1315        ORA     A               ;SET FLAGS
1316        JZ      ORG2            ;ORG OPCODE
1317        JM      DAT2            ;DATA OPCODE
1318        JPO     EQU2            ;EQUATE PSEUDO-OP
1319        CPI     5
1320        JC      RES2            ;RES OPCODE
1321        JNZ     EASS            ;END OPCODE
1322; DO DW OPCODE
1323ACO2:   CALL    TYS6            ;GET VALUE
1324        JMP     ACO1
1325; DO DS PSEUDO-OP
1326RES2:   CALL    ASBL            ;GET OPERAND
1327        MOV     B,H
1328        MOV     C,L
1329        LHLD    BBUF+2          ;FETCH STORAGE COUNTER
1330        DAD     B               ;ADD VALUE
1331        SHLD    BBUF+2
1332RES21:  XRA     A               ;GET A ZERO
1333        JMP     OCN2
1334; DO DB PSEUDO-OP
1335DAT2:   CALL    TY55            ;GET OPERAND
1336DAT2A:  XRA     A               ;MAKE ZERO
1337        MVI     C,1             ;BYTE COUNT
1338        JMP     OCN1
1339;
1340; HANDLE EQUATES ON 2ND PASS
1341;
1342EQU2:   CALL    ASBL            ;GET OPERAND INTO HL AND
1343                                ;  FALL INTO NEXT ROUTINE
1344;
1345; STORE CONTENTS OF HL AS HEX ASCII AT OBUF+2
1346;   ON RETURN, DE HOLDS VALUE WHICH WAS IN HL.
1347;
1348BINAD:  XCHG                    ;PUT VALUE INTO DE
1349        LXI     H,OBUF+2                ;POINTER TO ADDR IN OBUF
1350        MOV     A,D             ;STORE HI BYTE
1351        CALL    BINH+3
1352        INX     H
1353        MOV     A,E             ;STORE LOW BYTE...
1354        CALL    BINH+3
1355        INX     H
1356        RET
1357; DO ORG PSEUDO-OP
1358ORG2:   CALL    ASBL            ;GET NEW ORIGIN
1359        LDA     OBUF            ;GET ERROR INDICATOR
1360        CPI     ' '             ;CHECK FOR AN ERROR
1361        RNZ                     ;DON?T MODIFY PC IF ERROR
1362        CALL    BINAD           ;STORE NEW ADDR IN OBUF
1363        LHLD    ASPC            ;FETCH PC
1364        XCHG
1365        SHLD    ASPC            ;STORE NEW PC
1366        MOV     A,L
1367        SUB     E               ;FORM DIFFERENCE OF ORIGINS
1368        MOV     E,A
1369        MOV     A,H
1370        SBB     D
1371        MOV     D,A
1372        LHLD    BBUF+2          ;FETCH STORAGE POINTER
1373        DAD     D               ;MODIFY
1374        SHLD    BBUF+2          ;SAVE
1375        RET
1376;
1377; PROCESS 1 BYTE INSTRUCTIONS WITHOUT OPERANDS
1378;
1379TYP1:   CALL    ASTO            ;STORE VALUE IN MEMORY
1380        RET
1381;
1382; PROCESS STAX AND LDAX INSTRUCTIONS
1383;
1384TYP2:   CALL    ASBL            ;FETCH OPERAND
1385        CNZ     ERRR            ;ILLEGAL REGISTER
1386        MOV     A,L             ;GET LOW ORDER OPERAND
1387        ORA     A               ;SET FLAGS
1388        JZ      TY31            ;OPERAND = 0
1389        CPI     2               ;OPERAND = 2
1390        CNZ     ERRR            ;ILLEGAL REGISTER
1391        JMP     TY31
1392;
1393; PROCESS PUSH, POP, INX, DCX, DAD INSTRUCTIONS
1394;
1395TYP3:   CALL    ASBL            ;FETCH OPERAND
1396        CNZ     ERRR            ;ILLEGAL REGISTER
1397        MOV     A,L             ;GET LOW ORDER OPERAND
1398        RRC                     ;CHECK LOW ORDER BIT
1399        CC      ERRR            ;ILLEGAL REGISTER
1400        RAL                     ;RESTORE
1401        CPI     8
1402        CNC     ERRR            ;ILLEGAL REGISTER
1403TY31:   RLC                     ;MULTIPLY BY 8
1404        RAL
1405        RAL
1406TY32:   MOV     B,A
1407        LDAX    D               ;FETCH OPCODE BASE
1408        ADD     B               ;FORM OPCODE
1409        CPI     118             ;CHECK FOR MOV M,M
1410        CZ      ERRR            ;ILLEGAL REGISTER
1411        JMP     TYP1
1412;
1413; PROCESS ACCUMULATOR, INR,DCR,MOV,RST INSTRUCTIONS
1414;
1415TYP4:   CALL    ASBL            ;FETCH OPERAND
1416        CNZ     ERRR            ;ILLEGAL REGISTER
1417        MOV     A,L             ;GET LOW ORDER OPERAND
1418        CPI     8
1419        CNC     ERRR            ;ILLEGAL REGISTER
1420        LDAX    D               ;FETCH OPCODE BASE
1421        CPI     64              ;CHECK FOR MOV INSTRUCTION
1422        JZ      TY41
1423        CPI     199
1424        MOV     A,L
1425        JZ      TY31            ;RST INSTRUCTION
1426        JM      TY32            ;ACCUMULATOR INSTRUCTION
1427        JMP     TY31            ;INR, DCR
1428; PROCESS MOV INSTRUCTION
1429TY41:   DAD     H               ;MULTIPLY OPERAND BY 8
1430        DAD     H
1431        DAD     H
1432        ADD     L               ;FORM OPCODE
1433        STAX    D               ;SAVE OPCODE
1434        CALL    MPNT
1435        CALL    ASCN
1436        CNZ     ERRR            ;INCREMENT POINTER
1437        MOV     A,L
1438        CPI     8
1439        CNC     ERRR            ;ILLEGAL REGISTER
1440        JMP     TY32
1441;
1442; PROCESS IMMEDIATE INSTRUCTIONS
1443; IMMEDIATE BYTE CAN BETWEEN -256 AND +255
1444; MVI INSTRUCTION IS A SPECIAL CASE AND CONTAINS
1445; 2 ARGUMENTS IN OPERAND
1446;
1447TYP5:   CPI     6               ;CHECK FOR MVI
1448        CZ      TY56
1449        CALL    ASTO            ;STORE OBJECT BYTE
1450TY55:   CALL    ASBL            ;GET IMMEDIATE ARGUMENT
1451        INR     A
1452        CPI     2               ;CHECK OPERAND FOR RANGE
1453        CNC     ERRV
1454        MOV     A,L
1455        JMP     TYP1
1456;
1457; FETCH 1ST ARG FOR MVI AND LXI INSTRUCTIONS
1458;
1459TY56:   CALL    ASBL            ;FETCH ARG
1460        CNZ     ERRR            ;ILLEGAL REGISTER
1461        MOV     A,L             ;GET LOW ORDER ARGUMENT
1462        CPI     8
1463        CNC     ERRR            ;ILLEGAL REGISTER
1464        DAD     H
1465        DAD     H
1466        DAD     H
1467        LDAX    D               ;FETCH OPCODE BASE
1468        ADD     L               ;FOR OPCODE
1469        MOV     E,A             ;SAVE OBJECT BYTE
1470MPNT:   LHLD    PNTR            ;FETCH POINTER
1471        MOV     A,M             ;FETCH CHARACTER
1472        CPI     ','             ;CHECK FOR COMMA
1473        INX     H               ;INCREMENT POINTER
1474        SHLD    PNTR
1475        JNZ     ERRS            ;SYNTAX ERROR IF NO COMMA
1476        MOV     A,E
1477        RET
1478;
1479; PROCESS 3 BYTE INSTRUCTIONS
1480; LXI INSTRUCTION IS A SPECIAL CASE
1481;
1482TYP6:   CPI     1               ;CHECK FOR LXI INSTRUCTION
1483        JNZ     TY6             ;JUMP IF NOT LXI
1484        CALL    TY56            ;GET REGISTER
1485        ANI     08H             ;CHECK FOR ILLEGAL REGISTER
1486        CNZ     ERRR            ;REGISTER ERROR
1487        MOV     A,E             ;GET OPCODE
1488        ANI     0F7H            ;CLEAR BIT IN ERROR
1489TY6:    CALL    ASTO            ;STORE OBJECT BYTE
1490TYS6:   CALL    ASBL            ;FETCH OPERAND
1491        MOV     A,L
1492        MOV     D,H
1493        CALL    ASTO            ;STORE 2ND BYTE
1494        MOV     A,D
1495        JMP     TYP1
1496        RET
1497;
1498; THIS ROUTINE IS USED TO STORE OBJECT CODE PRODUCED
1499; BY THE ASSEMBLER DURING PASS 2 INTO MEMORY
1500;
1501ASTO:   LHLD    BBUF+2          ;FETCH STORAGE ADDRESS
1502        MOV     M,A             ;STORE OBJECT BYTE
1503        INX     H               ;INCREMENT LOCATION
1504        SHLD    BBUF+2
1505        LHLD    OIND            ;FETCH OUTPUT ADDRESS
1506        INX     H
1507        CALL    BINH+3          ;CONVERT OBJECT BYTE
1508        SHLD    OIND
1509        RET
1510;
1511; GET HERE WHEN END PSEUDO-OP IS FOUND OR WHEN
1512; END-OF-FILE OCCURS IN SOURCE FILE.  CONTROL IS SET
1513; FOR EITHER PASS 2 OR ASSEMBLY TERMINATOR IF FINISHED
1514;
1515EASS:   LDA     PASI            ;FETCH PASS INDICATOR
1516        ORA     A               ;SET FLAGS
1517        JNZ     EOR             ;JUMP IF FINISHED
1518        MVI     A,1             ;PASS INDICATOR FOR 2ND PASS
1519        JMP     ASM3            ;DO 2ND PASS
1520;
1521; THIS ROUTINE SCANS THROUGH A CHARACTER STRING UNTIL
1522; THE FIRST NON-BLANK CHARACTER IS FOUND
1523;
1524; ON RETURN, CARRY SET INDICATES A CARRIAGE RETURN
1525; AS  FIRST NON-BLANK CHARACTER.
1526;
1527SBLK:   LHLD    PNTR            ;FETCH ADDRESS
1528SBL1:   MOV     A,M             ;FETCH CHARACTER
1529        CPI     ' '             ;CHECK FOR BLANK
1530        RNZ                     ;RETURN IF NON-BLANK
1531SBL2:   INX     H               ;INCREMENT
1532        SHLD    PNTR            ;SAVE POINTER
1533        JMP     SBL1
1534;
1535; THIS ROUTINE IS USED TO CHECK THE CONDITION
1536; CODE NMEUMONICS FOR CONDITIONAL JUMPS, CALLS,
1537; AND RETURNS.
1538;
1539COND:   LXI     H,ABUF+1
1540        SHLD    ADDS
1541        MVI     B,2             ;2 CHARACTERS
1542        CALL    COPC
1543        RET
1544;
1545; THE FOLLOWING IS THE OPCODE TABLE
1546;
1547OTAB:   DB      'ORG'
1548        DB      0
1549        DB      0
1550        DB      'EQU'
1551        DB      0
1552        DB      1
1553        DB      'DB'
1554        DB      0
1555        DB      0
1556        DB      -1 AND 0FFH
1557        DB      'DS'
1558        DB      0
1559        DB      0
1560        DB      3
1561        DB      'DW'
1562        DB      0
1563        DB      0
1564        DB      5
1565        DB      'END'
1566        DB      0
1567        DB      6
1568        DB      0
1569        DB      'HLT'
1570        DB      118
1571        DB      'RLC'
1572        DB      7
1573        DB      'RRC'
1574        DB      15
1575        DB      'RAL'
1576        DB      23
1577        DB      'RAR'
1578        DB      31
1579        DB      'RET'
1580        DB      201
1581        DB      'CMA'
1582        DB      47
1583        DB      'STC'
1584        DB      55
1585        DB      'DAA'
1586        DB      39
1587        DB      'CMC'
1588        DB      63
1589        DB      'EI'
1590        DB      0
1591        DB      251
1592        DB      'DI'
1593        DB      0
1594        DB      243
1595        DB      'NOP'
1596        DB      0
1597        DB      0
1598        DB      'XCHG'
1599        DB      235
1600        DB      'XTHL'
1601        DB      227
1602        DB      'SPHL'
1603        DB      249
1604        DB      'PCHL'
1605        DB      233
1606        DB      0
1607        DB      'STAX'
1608        DB      2
1609        DB      'LDAX'
1610        DB      10
1611        DB      0
1612        DB      'PUSH'
1613        DB      197
1614        DB      'POP'
1615        DB      0
1616        DB      193
1617        DB      'INX'
1618        DB      0
1619        DB      3
1620        DB      'DCX'
1621        DB      0
1622        DB      11
1623        DB      'DAD'
1624        DB      0
1625        DB      9
1626        DB      0
1627        DB      'INR'
1628        DB      4
1629        DB      'DCR'
1630        DB      5
1631        DB      'MOV'
1632        DB      64
1633        DB      'ADD'
1634        DB      128
1635        DB      'ADC'
1636        DB      136
1637        DB      'SUB'
1638        DB      144
1639        DB      'SBB'
1640        DB      152
1641        DB      'ANA'
1642        DB      160
1643        DB      'XRA'
1644        DB      168
1645        DB      'ORA'
1646        DB      176
1647        DB      'CMP'
1648        DB      184
1649        DB      'RST'
1650        DB      199
1651        DB      0
1652        DB      'ADI'
1653        DB      198
1654        DB      'ACI'
1655        DB      206
1656        DB      'SUI'
1657        DB      214
1658        DB      'SBI'
1659        DB      222
1660        DB      'ANI'
1661        DB      230
1662        DB      'XRI'
1663        DB      238
1664        DB      'ORI'
1665        DB      246
1666        DB      'CPI'
1667        DB      254
1668        DB      'IN'
1669        DB      0
1670        DB      219
1671        DB      'OUT'
1672        DB      211
1673        DB      'MVI'
1674        DB      6
1675        DB      0
1676        DB      'JMP'
1677        DB      0
1678        DB      195
1679        DB      'CALL'
1680        DB      205
1681        DB      'LXI'
1682        DB      0
1683        DB      1
1684        DB      'LDA'
1685        DB      0
1686        DB      58
1687        DB      'STA'
1688        DB      0
1689        DB      50
1690        DB      'SHLD'
1691        DB      34
1692        DB      'LHLD'
1693        DB      42
1694        DB      0
1695;       CONDITION       CODE    TABLE
1696        DB      'NZ'
1697        DB      0
1698        DB      'Z'
1699        DB      0
1700        DB      8
1701        DB      'NC'
1702        DB      16
1703        DB      'C'
1704        DB      0
1705        DB      24
1706        DB      'PO'
1707        DB      32
1708        DB      'PE'
1709        DB      40
1710        DB      'P'
1711        DB      0
1712        DB      48
1713        DB      'M'
1714        DB      0
1715        DB      56
1716        DB      0
1717;
1718; THIS ROUTINE IS USED TO CHECK A GIVEN OPCODE
1719; AGAINST THE LEGAL OPCODES IN THE OPCODE TABLE
1720;
1721COPC:   LHLD    ADDS
1722        LDAX    D               ;FETCH CHARACTER
1723        ORA     A               ;SET FLAGS
1724        JZ      COP1            ;JUMP IF TERMINATION CHARACTER
1725        MOV     C,B
1726        CALL    SEAR
1727        LDAX    D
1728        RZ                      ;RETURN IF A MATCH
1729        INX     D               ; NEXT STRING
1730        JMP     COPC            ;CONTINUE SEARCH
1731COP1:   INR     A               ;CLEAR ZERO FLAG
1732        INX     D               ;INCREMENT ADDRESS
1733        RET
1734;
1735; THIS ROUTINE CHECKS THE LEGAL OPCODES IN BOTH PASS 1
1736; AND PASS 2.  IN PASS 1 THE PROGRAM COUNTER IS INCRE-
1737; MENTED BY THE CORRECT NUMBER OF BYTES.  AN ADDRESS IS
1738; ALSO SET SO THAT AN INDEXED JUMP CAN BE MADE TO
1739; PROCESS THE OPCODE FOR PASS 2.
1740;
1741OPCD:   LXI     H,ABUF          ;GET ADDRESS
1742        SHLD    ADDS
1743        LXI     D,OTAB          ;OPCODE TABLE ADDRESS
1744        MVI     B,4             ;CHARACTER COUNT
1745        CALL    COPC            ;CHECK OPCODE
1746        JZ      PSEU            ;JUMP IF PSEUDO-OP
1747        DCR     B               ;3-CHARACTER OPCODES
1748        CALL    COPC
1749        JZ      OP1
1750        INR     B               ;4 CHARACTER OPCODES
1751        CALL    COPC
1752OP1:    LXI     H,TYP1          ;TYPE 1 INSTRUCTIONS
1753OP2:    MVI     C,1             ;1 BYTE INSTRUCTIONS
1754        JZ      OCNT
1755;
1756OPC2:   CALL    COPC            ;CHECK FOR STAX, LDAX
1757        LXI     H,TYP2
1758        JZ      OP2
1759        CALL    COPC            ;CHECK FOR PUSH,POP,INX
1760                                ; DCX AND DAD
1761        LXI     H,TYP3
1762        JZ      OP2
1763        DCR     B               ;3 CHAR OPCODES
1764        CALL    COPC            ;ACCUMULATOR INSTRUCTIONS,
1765                                ; INR, DCR, MOV, RST
1766        LXI     H,TYP4
1767        JZ      OP2
1768;
1769OPC3:   CALL    COPC            ;IMMEDIATE INSTRUCTIONS
1770        LXI     H,TYP5
1771        MVI     C,2             ;2 BYTE INSTRUCTIONS
1772        JZ      OCNT
1773        INR     B               ;4 CHARACTER OPCODES
1774        CALL    COPC            ;JMP, CALL, LIX, LDA, STA,
1775                                ; LHLD, SHLD OPCODES
1776        JZ      OP4
1777        CALL    COND            ;CONDITIONAL INSTRUCTIONS
1778        JNZ     OERR            ;ILLEGAL OPCODE
1779        ADI     192             ;ADD BASE VALUE TO RETURN
1780        MOV     D,A
1781        MVI     B,3             ;3 CHARACTER OPCODES
1782        LDA     ABUF            ;FETCH FIRST CHARACTER
1783        MOV     C,A             ;SAVE CHARACTER
1784        CPI     'R'             ;CONDITIONAL RETURN
1785        MOV     A,D
1786        JZ      OP1
1787        MOV     A,C
1788        INR     D               ;FORM CONDITIONAL JUMP
1789        INR     D
1790        CPI     'J'             ;CONDITIONAL JUMP
1791        JZ      OPAD
1792        CPI     'C'             ;CONDITIONAL CALL
1793        JNZ     OERR            ;ILLEGAL OPCODE
1794        INR     D               ;FORM CONDITIONAL CALL
1795        INR     D
1796OPAD:   MOV     A,D             ;GET OPCODE
1797OP4:    LXI     H,TYP6
1798OP5:    MVI     C,3             ;3 BYTE INSTRUCTION
1799OCNT:   STA     TEMP            ;SAVE OPCODE
1800;
1801; CHECK FOR OPCODE ONLY CONTAINING THE CORRECT NUMBER OF
1802; CHARACTERS.  THUS ADDQ, SAY, WOULD GIVE AN ERROR
1803;
1804        MVI     A,ABUF AND 0FFH ;LOAD BUFFER ADDRESS
1805        ADD     B               ;ADD LENGTH OF BUFFER
1806        MOV     E,A
1807        MVI     A,ABUF/256
1808        ACI     0               ;GET HIGH ORDER ADDRESS
1809        MOV     D,A
1810        LDAX    D               ;FETCH CHARACTER AFTER OPCODE
1811        ORA     A               ;IT SHOULD BE ZERO
1812        JNZ     OERR            ;OPCODE ERROR
1813        LDA     PASI            ;FETCH PASS INDICATOR
1814OCN1:   MVI     B,0
1815        XCHG
1816OCN2:   LHLD    ASPC            ;FETCH PROGRAM COUNTER
1817        DAD     B               ;ADD IN BYTE COUNT
1818        SHLD    ASPC            ;STORE PC
1819        ORA     A               ;WHICH PASS?
1820        RZ                      ;RETURN IF PASS 1
1821        LDA     TEMP            ;FETCH OPCODE
1822        XCHG
1823        PCHL
1824;
1825OERR:   LXI     H,ERRO          ;GET ERROR ADDRESS
1826        MVI     C,3             ;LEAVE 3 BYTES FOR PATCH
1827        JMP     OCN1-3
1828;
1829PSEU:   LXI     H,ABUF+4                ;SET BUFFER ADDRESS
1830        MOV     A,M             ;FETCH CHARACTER AFTER OPCODE
1831        ORA     A               ;SHOULD BE A ZERO
1832        JNZ     OERR
1833        LDA     PASI            ;FETCH PASS INDICATOR
1834        ORA     A
1835        JZ      PSU1
1836        JMP     PSU2
1837;
1838; THIS ROUTINE IS USED TO PROCESS LABELS.
1839; IT CHECKS TO SEE IF A LABEL IS IN THE SYMBOL TABLE
1840; OR NOT.  ON RETURN, Z=1 INDICATES A MATCH WAS FOUND
1841; AND H,L CONTAIN THE VALUE ASSOCIATED WITH THE LABEL.
1842; THE REGISTER NAMES A, B, C, D, E, H, L, P, AND S ARE
1843; PRE-DEFINED AND NEED NOT BE ENTERED BY THE USER.
1844; ON RETURN, C=1 INDICATES A LABEL ERROR.
1845;
1846SLAB:   CPI     'A'             ;CHECK FOR LEGAL CHARACTER
1847        RC
1848        CPI     'Z'+1           ;CHECK FOR ILLEGAL CHARACTER
1849        CMC
1850        RC                      ;RETURN IF ILLEGAL CHARACTER
1851        CALL    ALPS            ;PLACE SYMBOL IN BUFFER
1852        LXI     H,ABUF          ;SET BUFFER ADDRESS
1853        SHLD    ADDS            ;SAVE ADDRESS
1854        DCR     B               ;CHECK IF ONE CHARACTER
1855        JNZ     SLA1
1856; CHECK IF PREFEFINED REGISTER NAME
1857        INR     B               ;SET B=1
1858        LXI     D,RTAB          ;REGISTER NAME TABLE
1859        CALL    COPC            ;CHECK NAME OF REGISTER
1860        JNZ     SLA1            ;NOT A PREFEFINED REGIGTER
1861        MOV     L,A             ;SET VALUE (HIGH)
1862        MVI     H,0
1863        JMP     SLA2
1864SLA1:   LDA     NOLA            ;FETCH SYMBOL COUNT
1865        MOV     B,A
1866        LXI     D,SYMT          ;SET SYMBOL TABLE ADDRESS
1867        ORA     A               ;ARE THERE ANY LABELS?
1868        JZ      SLA3            ;JUMP IF NO LABELS
1869        MVI     A,LLAB          ;FETCH LENGTH OF LABEL
1870        STA     NCHR
1871        CALL    COMS            ;CHECK TABLE
1872        MOV     C,H             ;SWAP H AND L
1873        MOV     H,L
1874        MOV     L,C
1875SLA2:   STC                     ;SET CARRY
1876        CMC                     ;CLEAR CARRY
1877        RET                     ;RETURN
1878SLA3:   INR     A               ;CLEAR ZERO FLAG
1879        ORA     A               ;CLEAR CARRY
1880        RET
1881;
1882; PREDEFINE REGISTER VALUES IN THIS TABLE
1883;
1884RTAB:   DB      'A'
1885        DB      7
1886        DB      'B'
1887        DB      0
1888        DB      'C'
1889        DB      1
1890        DB      'D'
1891        DB      2
1892        DB      'E'
1893        DB      3
1894        DB      'H'
1895        DB      4
1896        DB      'L'
1897        DB      5
1898        DB      'M'
1899        DB      6
1900        DB      'P'
1901        DB      6
1902        DB      'S'
1903        DB      6
1904        DB      0               ;END OF TABLE INDICATOR.
1905;
1906; THIS ROUTINE SCANS THE INPUT LINE AND PLACES TH
1907; OPCODES AND LABELS IN THE BUFFER.  THE SCAN TERMINATES
1908; WHEN A CHARACTER OTHER THAN 0-9 OR A-Z IS FOUND.
1909;
1910ALPS:   MVI     B,0             ;SET COUNT
1911ALP1:   STAX    D               ;STORE CHARACTER IN BUFFER
1912        INR     B               ;INCREMENT COUNT
1913        MOV     A,B             ;FETCH COUNT
1914        CPI     11              ;MAXIMUM BUFFER SIZE
1915        RNC                     ;RETURN IF BUFFER FILLED
1916        INX     D               ;INCREMENT BUFFER
1917        INX     H               ;INCREMENT INPUT POINTER
1918        SHLD    PNTR            ;SAVE LINE POINTER
1919        MOV     A,M             ;FETCH CHARACTER
1920        CPI     '0'             ;CHECK FOR ILLEGAL CHARACTERS
1921        RC
1922        CPI     '9'+1
1923        JC      ALP1
1924        CPI     'A'
1925        RC
1926        CPI     'Z'+1
1927        JC      ALP1
1928        RET
1929;
1930; THIS ROUTINE IS USED TO SCAN THROUGH THE INPUT LINE
1931; TO FETCH THE VALUE OF THE OPERAND FIELD.  ON RETURN,
1932; THE VALUE OF THE OPERAND IS CONTAINED IN REG?S H,L
1933;
1934ASBL:   CALL    SBLK            ;GET 1ST ARGUMENT
1935ASCN:   LXI     H,0             ;GET A ZERO
1936        SHLD    OPRD            ;INITIALIZE OPERAND
1937        INR     H
1938        SHLD    OPRI-1          ;INITIALIZE OPERAND INDICATOR
1939NXT1:   LHLD    PNTR            ;FETCH SCAN POINTER
1940        DCX     H
1941        CALL    ZBUF            ;CLEAR BUFFER
1942        STA     SIGN            ;ZERO SIGN INDICATOR
1943NXT2:   INX     H               ;INCREMENT POINTER
1944        MOV     A,M             ;FETCH NEXT CHARACTER
1945        CPI     ' '+1
1946        JC      SEND            ;JUMP IF CR OR BLANK
1947        CPI     ','             ;FIELD SEPARATOR
1948        JZ      SEND
1949; CHECK FOR OPERATOR
1950        CPI     '+'             ;CHECK FOR PLUS
1951        JZ      ASC1
1952        CPI     '-'             ;CHECK FOR MINUS
1953        JNZ     ASC2
1954        STA     SIGN
1955ASC1:   LDA     OPRI            ;FETCH OPERAND INDICATOR
1956        CPI     2               ;CHECK FOR 2 OPERATORS
1957        JZ      ERRS            ;SYNTAX ERROR
1958        MVI     A,2
1959        STA     OPRI            ;SET INDICATOR
1960        JMP     NXT2
1961; CHECK FOR OPERANDS
1962ASC2:   MOV     C,A             ;SAVE CHARACTER
1963        LDA     OPRI            ;GET INDICATOR
1964        ORA     A               ;CHECK FOR 2 OPERANDS
1965        JZ      ERRS            ;SYNTAX ERROR
1966        MOV     A,C
1967        CPI     '$'             ;LC EXPRESSION
1968        JNZ     ASC3
1969        INX     H               ;INCREMENT POINTER
1970        SHLD    PNTR            ;SAVE POINTER
1971        LHLD    ASPC            ;FETCH LOCATION COUNTER
1972        JMP     AVAL
1973;CHECK FOR ASCII CHARACTERS
1974ASC3:   CPI     27H             ;CHECK FOR SINGLE QUOTE
1975        JNZ     ASC5            ;JUMP IF NOT QUOTE
1976        LXI     D,0             ;GET A ZERO
1977        MVI     C,3             ;CHARACTER COUNT
1978ASC4:   INX     H               ;BUMP POINTER
1979        SHLD    PNTR            ;SAVE
1980        MOV     A,M             ;FETCH NEXT CHARACTER
1981        CPI     ASCR            ;IS IT A CARRIAGE RETURN?
1982        JZ      ERAR            ;ARGUMENT ERROR
1983        CPI     27H             ;IS IT A QUOTE?
1984        JNZ     SSTR
1985        INX     H               ;INCREMENT POINTER
1986        SHLD    PNTR            ;SAVE
1987        MOV     A,M             ;FETCH NEXT CHAR
1988        CPI     27H             ;CHECK FOR 2 QUOTES IN A ROW
1989        JNZ     AVAL+1          ;TERMINAL QUOTE
1990SSTR:   DCR     C               ;CHECK COUNT
1991        JZ      ERAR            ;TOO MANY CHARACTERS
1992        MOV     D,E
1993        MOV     E,A             ;SET CHARACTER IN BUFFER
1994        JMP     ASC4
1995ASC5:   CPI     '0'             ;CHECK FOR NUMERIC
1996        JC      ERAR            ;ILLEGAL CHARACTER
1997        CPI     '9'+1
1998        JNC     ALAB
1999        CALL    NUMS            ;GET NUMERIC VALUE
2000        JC      ERAR            ;ARGUMENT ERROR
2001AVAL:   XCHG
2002        LHLD    OPRD            ;FETCH OPERAND
2003        XRA     A               ;GET A ZERO
2004        STA     OPRI            ;STOR IN OPERAND INDICATOR
2005        LDA     SIGN            ;GET SIGN INDICATOR
2006        ORA     A               ;SET FLAGS
2007        JNZ     ASUB
2008        DAD     D               ;FORM RESULT
2009ASC7:   SHLD    OPRD            ;SAVE RESULT
2010        JMP     NXT1
2011ASUB:   MOV     A,L
2012        SUB     E
2013        MOV     L,A
2014        MOV     A,H
2015        SBB     D
2016        MOV     H,A
2017        JMP     ASC7
2018ALAB:   CALL    SLAB
2019        JZ      AVAL
2020        JC      ERAR            ;ILLEGAL SYMBOL
2021        JMP     ERRU            ;UNDEFINED SYMBOL
2022;
2023; GET HERE WHEN TERMINATING CHARACTER IS FOUND.
2024; CHECK FOR LEADING FIELD SEPARATOR
2025;
2026SEND:   LDA     OPRI            ;FETCH OPERAND INDICATOR
2027        ORA     A               ;SET FLAGS
2028        JNZ     ERRS            ;SYNTAX ERROR
2029        LHLD    OPRD
2030SEN1:   MOV     A,H             ;GET HIGH ORDER BYTE
2031        LXI     D,TEMP          ;GET ADDRESS
2032        ORA     A               ;SET FLAGS
2033        RET
2034;
2035; GET A NUMERIC VALUE WHICH IS EITHER HEXADECIMAL OR
2036; DECIMAL.  ON RETURN, CARRY SET INDICATES AN ERROR.
2037;
2038NUMS:   CALL    ALPS            ;GET NUMERIC
2039        DCX     D
2040        LDAX    D               ;GET LAST CHARACTER
2041        LXI     B,ABUF          ;SET BUFFER ADDRESS
2042        CPI     'H'             ;IS IT HEXADECIMAL?
2043        JZ      NUM2
2044        CPI     'D'             ;IS IT DECIMAL
2045        JNZ     NUM1
2046        XRA     A               ;GET A ZERO
2047        STAX    D               ;CLEAR D FROM BUFFER
2048NUM1:   CALL    ADEC            ;CONVERT DECIMAL VALUE
2049        RET
2050NUM2:   XRA     A               ;GET A ZERO
2051        STAX    D               ;CLEAR H FROM BUFFER
2052        CALL    AHEX
2053        RET
2054;
2055; PROCESS REGISTER ERROR
2056;
2057ERRR:   MVI     A,'R'           ;GET INDICATOR
2058        LXI     H,0             ;GET A ZERO
2059        STA     OBUF            ;SET IN OUTPUT BUFFER
2060        RET
2061;
2062; PROCESS SYNTAX ERROR
2063;
2064ERRS:   MVI     A,'S'           ;GET INDICATOR
2065        STA     OBUF            ;STORE IN OUTPUT BUFFER
2066        LXI     H,0
2067        JMP     SEN1
2068;
2069; PROCESS UNDEFINED SYMBOL ERROR
2070;
2071ERRU:   MVI     A,'U'           ;GET INDICATOR
2072        JMP     ERRS+2
2073;
2074; PROCESS VALUE ERROR
2075;
2076ERRV:   MVI     A,'V'           ;GET INDICATOR
2077        JMP     ERRR+2
2078;
2079; PROCESS MISSING LABEL ERROR
2080;
2081ERRM:   MVI     A,'M'           ;GET INDICATOR
2082        STA     OBUF            ;STORE IN OUTPUT BUFFER
2083        CALL    AOU1            ;DISPLAY ERROR
2084        RET
2085;
2086;PROCESS ARGUMENT ERROR
2087;
2088ERAR:   MVI     A,'A'           ;GET INDICATOR
2089        JMP     ERRS+2
2090;
2091; PROCESS OPCODE ERROR
2092; STORE 3 BYTES OF ZERO IN OBJECT CODE TO PROVIDE
2093; FOR A PATCH
2094;
2095ERRO:   MVI     A,'O'           ;GET INDICATOR
2096        STA     OBUF            ;STORE IN OUTPUT BUFFER
2097        LDA     PASI            ;FETCH PASS INDICATOR
2098        ORA     A               ;WHICH PASS
2099        RZ                      ;RETURN IF PASS 1
2100        MVI     C,3             ;NEED 3 BYTES
2101ERO1:   XRA     A               ;GET A ZERO
2102        CALL    ASTO            ;PUT IN LISTING AND MEMORY
2103        DCR     C
2104        JNZ     ERO1
2105        RET
2106;
2107; PROCESS LABEL ERROR
2108;
2109ERRL:   MVI     A,'L'           ;GET INDICATOR
2110        JMP     ERRO+2
2111;
2112; PROCESS DUPLICATE LABEL ERROR
2113;
2114ERRD:   MVI     A,'D'           ;GET INDICATOR
2115        STA     OBUF
2116        CALL    AOUT
2117        JMP     OPC
2118;
2119; THIS ROUTINE SETS OR CLEARS BREAKPOINTS
2120;
2121BREAK:  LDA     ABUF            ;CHECK FOR AN ARG
2122        ORA     A
2123        JZ      CLRB            ;IF NO ARGUMENT, GO CLEAR BREAKPOINT
2124        MVI     D, NBR          ;ELSE GET NUMBER OF BREAKPOINTS
2125        LXI     H,BRT           ;AND ADDR OF TABLE
2126B1:     MOV     A,M             ;GET HI BYTE OF ENTRY
2127        INX     H
2128        MOV     B,M             ;GET LOW BYTE OF ENTRY
2129        ORA     B               ;CHECK FOR EMPTY ENTRY
2130        JZ      B2              ;BRANCH IF EMPTY
2131        INX     H               ;ELSE GO ON TO NEXT ENTRY
2132        INX     H
2133        DCR     D               ;BUMP COUNT
2134        JNZ     B1              ;AND TRY AGAIN
2135        JMP     WHAT            ;OOPS NO ROOM
2136B2:     DCX     H
2137        XCHG
2138        LHLD    BBUF            ;GET ADDRESS
2139        XCHG                    ;IN D,E
2140        MOV     A,D             ;CHECK FOR ADDR > 11D
2141        ORA     A
2142        JNZ     B3
2143        MOV     A,E
2144        CPI     11
2145            JC  WHAT            ;OOPS, TOO LOW
2146B3:     MOV     M,D             ;SAVE ADDRESS
2147        INX     H
2148        MOV     M,E
2149        INX     H
2150        LDAX    D               ;PICK UP INSTRUCTION
2151        MOV     M,A             ;SAVE IT
2152        MVI     A,0CFH          ;RST 1 INSTRUCTION
2153        STAX    D
2154        MVI     A,0C3H          ;SET UP LO MEMORY
2155        STA     8               ;WITH A JUMP TO BREAKPOINT
2156        LXI     H,BRKP
2157        SHLD    9
2158        RET                     ;THEN RETURN
2159;
2160; THIS ROUTINE CLEARS ALL BREAKPOINTS
2161;
2162CLRB:   LXI     H,BRT           ;GET TABLE ADDRESS
2163        MVI     B,NBR           ;GET NUMBER OF BREAKPOINTS
2164CLBL:   XRA     A               ;GET A ZERO
2165        MOV     D,M             ;GET HI-BYTE OF ENTRY
2166        MOV     M,A
2167        INX     H
2168        MOV     E,M             ;GET LO-BYTE OF ENTRY
2169        MOV     M,A
2170        INX     H
2171        MOV     B,M             ;GET INST BYTE
2172        INX     H
2173        MOV     A,D             ;WAS THIS A NULL ENTRY
2174        ORA     E
2175        JZ      CL2             ;BRANCH IF IT WAS
2176        MOV     A,B
2177        STAX    D               ;ELSE PLUG INST BACK IN
2178CL2:    DCR     B               ;BUMP COUNT
2179        JNZ     CLBL            ;GO DO NEXT ONE
2180        RET
2181;
2182; COME HERE WHEN WE HIT A BREAKPOINT
2183;
2184BRKP:   SHLD    HOLD+8          ;SAVE H,L
2185        POP     H               ;GET PC
2186        DCX     H               ;ADJUST IT
2187        SHLD    HOLD+10         ;SAVE IT
2188        PUSH    PSW             ;SAVE FLAGS
2189        POP     H               ;GET THEM INTO H,L
2190        SHLD    HOLD            ;NOW STORE THEM FOR USER
2191        LXI     H,0
2192        DAD     SP              ;GET STACK POINTER
2193        LXI     SP,HOLD+8       ;SET STACK POINTER AGAIN
2194        PUSH    H               ;SAVE OLD SP
2195        PUSH    D               ;SAVE D,E
2196        PUSH    B               ;SAVE B,C
2197        CMA                     ;COMPLEMENT ACCUMULATOR
2198        OUT     0FFH            ;DISPLAY IT IN LIGHTS
2199        LXI     SP,AREA+18      ;SET SP AGAIN
2200        LHLD    HOLD+10         ;GET PC
2201        XCHG                    ;INTO D,E
2202        LXI     H,BRT           ;GET ADDR OF TABLE
2203        MVI     B,NBR           ;AND NUMBER OF ENTRIES
2204BL1:    MOV     A,M             ;GET AN ENTRY FROM THE TABLE
2205        INX     H
2206        CMP     D               ;DOES IT MATCH?
2207        JNZ     BL2             ;BRANCH IF NOT
2208        MOV     A,M             ;ELSE GET NEXT BYTE
2209        CMP     E               ;CHECK IT
2210        JZ      BL3             ;IT MATCHES!
2211BL2:    INX     H               ;BUMP AROUND THIS ENTRY
2212        INX     H
2213        DCR     B               ;BUMP COUNT
2214        JZ      WHAT            ;NOT IN OUR TABLE
2215        JMP     BL1
2216;
2217BL3:    INX     H
2218        MOV     A,M             ;GET INSTR BYTE
2219        STAX    D               ;PUT IT BACK
2220        XRA     A               ;CLEAR ENTRY IN TABLE
2221        DCX     H
2222        MOV     M,A
2223        DCX     H
2224        MOV     M,A
2225        CALL    CRLF            ;RESTORE THE CARRIAGE
2226        LDA     HOLD+11         ;GET HI-BYTE OF PC
2227        CALL    HOUT            ;TYPE IT
2228        LDA     HOLD+10         ;GET LO-BYTE OF PC
2229        CALL    HOUT            ;TYPE IT
2230        LXI     H,BMES          ;TELL USER WHAT IT IS
2231        CALL    SCRN
2232        JMP     EOR             ;GO BACK TO COMMAND LEVEL
2233;
2234BMES:   DB      ' BREAK',13
2235;
2236; THIS ROUTINE PROCEEDS FROM A BREAKPOINT
2237;
2238PROC:   LDA     ABUF            ;CHECK FOR ARG
2239        ORA     A
2240        JZ      P1              ;JUMP IF NO ARG
2241        LHLD    BBUF            ;ELSE GET ARG
2242        SHLD    HOLD+10         ;PLUG IT INTO PC SLOT
2243P1:     LXI     SP,HOLD         ;SET SP TO POINT AT REG?S
2244        POP     PSW             ;RESTORE PSW
2245        POP     B               ;RESTORE B,C
2246        POP     D               ;RESTORE D,E
2247        POP     H               ;GET OLD SP
2248        SPHL                    ;RESTORE IT
2249        LHLD    HOLD+10         ;GET PC
2250        PUSH    H               ;PUT IT ON STACK
2251        LHLD    HOLD+8          ;RESTORE H,L
2252        RET                     ;AND PROCEED
2253;
2254; SYSTEM RAM
2255;
2256        ORG     1000H
2257;
2258; DEFINE BREAKPOINT REGION
2259;
2260NBR     EQU     8               ;NUMBER OF BREAKPOINTS
2261HOLD:   DS      12              ;REGISTER HOLD AREA
2262BRT:    DS      3*NBR           ;BREAKPOINT TABLE
2263;
2264; FILE AREA PARAMETERS
2265;
2266MAXFIL  EQU     6
2267NMLEN   EQU     5
2268FELEN   EQU     NMLEN+8
2269FILE0:  DS      NMLEN
2270BOFP:   DS      2
2271EOFP:   DS      2
2272MAXL:   DS      4
2273FILTB:  DS      (MAXFIL-1)*FELEN
2274INSP:   DS      2
2275DELP    EQU     INSP
2276ASCR    EQU     13
2277HCON:   DS      2
2278ADDS    EQU     HCON
2279FBUF:   DS      NMLEN
2280FREAD:  DS      2
2281FEF:    DS      1
2282FOCNT   EQU     FEF
2283ABUF:   DS      12
2284BBUF:   DS      4
2285SCNT:   DS      1
2286DCNT:   DS      1
2287NCOM    EQU     11
2288TABA:   DS      2
2289ASPC:   DS      2
2290PASI:   DS      1
2291NCHR:   DS      1
2292PNTR:   DS      2
2293NOLA:   DS      1
2294SIGN:   DS      1
2295OPRD:   DS      2
2296OPRI:   DS      1
2297TEMP:   DS      1
2298APNT    EQU     INSP
2299AERR    EQU     SCNT
2300OIND:   DS      2
2301LLAB    EQU     5
2302AREA:   DS      18
2303OBUF:   DS      16
2304        DS      5
2305IBUF:   DS      83
2306SWCH    EQU     0FFH
2307SYMT    EQU     $
2308        END
2309