home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / zsys / znode-12 / i / procself.lbr / PROCSELF.AZM / PROCSELF.ASM
Encoding:
Assembly Source File  |  1993-06-12  |  51.9 KB  |  2,206 lines

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