home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / ucasm.lbr / UCASM.ZZ0 / UCASM.Z80
Encoding:
Text File  |  1988-01-08  |  38.5 KB  |  2,470 lines

  1.  
  2. ; UCASM Micro-controller Assembler
  3. ; copyright (c) 1987, 1988 by J. L. Post
  4. ; This file MUST be accompanied by UCASM.DOC - Please read it
  5. ;
  6. ; Version 1.2 - Dec/21/87
  7. ;    added line number in error reports
  8. ; Version 1.1 - Dec/18/87
  9. ;    added DB, DW, and DS as equivalents of DEFB, DEFW, and DEFS
  10. ;    added operators <, >, and ^ for shift left, shift right, and
  11. ;    control character definition. Also check for divide by zero.
  12. ; Version 1.0 - first release Dec/13/87
  13. ;
  14. ; Assembles code for the following micro-controllers:
  15. ;
  16. ;            ROM (E = eprom)
  17. ;        1K    2K    4K    External
  18. ;-----------------------------------------------
  19. ; RAM    64    8021 *            8035
  20. ; (bytes)    8041 *
  21. ;        8048
  22. ;        8741 (E) *
  23. ;        8748 (E)
  24. ;-----------------------------------------------
  25. ;    128    8041 *    8049        8039
  26. ;        8741 (E) *
  27. ;-----------------------------------------------
  28. ;    256        8042    8050    8040
  29. ;            8742 (E)
  30. ;-----------------------------------------------
  31. ;
  32. ; * 8021 is a 28 pin chip that supports a subset of 8035 code.
  33. ; 8041/8741 are listed twice because the NEC chip has only 64
  34. ; bytes of internal ram, while the Intel chip has 128 bytes
  35. ; (at least that's what the spec sheets say.)
  36. ;
  37. VER    EQU    1        ; Version number
  38. REV    EQU    2        ; Revision number
  39. ;
  40. TAB    EQU    9
  41. CR    EQU    13
  42. LF    EQU    10
  43. CTRLZ    EQU    1AH        ; Control Z
  44. ESC    EQU    1BH        ; Escape
  45. QUOTE    EQU    27H        ; ASCII single quote (')
  46. CARAT    EQU    5EH        ; Control char definition (^)
  47. ;
  48. BOOT    EQU    0
  49. BDOS    EQU    5
  50. FCB    EQU    5CH
  51. ;
  52. ;
  53.     ORG    100H
  54. ;
  55.     JR    START
  56. ;
  57. ;
  58. HEXOPT:    DEFB    0        ; 0 if no FILE.HEX output
  59. LSTOPT:    DEFB    0        ; 0 if no FILE.LST output
  60. LSTTYP:    DEFB    'LST'        ; Default list file type
  61. HEXTYP:    DEFB    'HEX'        ; Default object file type
  62. MAXERR:    DEFB    10        ; Maximum error count before abort
  63. PAGLEN:    DEFB    0        ; List page length (0 if no paging, usually 66)
  64.     DEFB    0        ; Lines printed per page (suggest 60)
  65. SRCTYP:    DEFB    'Z80'        ; Default source file type
  66. ;
  67. ; HEXOPT and LSTOPT can be modified at run time by the H or L options
  68. ;
  69. START:    LD    SP,STACK
  70.     LD    HL,IMSG        ; Say hello
  71.     CALL    PRINT
  72.     CALL    INIT        ; Init fcb's and options
  73.     CALL    GETSRC        ; Read in source file
  74.     JR    C,RDERR        ; Abort if read error
  75.     CALL    ASM        ; Do the assembly
  76.     CALL    DCRLF
  77.     LD    BC,(BYTCNT)    ; Show how many bytes in object code
  78.     CALL    PDEC
  79.     LD    HL,DONMSG    ; Points to 'byte' text
  80.     CALL    DUALP        ; Print to console and/or list file
  81.     LD    BC,(BYTCNT)
  82.     LD    A,B
  83.     OR    A
  84.     JR    NZ,END1        ; Go if object byte count > 256
  85.     LD    A,C
  86.     DEC    A
  87.     JR    Z,END2        ; Go if byte count = 1
  88. ;
  89. END1:    LD    A,'s'        ; Else append 's'
  90.     CALL    DCHR        ; Output to console and/or list file
  91. ;
  92. END2:    LD    A,','
  93.     CALL    DCHR
  94.     LD    A,' '
  95.     CALL    DCHR
  96.     LD    A,(ERRCNT)    ; Show error count
  97.     LD    C,A
  98.     LD    B,0
  99.     CALL    PDEC
  100.     CALL    DUALP
  101.     LD    A,(ERRCNT)
  102.     DEC    A
  103.     JR    Z,EXIT
  104.     LD    A,'s'
  105.     CALL    DCHR
  106. ;
  107. EXIT:    LD    A,(FILFLG)    ; Test if any files open
  108.     OR    A
  109.     JR    Z,EXIT1        ; Go if none opened
  110.     AND    1
  111.     CALL    NZ,CLSHEX    ; Close open hex file
  112.     LD    A,(FILFLG)
  113.     AND    4
  114.     CALL    NZ,CLSLST    ; Close open list file
  115. ;
  116. EXIT1:    JP    BOOT        ; Exit to system
  117. ;
  118. RDERR:    LD    HL,RDERMS    ; Source file read error
  119.     CALL    PRINT
  120.     JR    EXIT
  121. ;
  122. CLSHEX:    LD    A,(HEXFLG)    ; Close .HEX object file
  123.     AND    80H
  124.     CALL    NZ,HEXDMP    ; Clear record buffer
  125.     LD    HL,LASTHR    ; Set last hex record
  126. ;
  127. CLSHX1:    LD    A,(HL)
  128.     INC    HL
  129.     OR    A
  130.     JR    Z,CLSHX2
  131.     CALL    HEXOUT
  132.     JR    CLSHX1
  133. ;
  134. CLSHX2:    LD    A,(FILFLG)
  135.     AND    2
  136.     CALL    NZ,FLSHEX    ; Flush hex buffer
  137.     LD    DE,FCB1
  138.     JR    CLOSE        ; Close file
  139. ;
  140. CLSLST:    LD    A,(FILFLG)    ; Close open list file
  141.     AND    8
  142.     CALL    NZ,FLSLST    ; Flush list buffer
  143.     LD    DE,FCB2        ; And close file
  144. ;
  145. CLOSE:    PUSH    HL        ; Close open files
  146.     LD    C,16
  147.     CALL    BDOS
  148.     POP    HL
  149.     RET
  150. ;
  151. ; Flush data out of open buffers
  152. ;
  153. FLSHEX:    PUSH    HL
  154.     LD    DE,(HEXDMA)    ; Set transfer address
  155.     CALL    SETDMA
  156.     LD    HL,(HEXDMA)
  157.     LD    DE,FCB1
  158.     LD    BC,(HEXOFF)    ; Get byte count
  159.     JR    FLSLS0
  160. ;
  161. FLSLST:    PUSH    HL
  162.     LD    DE,(LSTDMA)
  163.     CALL    SETDMA
  164.     LD    HL,(LSTDMA)
  165.     LD    DE,FCB2
  166.     LD    BC,(LSTOFF)
  167. FLSLS0:    ADD    HL,BC
  168. ;
  169. FLSLS1:    BIT    7,C
  170.     JR    NZ,WRITE
  171.     LD    (HL),CTRLZ    ; Fill extra space with control Z
  172.     INC    HL
  173.     INC    C
  174.     JR    FLSLS1
  175. ;
  176. WRITE:    LD    C,21        ; Write record to file
  177.     CALL    BDOS
  178.     POP    HL
  179.     RET
  180. ;
  181. LASTHR:    DEFB    ':00000001FF',0
  182. ;
  183. ; Initialize FCBs and options
  184. ;
  185. INIT:    LD    A,(FCB+9)    ; See if file type specified
  186.     CP    ' '
  187.     JR    NZ,INIT1
  188.     LD    HL,SRCTYP    ; Set default file type
  189.     LD    DE,FCB+9
  190.     LD    BC,3
  191.     LDIR
  192.  
  193. INIT1:    LD    HL,FCB1
  194.     LD    DE,FCB1+1
  195.     LD    BC,72
  196.     LD    (HL),0        ; Clear output fcbs
  197.     LDIR
  198.     LD    HL,FCB
  199.     LD    DE,FCB1
  200.     LD    BC,9
  201.     LDIR
  202.     LD    HL,HEXTYP    ; Init object file fcb
  203.     LD    BC,3
  204.     LDIR
  205.     LD    HL,FCB
  206.     LD    DE,FCB2
  207.     LD    BC,9
  208.     LDIR
  209.     LD    HL,LSTTYP    ; Init list file FCB
  210.     LD    BC,3
  211.     LDIR
  212.     LD    HL,FCB+17    ; Point to auxiliary FCB for options
  213. ;
  214. INIT2:    LD    A,(HL)
  215.     INC    HL
  216.     CP    21H
  217.     RET    C
  218.     CP    'H'
  219.     JR    Z,INIT3
  220.     CP    'L'
  221.     JR    NZ,INIT2
  222.     LD    (LSTOPT),A    ; Set list file option
  223.     JR    INIT2
  224. ;
  225. INIT3:    LD    (HEXOPT),A    ; Set .HEX file option
  226.     JR    INIT2
  227. ;
  228. ; Read in source file
  229. ;
  230. GETSRC:    LD    DE,IBFR        ; Set DMA address
  231.     LD    (IBFRP),DE    ; Set input buffer pointer
  232.     LD    (IBFEND),DE    ; Flag end of input buffer
  233.     CALL    SETDMA
  234.     LD    DE,FCB        ; Attempt to open file
  235.     CALL    OPNFIL
  236.     RET    C        ; Abort if error
  237. ;
  238. GTSRC1:    LD    DE,FCB
  239.     LD    C,20
  240.     CALL    BDOS        ; Read record
  241.     OR    A
  242.     JR    NZ,GTSRC2    ; Go if done
  243.     LD    HL,(IBFEND)    ; Else updata DMA address
  244.     LD    BC,128
  245.     ADD    HL,BC
  246.     LD    (IBFEND),HL    ; Update buffer end address
  247.     LD    D,H
  248.     LD    E,L
  249.     CALL    SETDMA        ; Update transfer address
  250.     JR    GTSRC1
  251. ;
  252. GTSRC2:    LD    HL,(IBFEND)    ; Test for empty file
  253.     LD    DE,IBFR
  254.     INC    DE
  255.     SBC    HL,DE
  256.     RET    C        ; Abort with error if file empty
  257.     LD    A,(IBFR)    ; Get first character
  258.     CP    CTRLZ
  259.     JR    Z,GTSRC3    ; Error if end of file char
  260.     LD    HL,(IBFEND)
  261.     INC    HL
  262.     INC    HL
  263.     LD    (SYMTAB),HL    ; Initialize symbol table pointers
  264.     LD    (SYMEND),HL
  265.     LD    (SYMPTR),HL
  266.     LD    (HL),0        ; Disable garbage in symbol table
  267.     OR    A        ; By setting terminator byte
  268.     RET
  269. ;
  270. GTSRC3:    SCF            ; Flag error and return
  271.     RET
  272. ;
  273. HEXOPN:    LD    A,(FILFLG)    ; Open .HEX file, if optioned
  274.     OR    1
  275.     LD    (FILFLG),A
  276.     LD    DE,FCB1
  277.     LD    (FCBTMP),DE
  278.     JR    OPEN
  279. ;
  280. LSTOPN:    LD    A,(FILFLG)    ; Open list file, if optioned
  281.     OR    4
  282.     LD    (FILFLG),A
  283.     LD    DE,FCB2
  284.     LD    (FCBTMP),DE
  285. ;
  286. OPEN:    LD    DE,(FCBTMP)
  287.     CALL    OPNFIL        ; Attempt to open file
  288.     JR    C,OPEN1        ; Go if doesn't exist
  289.     LD    DE,(FCBTMP)
  290.     LD    C,19
  291.     CALL    BDOS        ; Else kill it (ouch!)
  292. ;
  293. OPEN1:    LD    DE,(FCBTMP)
  294.     LD    C,22
  295.     CALL    BDOS        ; Make new file
  296.     INC    A        ; Z set if error
  297.     RET
  298. ;
  299. OPNFIL:    LD    C,15
  300.     CALL    BDOS
  301.     INC    A
  302.     JR    Z,OPNFL1    ; Go if can't open file
  303.     XOR    A
  304.     RET
  305. ;
  306. OPNFL1:    SCF            ; Open file error return
  307.     RET
  308. ;
  309. SETDMA:    PUSH    HL        ; Set dma transfer address in DE
  310.     PUSH    BC
  311.     LD    C,26
  312.     CALL    BDOS
  313.     POP    BC
  314.     POP    HL
  315.     RET
  316. ;
  317. ; End of Assembly Pass Processing
  318. ;
  319. ASMDON:    LD    HL,IBFR
  320.     LD    (IBFRP),HL    ; Reset input buffer pointer
  321.     LD    HL,0
  322.     LD    (PC),HL        ; Reset program counter
  323.     LD    (LINUM),HL    ; Clear line number
  324.     LD    A,(PASS)
  325.     INC    A
  326.     LD    (PASS),A    ; Update pass number
  327.     CP    2
  328.     RET    NC
  329.     DEC    A
  330.     JR    NZ,ASM        ; Go if pass 1
  331.     LD    A,(HEXOPT)
  332.     OR    A
  333.     JR    Z,ASMDN1    ; Go if no object file option
  334.     LD    HL,(SYMEND)
  335.     INC    H
  336.     LD    (HEXDMA),HL    ; Set address of hex file buffer
  337.     CALL    HEXOPN        ; Open hex file
  338.     LD    HL,HEXTYP
  339.     JR    Z,OPNERR    ; Go if can't open object file
  340. ;
  341. ASMDN1:    LD    A,(LSTOPT)
  342.     OR    A
  343.     JR    Z,ASM        ; Go if no list file option
  344.     LD    HL,(SYMEND)
  345.     INC    H
  346.     INC    H
  347.     LD    (LSTDMA),HL    ; Set address of list file buffer
  348.     CALL    LSTOPN        ; Open list file
  349.     LD    HL,LSTTYP
  350.     JR    NZ,ASM        ; Go if open ok
  351. ;
  352. OPNERR:    EX    DE,HL        ; Can't open file
  353.     LD    HL,OPNEMS    ; Report error
  354.     CALL    PRINT
  355.     LD    B,3
  356. ;
  357. OPNER1:    LD    A,(DE)        ; Show type of file
  358.     CALL    CHROUT
  359.     INC    DE
  360.     DJNZ    OPNER1
  361.     CALL    PRINT
  362.     JP    EXIT        ; Then abort
  363. ;
  364. ; Assemble source code
  365. ;
  366. ASM:    XOR    A
  367.     LD    (ERRFLG),A    ; Clear error flag
  368.     LD    (OCLEN),A    ; And opcode length
  369.     LD    HL,(LINUM)
  370.     INC    HL
  371.     LD    (LINUM),HL
  372.     CALL    GETLIN        ; Get next line into buffer
  373.     CP    CTRLZ
  374.     JR    Z,ASMDON    ; Go if end of file
  375.     LD    HL,LINBFR
  376.     LD    A,(HL)
  377.     CP    CTRLZ
  378.     JR    Z,ASMDON    ; Go if end of file
  379.     CP    CR
  380.     JP    Z,ASMRET    ; Ignore empty line
  381.     CP    TAB
  382.     JR    Z,ASM1        ; Go if no label
  383.     CP    ' '
  384.     JR    Z,ASM1        ; Ditto
  385.     CP    ';'
  386.     JP    Z,ASMRET    ; Go if comment line
  387.     LD    A,(PASS)
  388.     OR    A
  389.     JR    NZ,ASM01    ; Go if pass two
  390.     PUSH    HL        ; Else enter label in symbol table
  391.     CALL    FNDSYM        ; See if already exists
  392.     EX    DE,HL        ; Put pointer in DE
  393.     POP    HL
  394.     JR    NZ,ASM0        ; Go if entry not found
  395.     LD    A,3
  396.     LD    (ERRFLG),A    ; Else flag multi def label error
  397.     EX    DE,HL
  398. ;
  399. ASM00:    DEC    HL
  400.     LD    A,(HL)
  401.     CP    ' '
  402.     JR    NC,ASM00    ; Find byte count
  403.     SET    7,(HL)        ; Flag as multiple for pass 2
  404.     JP    ASMERR
  405. ;
  406. ASM0:    PUSH    HL
  407.     CALL    ENTSYM        ; Enter into symbol table
  408.     DEC    HL        ; Point to value
  409.     DEC    HL
  410.     LD    BC,(PC)        ; Get program counter
  411.     LD    (HL),C
  412.     INC    HL
  413.     LD    (HL),B
  414.     POP    HL
  415. ;
  416. ASM01:    CALL    SKPLBL        ; Skip over label
  417. ;
  418. ASM1:    CALL    NEXTF        ; Point to next field
  419.     LD    A,1
  420.     LD    (ERRFLG),A
  421.     CALL    LOOKUP        ; Find entry in opcode table
  422.     JR    C,ASMER        ; Go if not found
  423.     XOR    A
  424.     LD    (ERRFLG),A
  425. ;
  426. ; Opcode entry found in table, DE => opcode in table
  427. ;
  428.     CALL    SKPLBL        ; Skip past mnemonic
  429.     CALL    NEXTF        ; Point HL to next field
  430.     LD    A,(DE)
  431.     LD    (OPCODE),A    ; Set base opcode
  432.     LD    A,(MAXTYP)
  433.     LD    B,A
  434.     INC    DE
  435.     LD    A,(DE)        ; Get group type
  436.     BIT    7,A
  437.     JR    NZ,PSUDO    ; Go if pseudo op
  438.     DEC    A
  439.     CP    B
  440.     JR    NC,ASMERR    ; Go if error
  441.     LD    C,A
  442.     LD    B,0
  443.     LD    IX,GRPTBL    ; Point to routine entry table
  444.     ADD    IX,BC
  445.     ADD    IX,BC
  446.     LD    C,(IX+0)    ; Get address of routine
  447.     LD    B,(IX+1)
  448.     PUSH    BC
  449.     POP    IX
  450. ;
  451. ASM2:    LD    IY,ASMRET    ; Set return address on stack
  452.     PUSH    IY
  453.     JP    (IX)        ; Execute routine
  454. ;
  455. PSUDO:    AND    7
  456.     PUSH    HL
  457.     LD    HL,PSUDTB    ; Get pseudo op table entry
  458.     ADD    A,A
  459.     LD    C,A
  460.     LD    B,0
  461.     ADD    HL,BC
  462.     LD    A,(HL)
  463.     INC    HL
  464.     LD    H,(HL)
  465.     LD    L,A
  466.     PUSH    HL
  467.     POP    IX
  468.     POP    HL
  469.     JR    ASM2
  470. ;
  471. ASMER:
  472. ASMERR:    LD    A,(ERRFLG)
  473.     ADD    A,A
  474.     LD    C,A
  475.     LD    B,0
  476.     XOR    A
  477.     LD    (ERRFLG),A    ; Clear error
  478.     LD    A,C
  479.     CP    6
  480.     JR    Z,ASMER1    ; Go if multiple label def
  481.     LD    A,(PASS)
  482.     OR    A
  483.     JR    Z,ASMRET    ; No error msg or update in pass 1
  484. ;
  485. ASMER1:    LD    HL,ERRMSG
  486.     CALL    DUALP
  487.     LD    HL,ERRTBL
  488.     ADD    HL,BC
  489.     LD    A,(HL)
  490.     INC    HL
  491.     LD    H,(HL)
  492.     LD    L,A
  493.     CALL    DUALP
  494.     LD    HL,LINMSG
  495.     CALL    DUALP
  496.     LD    BC,(LINUM)
  497.     CALL    PDEC
  498.     CALL    DCRLF
  499.     LD    HL,LINBFR
  500.     CALL    PRINT
  501.     CALL    UPERCT        ; Update error counter
  502.     XOR    A
  503. ;
  504. ASMRET:    JR    C,ASMERR    ; Go if subroutine error
  505.     LD    A,(ERRFLG)
  506.     OR    A
  507.     JR    NZ,ASMERR
  508.     LD    A,(PASS)
  509.     OR    A
  510.     JR    Z,ASMR1        ; Go if first pass
  511.     LD    A,(HEXOPT)
  512.     OR    A
  513.     CALL    NZ,HEXWR    ; Go if hex output required
  514.     LD    A,(LSTOPT)
  515.     OR    A
  516.     CALL    NZ,LSTWR    ; Go if list output required
  517. ;
  518. ASMR1:    LD    A,(OCLEN)    ; Update program counter
  519.     LD    HL,(PC)
  520.     LD    C,A
  521.     LD    B,0
  522.     ADD    HL,BC
  523.     LD    (PC),HL
  524.     LD    A,(PASS)
  525.     OR    A
  526.     JP    Z,ASM        ; No update byte count on pass 1
  527.     LD    HL,(BYTCNT)
  528.     ADD    HL,BC
  529.     LD    (BYTCNT),HL
  530.     JP    ASM
  531. ;
  532. ; Find mnemonic in opcode table
  533. ; On entry HL => start of linebfr opcode
  534. ; On exit DE => opcode in opcode table, C set if not found
  535. ;
  536. LOOKUP:    LD    DE,OPTBL
  537. ;
  538. LOOK1:    LD    A,(DE)
  539.     AND    7
  540.     JR    NZ,LOOK2
  541.     SCF
  542.     RET
  543. ;
  544. LOOK2:    LD    B,A
  545.     PUSH    HL
  546.     INC    DE
  547.     CALL    CPSTRG        ; Compare strings
  548.     LD    A,(HL)        ; Check if source end
  549.     POP    HL
  550.     JR    Z,LOOK5        ; Go if match
  551. ;
  552. LOOK3:    INC    DE        ; Skip to end of mnemonic
  553.     DJNZ    LOOK3
  554. ;
  555. LOOK4:    INC    DE        ; Skip over code and group
  556.     INC    DE
  557.     JR    LOOK1
  558. ;
  559. LOOK5:    CP    21H
  560.     JR    NC,LOOK4    ; Go if not full match
  561.     XOR    A
  562.     RET
  563. ;
  564. CPSTRG:    LD    A,(DE)
  565.     CP    (HL)
  566.     RET    NZ
  567.     INC    HL
  568.     INC    DE
  569.     DJNZ    CPSTRG
  570.     RET
  571. ;
  572. GETLIN:    LD    HL,(IBFRP)    ; Get input buffer pointer
  573.     LD    DE,LINBFR
  574.     LD    (LINBFP),DE    ; Init line buffer pointer
  575.     LD    B,80        ; Max char count per line
  576. ;
  577. GTLIN1:    LD    A,(HL)
  578.     CP    CTRLZ
  579.     RET    Z        ; Done if end of file
  580.     LD    (DE),A        ; Store in line buffer
  581.     INC    DE
  582.     INC    HL
  583.     CP    LF
  584.     JR    Z,GTLIN2    ; Do for entire line
  585.     DJNZ    GTLIN1
  586. ;
  587. GTLIN2:    XOR    A
  588.     LD    (DE),A        ; Flag end of line
  589.     LD    (IBFRP),HL    ; Update input buffer pointer
  590.     RET
  591. ;
  592. ; Print decimal value in BC, suppress leading zeros
  593. ;
  594. PDEC:    PUSH    HL
  595.     PUSH    DE
  596.     LD    H,B
  597.     LD    L,C
  598.     LD    C,0
  599.     LD    DE,1000
  600.     CALL    PDECS
  601.     LD    DE,100
  602.     CALL    PDECS
  603.     LD    DE,10
  604.     CALL    PDECS
  605.     LD    A,L
  606.     OR    30H
  607.     CALL    DCHR
  608.     POP    DE
  609.     POP    HL
  610.     RET
  611. ;
  612. PDECS:    LD    B,0
  613. ;
  614. PDECS1:    INC    B
  615.     SBC    HL,DE
  616.     JR    NC,PDECS1
  617.     DEC    B
  618.     ADD    HL,DE
  619.     LD    A,B
  620.     OR    A
  621.     JR    NZ,PDECS2
  622.     BIT    0,C
  623.     RET    Z
  624. ;
  625. PDECS2    SET    0,C
  626.     OR    30H
  627.     JR    DCHR
  628. ;
  629. DUALP:    LD    A,(PASS)
  630.     OR    A
  631.     JR    Z,PRINT
  632.     LD    A,(LSTOPT)
  633.     OR    A
  634.     JR    Z,PRINT
  635.     PUSH    HL
  636.     PUSH    BC
  637. ;
  638. DUALP1:    LD    A,(HL)
  639.     INC    HL
  640.     OR    A
  641.     JR    Z,DUALP2
  642.     CALL    PUTLST
  643.     JR    DUALP1
  644. ;
  645. DUALP2:    POP    BC
  646.     POP    HL
  647. ;
  648. PRINT:    LD    A,(HL)
  649.     INC    HL
  650.     OR    A
  651.     RET    Z
  652.     CALL    CHROUT
  653.     JR    PRINT
  654. ;
  655. DCRLF:    LD    A,(PASS)
  656.     OR    A
  657.     JR    Z,CRLF
  658.     LD    A,(LSTOPT)
  659.     OR    A
  660.     JR    Z,CRLF
  661.     PUSH    HL
  662.     PUSH    BC
  663.     LD    A,CR
  664.     CALL    PUTLST
  665.     LD    A,LF
  666.     CALL    PUTLST
  667.     POP    BC
  668.     POP    HL
  669. ;
  670. CRLF:    LD    A,CR
  671.     CALL    CHROUT
  672.     LD    A,LF
  673. ;
  674. CHROUT:    PUSH    HL
  675.     PUSH    DE
  676.     PUSH    BC
  677.     PUSH    AF
  678.     LD    E,A
  679.     LD    C,6
  680.     CALL    BDOS
  681.     POP    AF
  682. ;
  683. SYSRET:    POP    BC
  684.     POP    DE
  685.     POP    HL
  686.     RET
  687. ;
  688. DCHR:    CALL    CHROUT
  689.     PUSH    AF
  690.     LD    A,(PASS)
  691.     OR    A
  692.     JR    Z,DCHRX
  693.     LD    A,(LSTOPT)
  694.     OR    A
  695.     JR    Z,DCHRX
  696.     POP    AF
  697.     PUSH    AF
  698.     PUSH    HL
  699.     PUSH    BC
  700.     CALL    PUTLST
  701.     POP    BC
  702.     POP    HL
  703. ;
  704. DCHRX:    POP    AF
  705.     RET
  706. ;
  707. ; Multiply BC * DE, product in BC
  708. ;
  709. MULT:    PUSH    HL
  710.     PUSH    DE
  711.     LD    HL,0
  712.     LD    A,16        ; Loop count
  713. ;
  714. MULT1:    ADD    HL,HL        ; Shift partial product
  715.     EX    DE,HL
  716.     ADC    HL,HL        ; Shift partial prod with carry
  717.     EX    DE,HL
  718.     JR    NC,MULT2
  719.     ADD    HL,BC
  720.     JR    NC,MULT2
  721.     INC    DE
  722. ;
  723. MULT2:    DEC    A
  724.     JR    NZ,MULT1
  725.     LD    C,L
  726.     LD    B,H
  727.     POP    DE
  728.     POP    HL
  729.     RET
  730. ;
  731. ; Divide DE / BC, quotient in DE remainder in BC
  732. ;
  733. DIV:    LD    A,B
  734.     OR    C
  735.     JP    Z,INVOPD    ; Can't divide by 0
  736.     PUSH    HL
  737.     LD    HL,0
  738.     LD    A,16
  739. ;
  740. DIV1:    EX    DE,HL
  741.     ADD    HL,HL
  742.     EX    DE,HL
  743.     ADC    HL,HL
  744.     INC    DE
  745.     OR    A
  746.     SBC    HL,BC
  747.     JR    NC,DIV2
  748.     DEC    DE
  749.     ADD    HL,BC
  750. ;
  751. DIV2:    DEC    A
  752.     JR    NZ,DIV1
  753.     LD    C,L
  754.     LD    B,H
  755.     POP    HL
  756.     RET
  757. ;
  758. KBSCAN:    PUSH    HL
  759.     PUSH    DE
  760.     PUSH    BC
  761.     LD    E,0FFH
  762.     LD    C,6
  763.     CALL    BDOS
  764.     AND    7FH
  765.     JR    SYSRET
  766. ;
  767. ROTATE:    RLCA
  768.     RLCA
  769.     RLCA
  770.     RLCA
  771.     RET
  772. ;
  773. ; Skip to next field in line buffer
  774. ;
  775. NEXTF:    LD    A,(HL)
  776.     CP    CTRLZ
  777.     RET    Z
  778.     CP    ' '
  779.     JR    Z,NEXTF1
  780.     CP    TAB
  781.     RET    NZ
  782. ;
  783. NEXTF1:    INC    HL
  784.     JR    NEXTF
  785. ;
  786. ; Skip to next operand in line buffer
  787. ;
  788. NEXTOP:    LD    A,(HL)
  789.     CP    CTRLZ
  790.     RET    Z
  791.     CP    ' '
  792.     JR    Z,NEXTO1
  793.     CP    TAB
  794.     JR    Z,NEXTO1
  795.     CP    ','
  796.     RET    NZ
  797. ;
  798. NEXTO1:    INC    HL
  799.     JR    NEXTOP
  800. ;
  801. UPERCT:    LD    A,(MAXERR)
  802.     PUSH    BC
  803.     LD    B,A
  804.     LD    A,(ERRCNT)
  805.     INC    A
  806.     CP    B
  807.     POP    BC
  808.     JR    NC,UPERC1
  809.     LD    (ERRCNT),A
  810.     RET
  811. ;
  812. UPERC1:    LD    HL,AWCRAP
  813.     CALL    PRINT
  814.     JP    EXIT
  815. ;
  816. PSUDTB:    DEFW    PSEQU
  817.     DEFW    PSORG
  818.     DEFW    PSDFB
  819.     DEFW    PSDFW
  820.     DEFW    PSDFS
  821.     DEFW    PSEND
  822.     DEFW    PSINV
  823.     DEFW    PSINV
  824. ;
  825. PSINV:    SCF            ; Invalid pseudo-op
  826. ;
  827. PSEND:    RET            ; Ignore end pseudo-op
  828. ;
  829. PSDFB:    LD    IY,OCLEN
  830.     LD    IX,OPCODE
  831. ;
  832. PSDB0:    LD    A,(HL)
  833.     CP    QUOTE
  834.     JR    Z,PSDB3        ; Go if ASCII literal
  835. ;
  836. PSDB1:    CALL    EXP
  837.     INC    (IY+0)
  838.     LD    A,(NUMBER)
  839.     LD    (IX+0),A
  840.     INC    IX
  841. ;
  842. PSDB2:    LD    A,(HL)
  843.     INC    HL
  844.     CP    ','
  845.     JR    Z,PSDB0
  846.     OR    A
  847.     RET
  848. ;
  849. PSDB3:    INC    HL
  850.     INC    HL
  851.     LD    A,(HL)
  852.     DEC    HL
  853.     DEC    HL
  854.     CP    QUOTE
  855.     JR    Z,PSDB1        ; Go if single ascii literal
  856.     INC    HL        ; Else assume it's a string
  857. ;
  858. PSDB4:    LD    A,(HL)
  859.     INC    HL
  860.     CP    CR
  861.     RET    Z
  862.     CP    QUOTE
  863.     JR    Z,PSDB2
  864.     LD    (IX+0),A
  865.     INC    IX
  866.     INC    (IY+0)
  867.     JR    PSDB4
  868. ;
  869. PSDFS:    CALL    EXP
  870.     PUSH    HL
  871.     LD    HL,(PC)
  872.     LD    BC,(NUMBER)
  873.     ADD    HL,BC
  874.     LD    (PC),HL
  875.     POP    HL
  876.     JR    PSORGX
  877. ;
  878. PSORG:    CALL    EXP
  879.     LD    BC,(NUMBER)
  880.     LD    (PC),BC
  881. ;
  882. PSORGX:    LD    A,(HEXFLG)
  883.     OR    40H        ; Set bit 6
  884.     LD    (HEXFLG),A    ; Flag skip in hex record
  885.     XOR    A
  886.     LD    (OCLEN),A
  887.     RET
  888. ;
  889. PSDFW:    CALL    EXP
  890.     LD    BC,(NUMBER)
  891.     LD    A,C
  892.     LD    C,B        ; Reverse order of bytes
  893.     LD    B,A
  894.     LD    (OPCODE),BC
  895.     LD    A,(OCLEN)
  896.     ADD    A,2
  897.     LD    (OCLEN),A
  898.     OR    A
  899.     RET
  900. ;
  901. ; EQU - enter label in symbol table
  902. ;
  903. PSEQU:    LD    A,(PASS)    ; On first pass only
  904.     OR    A
  905.     RET    NZ
  906.     CALL    EXP
  907.     PUSH    HL
  908.     LD    HL,(SYMEND)    ; Better be last symbol entered
  909.     DEC    HL
  910.     DEC    HL
  911.     LD    BC,(NUMBER)
  912.     LD    (HL),C
  913.     INC    HL
  914.     LD    (HL),B
  915.     POP    HL
  916.     OR    A
  917.     RET
  918. ;
  919. MAXTYP:    DEFB    15
  920. ;
  921. GRPTBL:    DEFW    GROUP1        ; Single byte, no options
  922.     DEFW    GROUP2        ; Jumps
  923.     DEFW    GROUP3        ; Call
  924.     DEFW    GROUP4        ; Clr cpl
  925.     DEFW    GROUP5        ; En dis
  926.     DEFW    GROUP6        ; Sel
  927.     DEFW    GROUP7        ; Strt
  928.     DEFW    GROUP8        ; Mov
  929.     DEFW    GROUP9        ; Dec inc
  930.     DEFW    GROUPA        ; Movd
  931.     DEFW    GROUPB        ; Add addc anl anld orl orld xrl
  932.     DEFW    GROUPC        ; In
  933.     DEFW    GROUPD        ; Outl
  934.     DEFW    GROUPE        ; Movx
  935.     DEFW    GROUPF        ; Xch xchd
  936. ;
  937. ; Group 1 - single byte opcodes, no options
  938. ;
  939. GROUP1:    LD    A,1
  940.     LD    (OCLEN),A
  941.     OR    A
  942.     RET
  943. ;
  944. ; Group 2 - double byte opcodes, second byte = address (jumps)
  945. ;
  946. GROUP2:    LD    A,2
  947.     LD    (OCLEN),A
  948.     LD    A,(OPCODE)    ; Get base opcode
  949.     AND    0FH
  950.     CP    2
  951.     JR    Z,GRP2A        ; Go if jbx
  952.     CP    6
  953.     JR    Z,GRP2A        ; Go if conditional jumps
  954.     CP    4
  955.     JR    Z,GRP2B        ; Go if jmp or call
  956.     LD    A,(HL)        ; Else djnz, get register
  957.     CP    'R'
  958.     JP    NZ,INVOPD    ; Go if not valid
  959.     INC    HL
  960.     LD    A,(HL)
  961.     INC    HL
  962.     SUB    30H
  963.     JP    C,INVOPD
  964.     CP    8
  965.     JP    NC,INVOPD
  966.     LD    B,A
  967.     LD    A,(OPCODE)
  968.     OR    B
  969.     LD    (OPCODE),A    ; Set register in opcode
  970.     LD    A,(HL)
  971.     CP    ','
  972.     JP    NZ,INVOPD
  973.     INC    HL
  974. ;
  975. GRP2A:    CALL    EXP        ; Conditional jumps & jBX
  976.     LD    A,(NUMBER+1)
  977.     LD    B,A
  978.     LD    A,(PC+1)
  979.     CP    B
  980.     JR    Z,GRP2X
  981.     LD    A,4
  982.     LD    (ERRFLG),A
  983.     SCF
  984.     RET
  985. ;
  986. GRP2X:    LD    A,(NUMBER)
  987.     LD    (OPCODE+1),A
  988.     OR    A
  989.     RET
  990. ;
  991. GRP2B:    CALL    EXP        ; Jump
  992.     LD    A,(NUMBER+1)
  993.     AND    7
  994.     RRCA
  995.     RRCA
  996.     RRCA
  997.     OR    4
  998.     LD    (OPCODE),A
  999.     JR    GRP2X
  1000. ;
  1001. ; Group 3 - calls, second byte = A0 - A7
  1002. ;
  1003. GROUP3:    LD    A,2
  1004.     LD    (OCLEN),A
  1005.     CALL    EXP
  1006.     LD    A,(NUMBER)
  1007.     LD    (OPCODE+1),A
  1008.     LD    A,(NUMBER+1)
  1009.     AND    7
  1010.     RRCA
  1011.     RRCA
  1012.     RRCA
  1013.     OR    14H
  1014.     LD    (OPCODE),A
  1015.     RET
  1016. ;
  1017. ; Group 4 - CLR, CPL
  1018. ;
  1019. GROUP4:    LD    A,1
  1020.     LD    (OCLEN),A
  1021.     LD    A,(HL)        ; Get operand
  1022.     CP    'A'        ; Done if CLR/CPL A
  1023.     RET    Z
  1024.     LD    B,70H
  1025.     CP    'C'
  1026.     JR    Z,GRP4A        ; Go if carry flag
  1027.     CP    'F'
  1028.     JP    NZ,INVOPD    ; Go if invalid operand
  1029.     LD    B,5EH
  1030.     INC    HL
  1031.     LD    A,(HL)        ; Better be '0' or '1'
  1032.     AND    1
  1033.     JR    Z,GRP4A
  1034.     LD    B,7EH
  1035. GRP4A:    LD    A,(OPCODE)    ; Modify opcode for carry flag
  1036.     ADD    A,B
  1037.     LD    (OPCODE),A
  1038.     RET
  1039. ;
  1040. ; EN DIS
  1041. ;
  1042. GROUP5:    LD    A,1
  1043.     LD    (OCLEN),A
  1044.     LD    A,(HL)        ; Get option
  1045.     CP    'I'
  1046.     RET    Z
  1047.     CP    'T'
  1048.     JP    NZ,INVOPD
  1049.     LD    B,20H
  1050.     JR    GRP4A
  1051. ;
  1052. ; SEL
  1053. ;
  1054. GROUP6:    LD    A,1
  1055.     LD    (OCLEN),A
  1056.     LD    B,0
  1057.     LD    A,(HL)        ; Get operand
  1058.     CP    'R'
  1059.     JR    Z,GRP6A
  1060.     CP    'M'
  1061.     JP    NZ,INVOPD
  1062.     INC    B
  1063.     INC    B
  1064. ;
  1065. GRP6A:    INC    HL
  1066.     LD    A,(HL)
  1067.     CP    'B'
  1068.     JP    NZ,INVOPD
  1069.     INC    HL
  1070.     LD    A,(HL)
  1071.     AND    1
  1072.     JR    Z,GRP6B
  1073.     INC    B
  1074. ;
  1075. GRP6B:    LD    A,B
  1076.     CALL    ROTATE
  1077.     LD    B,A
  1078.     LD    A,(OPCODE)
  1079.     ADD    A,B
  1080.     LD    (OPCODE),A
  1081.     RET
  1082. ;
  1083. ; STRT
  1084. ;
  1085. GROUP7:    LD    A,1
  1086.     LD    (OCLEN),A
  1087.     LD    A,(HL)
  1088.     CP    'C'
  1089.     RET    Z
  1090.     CP    'T'
  1091.     JP    NZ,INVOPD
  1092.     LD    A,(OPCODE)
  1093.     OR    10H
  1094.     LD    (OPCODE),A
  1095.     RET
  1096. ;
  1097. ; MOV
  1098. ;
  1099. GROUP8:    LD    A,1
  1100.     LD    (OCLEN),A
  1101.     LD    A,(HL)
  1102.     INC    HL
  1103.     CP    'A'
  1104.     JR    NZ,GRP8B    ; Go if not <MOV,A???
  1105.     LD    A,(HL)
  1106.     CP    ','
  1107.     JP    NZ,INVOPD
  1108.     INC    HL
  1109.     LD    A,(HL)
  1110.     CP    '#'
  1111.     JR    NZ,GRP8A    ; Go if not immediate data
  1112.     INC    HL
  1113.     CALL    EXP        ; Get immed data
  1114.     LD    A,2
  1115.     LD    (OCLEN),A
  1116.     LD    A,(NUMBER)
  1117.     LD    (OPCODE+1),A
  1118.     OR    A
  1119.     RET
  1120. ;
  1121. GRP8A:    LD    A,(HL)        ; Get operand
  1122.     INC    HL
  1123.     LD    B,42H
  1124.     CP    'T'
  1125.     JR    Z,GRP8AX
  1126.     LD    B,0C7H
  1127.     CP    'P'
  1128.     JR    Z,GRP8AX
  1129.     CP    'R'
  1130.     JR    Z,GRP8A1
  1131.     CP    '@'
  1132.     JP    NZ,INVOPD
  1133.     LD    B,0F0H
  1134.     LD    A,(HL)
  1135.     CP    'R'
  1136.     JP    NZ,INVOPD
  1137.     INC    HL
  1138.     LD    A,(HL)
  1139.     CP    '0'
  1140.     JR    Z,GRP8AX
  1141.     INC    B
  1142.     CP    '1'
  1143.     JP    NZ,INVOPD
  1144. GRP8AX:    LD    A,B
  1145.     LD    (OPCODE),A
  1146.     OR    A
  1147.     RET
  1148. ;
  1149. GRP8A1:    LD    A,(HL)
  1150.     SUB    '0'
  1151.     JP    C,INVOPD
  1152.     CP    8
  1153.     JP    NC,INVOPD
  1154.     OR    0F8H
  1155.     LD    B,A
  1156.     JR    GRP8AX
  1157. ;
  1158. GRP8B:    LD    B,0D7H
  1159.     CP    'P'
  1160.     JR    Z,GRP8AX
  1161.     LD    B,62H
  1162.     CP    'T'
  1163.     JR    Z,GRP8AX
  1164.     LD    B,0A0H        ; Base for mov r,x or mov @r,x
  1165.     CP    'R'
  1166.     JR    Z,GRP8B2
  1167.     CP    '@'
  1168.     JP    NZ,INVOPD
  1169.     LD    A,(HL)
  1170.     CP    'R'
  1171.     JP    NZ,INVOPD
  1172.     INC    HL
  1173.     LD    A,(HL)
  1174.     SUB    '0'
  1175.     JP    C,INVOPD
  1176.     CP    8
  1177.     JP    NC,INVOPD
  1178.     LD    C,A
  1179.     INC    HL
  1180.     LD    A,(HL)
  1181.     CP    ','
  1182.     JP    NZ,INVOPD
  1183.     INC    HL
  1184.     LD    A,(HL)
  1185.     INC    HL
  1186.     CP    '#'
  1187.     JR    Z,GRP8B1
  1188.     CP    'A'
  1189.     JP    NZ,INVOPD
  1190.     LD    A,C
  1191.     CP    2
  1192.     JP    NC,INVOPD
  1193.     OR    B
  1194.     LD    B,A
  1195. ;
  1196. GRP8BX:    LD    A,B
  1197.     LD    (OPCODE),A
  1198.     OR    A
  1199.     RET
  1200. ;
  1201. GRP8B1:    LD    A,0B0H
  1202.     OR    C
  1203.     LD    B,A
  1204.     CALL    EXP
  1205.     LD    A,(NUMBER)
  1206.     LD    (OPCODE+1),A
  1207.     LD    A,2
  1208.     LD    (OCLEN),A
  1209.     JR    GRP8BX
  1210. ;
  1211. GRP8B2:    LD    A,(HL)        ; Get register
  1212.     SUB    30H
  1213.     JP    C,INVOPD
  1214.     CP    8
  1215.     JP    NC,INVOPD
  1216.     LD    C,A        ; Save register number
  1217.     INC    HL
  1218.     LD    A,(HL)
  1219.     CP    ','
  1220.     JP    NZ,INVOPD
  1221.     INC    HL
  1222.     LD    A,(HL)
  1223.     CP    '#'
  1224.     JR    Z,GRP8B3    ; Go if MOV RX,#data
  1225.     LD    A,0A8H
  1226.     OR    C
  1227.     LD    (OPCODE),A
  1228.     RET
  1229. ;
  1230. GRP8B3:    INC    HL
  1231.     LD    A,2
  1232.     LD    (OCLEN),A
  1233.     LD    A,0B8H
  1234.     OR    C
  1235.     LD    (OPCODE),A
  1236.     CALL    EXP
  1237.     LD    A,(NUMBER)
  1238.     LD    (OPCODE+1),A
  1239.     OR    A
  1240.     RET
  1241. ;
  1242. ; DEC INC
  1243. ;
  1244. GROUP9:    LD    A,1
  1245.     LD    (OCLEN),A
  1246.     LD    A,(OPCODE)
  1247.     AND    10H
  1248.     JR    Z,GRP9B        ; Go if DEC
  1249.     LD    A,(HL)
  1250.     CP    'A'
  1251.     RET    Z
  1252.     CP    '@'
  1253.     JR    Z,GRP9A
  1254.     CP    'R'
  1255.     JP    NZ,INVOPD
  1256.     LD    B,18H
  1257.     JR    GRP9C
  1258. ;
  1259. GRP9A:    INC    HL
  1260.     LD    A,(HL)
  1261.     CP    'R'
  1262.     JP    NZ,INVOPD
  1263.     LD    B,10H
  1264.     INC    HL
  1265.     LD    A,(HL)
  1266.     SUB    30H
  1267.     JP    C,INVOPD
  1268.     CP    2
  1269.     JR    GRP9D
  1270. ;
  1271. GRP9B:    LD    A,(HL)        ; Get operand
  1272.     CP    'A'
  1273.     RET    Z
  1274.     CP    'R'
  1275.     JP    NZ,INVOPD
  1276.     LD    B,0C8H
  1277. ;
  1278. GRP9C:    INC    HL
  1279.     LD    A,(HL)
  1280.     SUB    30H
  1281.     JP    C,INVOPD
  1282.     CP    8
  1283. ;
  1284. GRP9D:    JP    NC,INVOPD
  1285.     OR    B
  1286.     LD    (OPCODE),A
  1287.     RET
  1288. ;
  1289. ; MOVD
  1290. ;
  1291. GROUPA:    LD    A,1
  1292.     LD    (OCLEN),A
  1293.     LD    B,3CH
  1294.     LD    A,(HL)
  1295.     CP    'A'
  1296.     JR    Z,GRPAA        ; Go if MOVD,A port
  1297. ;
  1298. GRPAX:    CP    'P'
  1299.     JP    NZ,INVOPD
  1300.     INC    HL
  1301.     LD    A,(HL)
  1302.     SUB    30H
  1303.     JP    C,INVOPD
  1304.     CP    2
  1305.     JP    NC,INVOPD
  1306.     OR    B
  1307.     LD    (OPCODE),A
  1308.     RET
  1309. ;
  1310. GRPAA:    LD    B,0CH
  1311.     INC    HL
  1312.     LD    A,(HL)
  1313.     CP    ','
  1314.     JP    NZ,INVOPD
  1315.     INC    HL
  1316.     LD    A,(HL)
  1317.     JR    GRPAX
  1318. ;
  1319. ; ADD ADDC ANL ANLD CRL ORLD XRL
  1320. ;
  1321. GROUPB:    LD    A,1
  1322.     LD    (OCLEN),A
  1323.     LD    A,(OPCODE)
  1324.     CP    53H
  1325.     JR    Z,GRPBE        ; Go if ANL (exceptions)
  1326.     CP    43H
  1327.     JR    Z,GRPBE        ; Go if ORL (exceptions)
  1328. ;
  1329. GRPBA:    LD    A,(HL)
  1330.     INC    HL
  1331.     CP    'A'
  1332.     JP    NZ,INVOPD
  1333.     LD    A,(HL)
  1334.     INC    HL
  1335.     CP    ','
  1336.     JP    NZ,INVOPD
  1337.     LD    A,(HL)
  1338.     INC    HL
  1339.     CP    '#'
  1340.     JR    Z,GRPBC        ; Go if immdeiate data
  1341.     CP    'R'
  1342.     LD    C,8
  1343.     JR    Z,GRPBB        ; Go if OP A,RX
  1344.     CP    '@'
  1345.     JP    NZ,INVOPD
  1346.     LD    C,2
  1347.     LD    A,(HL)
  1348.     INC    HL
  1349.     CP    'R'
  1350.     JP    NZ,INVOPD
  1351. ;
  1352. GRPBB:    LD    A,(HL)
  1353.     SUB    30H
  1354.     JP    C,INVOPD
  1355.     CP    C
  1356.     JP    NC,INVOPD
  1357.     LD    B,A
  1358.     LD    A,(OPCODE)
  1359.     AND    0E0H
  1360.     JR    NZ,GRPBB1
  1361.     LD    A,(OPCODE)
  1362.     AND    0F0H
  1363.     ADD    A,60H
  1364.     LD    (OPCODE),A
  1365. ;
  1366. GRPBB1:    LD    A,(OPCODE)
  1367.     BIT    3,C
  1368.     JR    Z,GRPBB2
  1369.     OR    8
  1370. ;
  1371. GRPBB2:    OR    B
  1372.     LD    (OPCODE),A
  1373.     RET
  1374. ;
  1375. GRPBC:    CALL    EXP
  1376.     LD    A,(NUMBER)
  1377.     LD    (OPCODE+1),A
  1378.     LD    A,2
  1379.     LD    (OCLEN),A
  1380.     OR    A
  1381.     RET
  1382. ;
  1383. GRPBE:    LD    A,(HL)
  1384.     CP    'A'
  1385.     JR    Z,GRPBA        ; Go if not an exception
  1386.     CP    'B'        ; Else ANL,ORL
  1387.     JR    Z,GRBUS        ; Go if BUS, # data
  1388.     CP    'P'
  1389.     JP    NZ,INVOPD
  1390.     INC    HL
  1391.     LD    A,(HL)
  1392.     SUB    31H
  1393.     JP    C,INVOPD
  1394.     CP    2
  1395.     JP    NC,INVOPD
  1396.     INC    A
  1397.     LD    B,A
  1398.     LD    A,(OPCODE)
  1399.     BIT    7,A
  1400.     JR    Z,GRBUS1    ; Go if ANL ORL
  1401.     OR    B
  1402.     LD    (OPCODE),A    ; Else ANLD ORLD
  1403.     RET
  1404. ;
  1405. GRBUS:    INC    HL
  1406.     INC    HL
  1407.     LD    B,0
  1408. ;
  1409. GRBUS1:    LD    A,2
  1410.     LD    (OCLEN),A
  1411.     INC    HL
  1412.     INC    HL
  1413.     LD    A,(HL)
  1414.     CP    '#'
  1415.     JP    NZ,INVOPD
  1416.     INC    HL
  1417.     PUSH    BC
  1418.     CALL    EXP
  1419.     POP    BC
  1420.     LD    A,(NUMBER)
  1421.     LD    (OPCODE+1),A
  1422.     LD    A,(OPCODE)
  1423.     ADD    A,45H
  1424.     OR    B
  1425.     LD    (OPCODE),A
  1426.     RET
  1427. ;
  1428. ; IN
  1429. ;
  1430. GROUPC:    LD    A,1
  1431.     LD    (OCLEN),A
  1432.     LD    A,(HL)
  1433.     CP    'A'
  1434.     JP    NZ,INVOPD
  1435.     INC    HL
  1436.     LD    A,(HL)
  1437.     CP    ','
  1438.     JP    NZ,INVOPD
  1439.     INC    HL
  1440.     LD    A,(HL)
  1441.     CP    'P'
  1442.     JP    NZ,INVOPD
  1443.     INC    HL
  1444.     LD    A,(HL)
  1445.     SUB    31H
  1446.     JP    C,INVOPD
  1447.     CP    2
  1448.     JP    NC,INVOPD
  1449.     INC    A
  1450.     OR    8
  1451.     LD    (OPCODE),A
  1452.     RET
  1453. ;
  1454. ; OUTL
  1455. ;
  1456. GROUPD:    LD    A,1
  1457.     LD    (OCLEN),A
  1458.     LD    A,(HL)
  1459.     CP    'B'
  1460.     RET    Z
  1461.     CP    'P'
  1462.     JP    NZ,INVOPD
  1463.     INC    HL
  1464.     LD    A,(HL)
  1465.     SUB    31H
  1466.     JP    C,INVOPD
  1467.     CP    2
  1468.     JP    NC,INVOPD
  1469.     INC    A
  1470.     OR    38H
  1471.     LD    (OPCODE),A
  1472.     RET
  1473. ;
  1474. ; MOVX
  1475. ;
  1476. GROUPE:    LD    A,1
  1477.     LD    (OCLEN),A
  1478.     LD    A,(HL)
  1479.     INC    HL
  1480.     CP    'A'
  1481.     JR    Z,GRPEA        ; Go if movx a,@rx
  1482.     LD    B,90H
  1483.     CP    '@'
  1484.     JP    NZ,INVOPD
  1485.     LD    A,(HL)
  1486.     CP    'R'
  1487.     JP    NZ,INVOPD
  1488. ;
  1489. GRPEX:    INC    HL
  1490.     LD    A,(HL)
  1491.     SUB    30H
  1492.     JP    C,INVOPD
  1493.     CP    2
  1494.     JP    NC,INVOPD
  1495.     OR    B
  1496.     LD    (OPCODE),A
  1497.     RET
  1498. ;
  1499. GRPEA:    LD    A,(HL)
  1500.     CP    ','
  1501.     JR    NZ,INVOPD
  1502.     INC    HL
  1503.     LD    A,(HL)
  1504.     CP    '@'
  1505.     JR    NZ,INVOPD
  1506.     INC    HL
  1507.     LD    A,(HL)
  1508.     CP    'R'
  1509.     JR    NZ,INVOPD
  1510.     LD    B,80H
  1511.     JR    GRPEX
  1512. ;
  1513. ; XCH XCHD
  1514. ;
  1515. GROUPF:    LD    A,1
  1516.     LD    (OCLEN),A
  1517.     LD    BC,28H SHL 8 OR    8
  1518.     LD    A,(HL)
  1519.     CP    'A'
  1520.     JR    NZ,INVOPD
  1521.     INC    HL
  1522.     LD    A,(HL)
  1523.     INC    HL
  1524.     CP    ','
  1525.     JR    NZ,INVOPD
  1526.     LD    A,(OPCODE)
  1527.     CP    30H
  1528.     JR    Z,GRPFC        ; Go if XCHD
  1529.     LD    A,(HL)
  1530.     CP    '@'
  1531.     JR    NZ,GRPFB
  1532.     LD    BC,20H SHL 8 OR    2
  1533. ;
  1534. GRPFA:    INC    HL
  1535.     LD    A,(HL)
  1536.  
  1537. GRPFB:    CP    'R'
  1538.     JR    NZ,INVOPD
  1539.     INC    HL
  1540.     LD    A,(HL)
  1541.     SUB    30H
  1542.     JR    C,INVOPD
  1543.     CP    C
  1544.     JR    NC,INVOPD
  1545.     OR    B
  1546.     LD    (OPCODE),A
  1547.     RET
  1548. ;
  1549. GRPFC:    LD    BC,30H SHL 8 OR    2
  1550.     LD    A,(HL)
  1551.     CP    '@'
  1552.     JR    Z,GRPFA
  1553. ;
  1554. INVOPD:    XOR    A
  1555.     LD    (OCLEN),A
  1556.     LD    A,2
  1557.     LD    (ERRFLG),A
  1558.     SCF
  1559.     RET
  1560. ;
  1561. ; Expression evaluation, on entry HL => text
  1562. ;
  1563. EXP:    LD    BC,0
  1564.     LD    (EXPOP),BC    ; Clear operation and flags
  1565.     LD    (NUMBER),BC    ; Clear temp result
  1566.     LD    (TMPVAL),BC
  1567.     DEC    HL
  1568. ;
  1569. EXPNXT:    INC    HL
  1570.     LD    A,(HL)
  1571.     CP    ' '
  1572.     JR    Z,EXPNXT    ; Skip spaces
  1573.     CP    ';'        ; Done if comment
  1574.     RET    Z
  1575.     CP    '$'
  1576.     JP    Z,EXPC        ; Go if PC reference
  1577.     CP    '<'
  1578.     JR    Z,EXPO
  1579.     CP    '>'
  1580.     JR    Z,EXPO
  1581.     CP    CARAT
  1582.     JR    Z,EXPO
  1583.     CP    '0'
  1584.     JR    C,EXPO        ; Go if operator
  1585.     CP    '9'+1
  1586.     JP    C,EXPN        ; Go if decimal
  1587.     PUSH    HL
  1588.     CALL    FNDSYM        ; Else is a symbol
  1589.     JR    Z,EXPNX1    ; Go if found
  1590.     LD    A,(PASS)
  1591.     OR    A
  1592.     JR    Z,EXPNX1    ; Go if pass 1
  1593.     LD    A,5
  1594.     LD    (ERRFLG),A    ; Set undefined symbol error
  1595. ;
  1596. EXPNX1:    LD    C,(HL)        ; Get it's value
  1597.     INC    HL
  1598.     LD    B,(HL)
  1599.     LD    (NUMBER),BC
  1600.     DEC    HL        ; Point back to byte count
  1601. ;
  1602. EXPNX2:    DEC    HL
  1603.     LD    A,(HL)
  1604.     AND    7FH
  1605.     CP    7
  1606.     JR    NC,EXPNX2
  1607.     BIT    7,(HL)        ; Test for multiple def
  1608.     POP    HL
  1609.     JR    Z,EXPNX3
  1610.     LD    A,3
  1611.     LD    (ERRFLG),A
  1612. ;
  1613. EXPNX3:    CALL    SKPLBL
  1614.     DEC    HL
  1615.     JR    EXPDO
  1616. ;
  1617. EXPO:    CP    ','
  1618.     RET    Z
  1619.     INC    HL
  1620.     CP    '+'
  1621.     JR    Z,EXAD        ; Go if addition
  1622.     CP    '-'
  1623.     JR    Z,EXSB        ; Go if subtraction
  1624.     CP    '*'
  1625.     JR    Z,EXML        ; Go if multiplication
  1626.     CP    '/'
  1627.     JR    Z,EXDV        ; Go if division
  1628.     CP    '&'
  1629.     JR    Z,EXAND        ; Go if logical and
  1630.     CP    '%'
  1631.     JR    Z,EXOR        ; Go if logical or
  1632.     CP    '!'
  1633.     JR    Z,EXEOR        ; Go if exclusive or
  1634.     CP    '<'
  1635.     JR    Z,EXSHL        ; Go if shift left
  1636.     CP    '>'
  1637.     JR    Z,EXSHR        ; Go if shift right
  1638.     CP    CARAT
  1639.     JR    Z,EXCRT        ; Go if control char def
  1640.     CP    QUOTE
  1641.     RET    NZ        ; Go if not ascii literal
  1642.     LD    A,(HL)
  1643.     LD    (NUMBER),A    ; Set ascii literal
  1644.     INC    HL
  1645.     LD    A,(HL)
  1646.     CP    QUOTE
  1647.     JR    Z,EXPDO        ; Go if ascii terminator
  1648.     DEC    HL        ; Else point back
  1649.     JR    EXPDO
  1650. ;
  1651. EXCRT:    LD    A,(HL)
  1652.     SUB    40H
  1653.     LD    (NUMBER),A
  1654.     JP    EXPNXT
  1655. ;
  1656. EXAD:    XOR    A
  1657.     JR    EXOPN
  1658. ;
  1659. EXSB:    LD    A,1
  1660.     JR    EXOPN
  1661. ;
  1662. EXML:    LD    A,2
  1663.     JR    EXOPN
  1664. ;
  1665. EXDV:    LD    A,3
  1666.     JR    EXOPN
  1667. ;
  1668. EXAND:    LD    A,4
  1669.     JR    EXOPN
  1670. ;
  1671. EXOR:    LD    A,5
  1672.     JR    EXOPN
  1673. ;
  1674. EXEOR:    LD    A,6
  1675.     JR    EXOPN
  1676. ;
  1677. EXSHL:    LD    A,7
  1678.     JR    EXOPN
  1679. ;
  1680. EXSHR:    LD    A,8
  1681. ;
  1682. EXOPN:    LD    (EXPOP),A    ; Set operator flag
  1683.     LD    BC,(NUMBER)
  1684.     LD    (TMPVAL),BC
  1685.     DEC    HL
  1686.     JP    EXPNXT        ; And get next
  1687. ;
  1688. EXPC:    LD    BC,(PC)
  1689.     LD    (NUMBER),BC    ; Set pc value and do operation
  1690. ;
  1691. EXPDO:    LD    A,(EXPOP)
  1692.     OR    A
  1693.     JR    Z,EXPDOA    ; Do addition
  1694.     DEC    A
  1695.     JR    Z,EXPDOS    ; Do subtraction
  1696.     DEC    A
  1697.     JR    Z,EXPDOM    ; Do multiplication
  1698.     DEC    A
  1699.     JR    Z,EXPDOD    ; Do division
  1700.     DEC    A
  1701.     JR    Z,EXPDAN    ; Do logical and
  1702.     DEC    A
  1703.     JR    Z,EXPDOR    ; Do logical or
  1704.     DEC    A
  1705.     JR    Z,EXPDOX    ; Do exclusive or
  1706.     DEC    A
  1707.     JR    Z,EXPDSL    ; Do shift left
  1708.     JP    EXPDSR        ; Else do shift right
  1709. ;
  1710. EXPDOX:    LD    DE,(TMPVAL)
  1711.     LD    BC,(NUMBER)
  1712.     LD    A,D
  1713.     XOR    B
  1714.     LD    B,A
  1715.     LD    A,E
  1716.     XOR    C
  1717.     LD    C,A
  1718.     LD    (NUMBER),BC
  1719.     JP    EXPNXT
  1720. ;
  1721. EXPDOD:    LD    DE,(TMPVAL)
  1722.     LD    BC,(NUMBER)
  1723.     CALL    DIV
  1724.     LD    (NUMBER),DE
  1725.     JP    EXPNXT
  1726. ;
  1727. EXPDOA:    PUSH    HL
  1728.     LD    HL,(TMPVAL)
  1729.     LD    BC,(NUMBER)
  1730.     ADD    HL,BC
  1731.     JR    EXPDX1
  1732. ;
  1733. EXPDOS:    PUSH    HL
  1734.     LD    HL,(TMPVAL)
  1735.     LD    BC,(NUMBER)
  1736.     OR    A
  1737.     SBC    HL,BC
  1738. ;
  1739. EXPDX1:    LD    (NUMBER),HL
  1740.     POP    HL
  1741.     JP    EXPNXT
  1742. ;
  1743. EXPDOM:    LD    DE,(TMPVAL)
  1744.     LD    BC,(NUMBER)
  1745.     CALL    MULT
  1746. ;
  1747. EXPDX2:    LD    (NUMBER),BC
  1748.     JP    EXPNXT
  1749. ;
  1750. EXPDAN:    LD    BC,(TMPVAL)
  1751.     LD    DE,(NUMBER)
  1752.     LD    A,B
  1753.     AND    D
  1754.     LD    B,A
  1755.     LD    A,C
  1756.     AND    E
  1757.     LD    C,A
  1758.     JR    EXPDX2
  1759. ;
  1760. EXPDOR:    LD    BC,(TMPVAL)
  1761.     LD    DE,(NUMBER)
  1762.     LD    A,B
  1763.     OR    D
  1764.     LD    B,A
  1765.     LD    A,C
  1766.     OR    E
  1767.     LD    C,A
  1768.     JR    EXPDX2
  1769. ;
  1770. EXPDSL:    LD    DE,(TMPVAL)
  1771.     LD    A,(NUMBER)
  1772.     AND    0FH        ; No more than 15 counts
  1773.     JR    Z,EXPSXX    ; Done if no shift
  1774.     LD    B,A        ; (else why shift it?)
  1775. EXPSL1:    SLA    E        ; Shift 16 bits left by count
  1776.     RL    D
  1777.     DJNZ    EXPSL1
  1778. ;
  1779. EXPSSX:    LD    (NUMBER),DE
  1780. ;
  1781. EXPSXX:    JP    EXPNXT
  1782. ;
  1783. EXPDSR:    LD    DE,(TMPVAL)
  1784.     LD    A,(NUMBER)
  1785.     AND    0FH
  1786.     JR    Z,EXPSXX
  1787.     LD    B,A
  1788. ;
  1789. EXPSR1:    SRL    D        ; Shift 16 bits right
  1790.     RR    E
  1791.     DJNZ    EXPSR1
  1792.     JR    EXPSSX
  1793. ;
  1794. EXPN:    CALL    GETINT        ; Get integer value
  1795.     BIT    0,C
  1796.     JR    NZ,EXPN1
  1797.     DEC    HL
  1798. ;
  1799. EXPN1:    DEC    HL
  1800.     JP    EXPDO
  1801. ;
  1802. GETINT:    LD    BC,0
  1803.     LD    (NUMBER),BC
  1804.     PUSH    HL
  1805. ;
  1806. GTNT1:    LD    A,(HL)
  1807.     INC    HL
  1808.     CP    '0'
  1809.     JR    C,GTNT2
  1810.     CP    '9'+1
  1811.     JR    C,GTNT1
  1812.     CP    'A'
  1813.     JR    C,GTNT2
  1814.     CP    'F'+1
  1815.     JR    C,GTNT1
  1816.     CP    'H'
  1817.     JR    NZ,GTNT2
  1818.     INC    C
  1819. ;
  1820. GTNT2:    POP    HL
  1821.     LD    A,(HL)
  1822.     INC    HL
  1823.     SUB    30H
  1824.     RET    C
  1825.     CP    10
  1826.     JR    C,GTNT3
  1827.     BIT    0,C
  1828.     RET    Z
  1829.     SUB    7
  1830.     RET    C
  1831.     CP    16
  1832.     RET    NC
  1833. ;
  1834. GTNT3:    PUSH    HL
  1835.     LD    D,0
  1836.     LD    E,A
  1837.     LD    HL,(NUMBER)
  1838.     BIT    0,C
  1839.     JR    Z,GTNT5
  1840.     LD    B,4
  1841. ;
  1842. GTNT4:    SLA    L
  1843.     RL    H        ; * 16
  1844.     DJNZ    GTNT4
  1845. ;
  1846. GTNT4A:    ADD    HL,DE
  1847.     LD    (NUMBER),HL
  1848.     JR    GTNT2
  1849. ;
  1850. GTNT5:    ADD    HL,HL
  1851.     PUSH    BC
  1852.     LD    B,H
  1853.     LD    C,L
  1854.     ADD    HL,HL
  1855.     ADD    HL,HL
  1856.     ADD    HL,BC
  1857.     POP    BC
  1858.     JR    GTNT4A
  1859. ;
  1860. ; Opcode Table
  1861. ; Each entry contains a byte count for the mnemonic, the mnemonic
  1862. ; itself, the default object code, and the group number.
  1863. ;
  1864. OPTBL:    DEFB    3,'ADD',3,11
  1865.     DEFB    4,'ADDC',13H,11
  1866.     DEFB    3,'ANL',53H,11
  1867.     DEFB    4,'ANLD',9CH,11
  1868.     DEFB    4,'CALL',14H,3
  1869.     DEFB    3,'CLR',27H,4
  1870.     DEFB    3,'CPL',37H,4
  1871.     DEFB    2,'DA',57H,1
  1872.     DEFB    3,'DEC',7,9
  1873.     DEFB    3,'DIS',15H,5
  1874.     DEFB    4,'DJNZ',0E8H,2
  1875.     DEFB    2,'EN',5,5
  1876.     DEFB    2,'IN',8,12
  1877.     DEFB    3,'INC',17H,9
  1878.     DEFB    3,'INS',8,1
  1879.     DEFB    3,'JB0',12H,2
  1880.     DEFB    3,'JB1',32H,2
  1881.     DEFB    3,'JB2',52H,2
  1882.     DEFB    3,'JB3',72H,2
  1883.     DEFB    3,'JB4',92H,2
  1884.     DEFB    3,'JB5',0B2H,2
  1885.     DEFB    3,'JB6',0D2H,2
  1886.     DEFB    3,'JB7',0F2H,2
  1887.     DEFB    2,'JC',0F6H,2
  1888.     DEFB    3,'JF0',0B6H,2
  1889.     DEFB    3,'JF1',76H,2
  1890.     DEFB    3,'JMP',4,2
  1891.     DEFB    4,'JMPP',0B3H,1
  1892.     DEFB    3,'JNC',0E6H,2
  1893.     DEFB    3,'JNI',86H,2
  1894.     DEFB    4,'JNT0',26H,2
  1895.     DEFB    4,'JNT1',46H,2
  1896.     DEFB    3,'JNZ',96H,2
  1897.     DEFB    3,'JTF',16H,2
  1898.     DEFB    3,'JT0',36H,2
  1899.     DEFB    3,'JT1',56H,2
  1900.     DEFB    2,'JZ'0C6H,2
  1901.     DEFB    3,'MOV',23H,8
  1902.     DEFB    4,'MOVD',0CH,10
  1903.     DEFB    4,'MOVP',0A3H,1
  1904.     DEFB    5,'MOVP3',0E3H,1
  1905.     DEFB    4,'MOVX',80H,14
  1906.     DEFB    3,'NOP',0,1
  1907.     DEFB    3,'ORL',43H,11
  1908.     DEFB    4,'ORLD',8CH,11
  1909.     DEFB    4,'OUTL',2,13
  1910.     DEFB    3,'RET',83H,1
  1911.     DEFB    4,'RETR',93H,1
  1912.     DEFB    2,'RL',0E7H,1
  1913.     DEFB    3,'RLC',0F7H,1
  1914.     DEFB    2,'RR',77H,1
  1915.     DEFB    3,'RRC',67H,1
  1916.     DEFB    3,'SEL',0C5H,6
  1917.     DEFB    4,'STOP',65H,1
  1918.     DEFB    4,'STRT',45H,7
  1919.     DEFB    4,'SWAP',47H,1
  1920.     DEFB    3,'XCH',20H,15
  1921.     DEFB    4,'XCHD',30H,15
  1922.     DEFB    3,'XRL',0D3H,11
  1923. ;
  1924. ; Pseudo ops
  1925. ;
  1926.     DEFB    3,'EQU',0,80H
  1927.     DEFB    3,'ORG',0,81H
  1928.     DEFB    4,'DEFB',0,82H
  1929.     DEFB    2,'DB',0,82H
  1930.     DEFB    4,'DEFW',0,83H
  1931.     DEFB    2,'DW',0,83H
  1932.     DEFB    4,'DEFS',0,84H
  1933.     DEFB    2,'DS',0,84H
  1934.     DEFB    3,'END',0,85H    ; Just in case some dork puts it in
  1935. ;
  1936.     DEFB    0        ; End of table
  1937. ;
  1938. ;
  1939. ; Write byte to hex file (at this point PC has not been updated)
  1940. ; HEXFLG:
  1941. ; Bits 0 - 4 = number of bytes in this record. Write record when
  1942. ; full (32 bytes), and append checksum (in HEXCKS).
  1943. ; Bit 5 =
  1944. ; Bit 6 = 1 if skip has occured (ie: org or defs)
  1945. ; Bit 7 = 1 if hex record has been opened, if = 0 then create header.
  1946. ;
  1947. HEXWR:    LD    A,(OCLEN)
  1948.     OR    A
  1949.     RET    Z        ; Done if nothing to output
  1950.     LD    B,A        ; Set loop count
  1951.     PUSH    HL
  1952.     PUSH    DE
  1953.     LD    DE,(PC)
  1954.     LD    (HEXPC),DE    ; Update .HEX file PC
  1955.     LD    HL,OPCODE
  1956. ;
  1957. HEXWR1:    LD    A,(HL)        ; Get data
  1958.     INC    HL
  1959.     CALL    HEXPUT        ; Put in hex buffer
  1960.     LD    DE,(HEXPC)
  1961.     INC    DE
  1962.     LD    (HEXPC),DE    ; Update file PC
  1963.     DJNZ    HEXWR1
  1964.     POP    DE
  1965.     POP    HL
  1966.     RET
  1967. ;
  1968. HEXPUT:    PUSH    HL
  1969.     PUSH    DE
  1970.     PUSH    BC
  1971.     LD    C,A        ; Save .HEX data
  1972.     LD    A,(HEXFLG)    ; Get flags
  1973.     AND    0C0H        ; Get bits 6 & 7
  1974.     CP    80H
  1975.     JR    C,HEXPTC    ; Go if new record
  1976.     JR    Z,HEXPTB    ; Go if no skip & not new record
  1977.     PUSH    BC
  1978.     CALL    HEXDMP        ; Else flush hexbfr & start new rcrd
  1979.     POP    BC
  1980. ;
  1981. HEXPTC:    LD    A,80H        ; Create new header
  1982.     LD    (HEXFLG),A    ; Flag new header
  1983.     LD    DE,(HEXPC)
  1984.     LD    (RECPC),DE    ; Set start adrs of record
  1985.     LD    A,D
  1986.     ADD    A,E
  1987.     LD    (HEXCKS),A    ; Initialize checksum
  1988.     LD    HL,HEXBFR
  1989.     LD    (HL),':'
  1990.     INC    HL
  1991.     LD    (HL),'0'    ; For now default byte count to zero
  1992.     INC    HL
  1993.     LD    (HL),'0'
  1994.     INC    HL
  1995.     LD    A,D        ; Set record pc in hex buffer
  1996.     CALL    PHEX
  1997.     LD    A,E
  1998.     CALL    PHEX
  1999.     LD    (HL),'0'    ; Set record type
  2000.     INC    HL
  2001.     LD    (HL),'0'
  2002. ;
  2003. HEXPTB:    LD    A,(HEXFLG)    ; Get offset into hexbfr
  2004.     AND    1FH
  2005.     RLCA
  2006.     ADD    A,9        ; Skip over record header
  2007.     LD    E,A
  2008.     LD    D,0
  2009.     LD    HL,HEXBFR
  2010.     ADD    HL,DE
  2011.     LD    A,(HEXCKS)    ; Update checksum
  2012.     ADD    A,C
  2013.     LD    (HEXCKS),A
  2014.     LD    A,C        ; Get data
  2015.     CALL    PHEX
  2016.     LD    A,(HEXFLG)
  2017.     INC    A
  2018.     LD    (HEXFLG),A
  2019.     AND    1FH
  2020.     CALL    Z,HEXDMP    ; Write record if full
  2021.     POP    BC
  2022.     POP    DE
  2023.     POP    HL
  2024.     RET
  2025. ;
  2026. PHEX:    PUSH    AF
  2027.     CALL    ROTATE
  2028.     CALL    PHEX1
  2029.     POP    AF
  2030. ;
  2031. PHEX1:    AND    0FH
  2032.     CP    10
  2033.     JR    C,PHEX2
  2034.     ADD    A,7
  2035. ;
  2036. PHEX2:    ADD    A,30H
  2037.     LD    (HL),A
  2038.     INC    HL
  2039.     RET
  2040. ;
  2041. ; Dump current record to hex output buffer
  2042. ;
  2043. HEXDMP:    LD    A,(HEXFLG)
  2044.     AND    1FH
  2045.     LD    B,A        ; Set loop count
  2046.     JR    NZ,HXDMP1    ; Go if not full record
  2047.     LD    B,32
  2048. ;
  2049. HXDMP1:    LD    A,(HEXCKS)    ; Update checksum
  2050.     ADD    A,B
  2051.     LD    (HEXCKS),A
  2052.     LD    A,B
  2053.     LD    HL,HEXBFR+1
  2054.     CALL    PHEX        ; Set byte count
  2055.     LD    A,B
  2056.     RLCA
  2057.     ADD    A,9        ; Add overhead
  2058.     LD    B,A
  2059.     LD    HL,HEXBFR
  2060. ;
  2061. HXDMP2:    LD    A,(HL)
  2062.     INC    HL
  2063.     PUSH    BC
  2064.     CALL    HEXOUT        ; Put in file buffer
  2065.     POP    BC
  2066.     DJNZ    HXDMP2
  2067.     LD    A,(HEXCKS)    ; Get checksum
  2068.     CPL
  2069.     INC    A
  2070.     CALL    PHEX
  2071.     DEC    HL
  2072.     DEC    HL
  2073.     LD    A,(HL)        ; Send checksum
  2074.     CALL    HEXOUT
  2075.     INC    HL
  2076.     LD    A,(HL)
  2077.     CALL    HEXOUT
  2078.     LD    A,CR
  2079.     CALL    HEXOUT
  2080.     LD    A,LF
  2081.     CALL    HEXOUT
  2082.     XOR    A
  2083.     LD    (HEXFLG),A
  2084.     RET
  2085. ;
  2086. HEXOUT:    PUSH    HL
  2087.     LD    HL,(HEXDMA)
  2088.     LD    BC,(HEXOFF)
  2089.     ADD    HL,BC
  2090.     LD    (HL),A
  2091.     POP    HL
  2092.     LD    A,(FILFLG)
  2093.     OR    2
  2094.     LD    (FILFLG),A
  2095.     INC    BC
  2096.     LD    A,C
  2097.     AND    80H
  2098.     LD    (HEXOFF),BC
  2099.     RET    Z
  2100.     LD    A,(FILFLG)
  2101.     AND    0FDH
  2102.     LD    (FILFLG),A
  2103.     CALL    FLSHEX
  2104.     LD    BC,0
  2105.     LD    (HEXOFF),BC
  2106.     RET
  2107. ;
  2108. LSTWR:    LD    A,(PASS)    ; No output during pass 1
  2109.     OR    A
  2110.     RET    Z
  2111.     LD    HL,LSTBFR
  2112.     LD    A,(OCLEN)
  2113.     OR    A
  2114.     JR    Z,LSTWR2    ; Go if no code generated
  2115.     LD    DE,(PC)
  2116.     LD    A,D
  2117.     CALL    HEXBUF        ; Put pc in list buffer
  2118.     LD    A,E
  2119.     CALL    HEXBUF
  2120.     LD    (HL),':'
  2121.     INC    HL
  2122.     LD    (HL),' '
  2123.     INC    HL
  2124.     LD    A,(OCLEN)
  2125.     CP    3
  2126.     JR    C,LSTWR0    ; Max of 2 hex in list file
  2127.     LD    A,2
  2128. ;
  2129. LSTWR0:    LD    B,A
  2130.     LD    DE,OPCODE
  2131. ;
  2132. LSTWR1:    LD    A,(DE)
  2133.     INC    DE
  2134.     CALL    HEXBUF        ; Put hex in buffer <= HL
  2135.     LD    (HL),' '
  2136.     INC    HL
  2137.     DJNZ    LSTWR1
  2138.     LD    A,(OCLEN)
  2139. ;
  2140. LSTWR2:    LD    B,13
  2141.     OR    A
  2142.     JR    Z,LSTWR3
  2143.     LD    B,4
  2144.     DEC    A
  2145.     JR    Z,LSTWR3
  2146.     LD    B,1
  2147. ;
  2148. LSTWR3:    LD    (HL),' '
  2149.     INC    HL
  2150.     DJNZ    LSTWR3
  2151.     EX    DE,HL        ; List buffer -> DE
  2152.     LD    HL,LINBFR
  2153.     LD    B,64
  2154. ;
  2155. LSTWR4:    LD    A,(HL)
  2156.     CP    TAB
  2157.     JR    NZ,LSTW4X
  2158.     INC    HL
  2159. ;
  2160. LSTW4A:    LD    A,' '
  2161.     LD    (DE),A
  2162.     INC    DE
  2163.     DEC    B
  2164.     JR    Z,LSTWR5
  2165.     LD    A,B
  2166.     AND    7
  2167.     JR    NZ,LSTW4A
  2168.     JR    LSTWR4
  2169. ;
  2170. LSTW4X:    LD    (DE),A
  2171.     INC    HL
  2172.     INC    DE
  2173.     CP    LF
  2174.     JR    Z,LSTWR5
  2175.     CP    CTRLZ
  2176.     JR    Z,LSTWR5
  2177.     DJNZ    LSTWR4
  2178. ;
  2179. LSTWR5:    EX    DE,HL
  2180.     LD    (HL),CR
  2181.     INC    HL
  2182.     LD    (HL),LF
  2183.     LD    HL,LSTBFR
  2184.     LD    A,(PAGLEN)
  2185.     OR    A
  2186.     JR    Z,LSTWR6
  2187.     LD    A,(CURLIN)
  2188.     INC    A
  2189.     LD    (CURLIN),A
  2190. ;
  2191. LSTWR6:    LD    A,(HL)
  2192.     OR    A
  2193.     RET    Z
  2194.     INC    HL
  2195.     PUSH    AF
  2196.     CALL    PUTLST
  2197.     POP    AF
  2198.     CP    LF
  2199.     JR    Z,LSTWR7
  2200.     CP    CTRLZ
  2201.     JR    NZ,LSTWR6
  2202.     RET
  2203. ;
  2204. LSTWR7:    LD    A,(CURLIN)
  2205.     OR    A
  2206.     RET    Z
  2207.     LD    B,A
  2208.     LD    A,(PAGLEN+1)    ; Get max printed line
  2209.     CP    B
  2210.     RET    NZ
  2211.     XOR    A
  2212.     LD    (CURLIN),A    ; Clear line counter
  2213.     LD    A,(PAGLEN)
  2214.     SUB    B
  2215.     RET    Z
  2216.     LD    B,A
  2217. ;
  2218. LSTWR8:    LD    A,LF
  2219.     PUSH    BC
  2220.     CALL    PUTLST
  2221.     POP    BC
  2222.     DJNZ    LSTWR8
  2223.     RET
  2224. ;
  2225. ; Write byte to list file
  2226. ;
  2227. PUTLST:    PUSH    HL
  2228.     LD    HL,(LSTDMA)
  2229.     LD    BC,(LSTOFF)
  2230.     ADD    HL,BC
  2231.     LD    (HL),A
  2232.     POP    HL
  2233.     LD    A,(FILFLG)
  2234.     OR    8
  2235.     LD    (FILFLG),A
  2236.     INC    BC
  2237.     LD    A,C
  2238.     AND    80H
  2239.     LD    (LSTOFF),BC
  2240.     RET    Z
  2241.     LD    A,(FILFLG)
  2242.     AND    0F7H
  2243.     LD    (FILFLG),A
  2244.     CALL    FLSLST
  2245.     LD    BC,0
  2246.     LD    (LSTOFF),BC
  2247.     RET
  2248. ;
  2249. HEXBUF:    PUSH    AF
  2250.     CALL    ROTATE
  2251.     CALL    HEXBF1
  2252.     POP    AF
  2253. ;
  2254. HEXBF1:    AND    0FH
  2255.     CP    10
  2256.     JR    C,HEXBF2
  2257.     ADD    A,7
  2258. ;
  2259. HEXBF2:    ADD    A,30H
  2260.     LD    (HL),A
  2261.     INC    HL
  2262.     RET
  2263. ;
  2264. SKPLBL:    LD    A,(HL)
  2265.     CP    ':'
  2266.     JR    Z,SKPLB1
  2267.     CP    ' '
  2268.     JR    Z,SKPLB1
  2269.     CP    'A'
  2270.     JR    NC,SKPLB1
  2271.     CP    '9'+1
  2272.     RET    NC
  2273.     CP    '0'
  2274.     RET    C
  2275. ;
  2276. SKPLB1:    INC    HL
  2277.     JR    SKPLBL
  2278. ;
  2279. ; Find entry in symbol table. On entry HL => label name.
  2280. ; On exit: NZ if not found, else Z and HL => value entry.
  2281. ;
  2282. FNDSYM:    PUSH    HL        ; Get length of new entry
  2283.     LD    C,0
  2284. ;
  2285. FNDS1:    LD    A,(HL)
  2286.     CP    '0'
  2287.     JR    C,FNDS3        ; Go if end of label
  2288.     CP    '9'+1
  2289.     JR    C,FNDS2        ; Go if numeric
  2290.     CP    'A'
  2291.     JR    C,FNDS3        ; Go if end
  2292.     CP    'Z'+1
  2293.     JR    NC,FNDS3    ; Go if end
  2294. ;
  2295. FNDS2:    INC    HL
  2296.     INC    C
  2297.     LD    A,C
  2298.     CP    6
  2299.     JR    NZ,FNDS1
  2300. ;
  2301. ; C = length of label name (6 maximum)
  2302. ;
  2303. FNDS3:    POP    HL        ; Recover pointer to label
  2304.     LD    DE,(SYMTAB)    ; Get pointer to start of table
  2305. ;
  2306. FNDS4:    LD    A,(DE)        ; Get label char count
  2307.     AND    7
  2308.     JR    NZ,FNDS5    ; Go if not end of table
  2309.     OR    0FFH        ; Else entry not found
  2310.     LD    HL,(SYMTAB)
  2311.     RET
  2312. ;
  2313. FNDS5:    CP    C
  2314.     JR    NZ,FNDS8    ; Go if not same length
  2315.     PUSH    HL        ; Save text pointer
  2316.     PUSH    DE        ; And entry pointer
  2317.     PUSH    BC        ; And length
  2318.     LD    B,A
  2319. ;
  2320. FNDS6:    INC    DE
  2321.     LD    A,(DE)
  2322.     CP    (HL)
  2323.     JR    NZ,FNDS7    ; Go if no match
  2324.     INC    HL
  2325.     DEC    C
  2326.     DJNZ    FNDS6        ; Do for all
  2327.     EX    DE,HL        ; Else point to value entry in HL
  2328.     INC    HL
  2329.     POP    BC
  2330.     POP    DE        ; Clean stack
  2331.     POP    DE
  2332.     RET
  2333. ;
  2334. FNDS7:    POP    BC
  2335.     POP    DE        ; Restore registers
  2336.     POP    HL
  2337.     LD    A,(DE)        ; Get length of this entry
  2338.     AND    7
  2339. ;
  2340. FNDS8:    ADD    A,3
  2341.     LD    B,A
  2342. ;
  2343. FNDS9:    INC    DE        ; Skip this entry
  2344.     DJNZ    FNDS9
  2345.     JR    FNDS4        ; Go check next entry
  2346. ;
  2347. ;  Enter label into symbol table. On entry HL => label name,
  2348. ;  (tmpval) = value of label. Only chars '0'-'9' and 'A'-'F' allowed.
  2349. ;  On exit HL => end of table (value entry + 2).
  2350. ;
  2351. ENTSYM:    LD    DE,(SYMEND)    ; Get pointer to end of table
  2352.     PUSH    HL        ; Compute length of entry
  2353.     LD    C,0
  2354. ;
  2355. ENTSM1:    LD    A,(HL)
  2356.     CP    '0'
  2357.     JR    C,ENTSM3    ; Go if end of label
  2358.     CP    '9'+1
  2359.     JR    C,ENTSM2    ; Go if numeric
  2360.     CP    'A'
  2361.     JR    C,ENTSM3    ; Go if end
  2362.     CP    'Z'+1
  2363.     JR    NC,ENTSM3    ; Go if end
  2364. ;
  2365. ENTSM2:    INC    HL
  2366.     INC    C
  2367.     LD    A,C
  2368.     CP    6
  2369.     JR    NZ,ENTSM1    ; 6 char maximum
  2370. ;
  2371. ENTSM3:    POP    HL
  2372.     LD    A,C        ; No entry if count = 0
  2373.     OR    A
  2374.     RET    Z
  2375.     LD    (DE),A        ; Set byte count in table
  2376.     INC    DE
  2377.     LD    B,0        ; Transfer label to table
  2378.     LDIR
  2379.     EX    DE,HL
  2380.     LD    BC,(TMPVAL)    ; Get value
  2381.     LD    (HL),C
  2382.     INC    HL
  2383.     LD    (HL),B
  2384.     INC    HL
  2385.     LD    (HL),0        ; Flag end of table
  2386.     LD    (SYMEND),HL    ; Update end of table pointer
  2387.     RET
  2388. ;
  2389. ; Data area
  2390. ;
  2391. LINUM:    DEFW    0        ; Input line number
  2392. PASS:    DEFB    0        ; Pass number
  2393. FILFLG:    DEFB    0        ; File open flag
  2394. IBFRP:    DEFW    IBFR        ; Source buffer pointer
  2395. FCBTMP:    DEFW    0        ; Temp fcb pointer
  2396. FCB1:    DEFS    36,0        ; Object file fcb
  2397. HEXDMA:    DEFW    0        ; Dma pointer for hex file
  2398. HEXOFF:    DEFW    0        ; Offset into hex buffer
  2399. HEXFLG:    DEFB    0        ; Hex output flags
  2400. HEXCKS:    DEFB    0        ; Hex checksum
  2401. HEXPC:    DEFW    0        ; Hex file pc
  2402. RECPC:    DEFW    0        ; Hex record pc
  2403. FCB2:    DEFS    36,0        ; List file fcb
  2404. CURLIN:    DEFW    0        ; Current line in list buffer
  2405. LSTDMA:    DEFW    0        ; Dma pointer for list file
  2406. LSTOFF:    DEFW    0        ; Offset into list buffer
  2407. BYTCNT:    DEFW    0        ; Object code byte count
  2408. ERRCNT:    DEFW    0        ; Error count
  2409. DMA1:    DEFW    0        ; Dma buffer pointer for object code
  2410. DMA2:    DEFW    0        ; Dma bfr ptr for list code
  2411. IBFEND:    DEFW    0        ; End of input buffer pointer
  2412. TMPVAL:    DEFW    0        ; Temp value storage
  2413. PC:    DEFW    0        ; Program counter value
  2414. OPCODE:    DEFS    60        ; Current binary opcode
  2415. OCLEN:    DEFB    0        ; Opcode length (0 - 2)
  2416. ERRFLG:    DEFB    0        ; Error flag
  2417.     DEFW    0
  2418. SYMTAB:    DEFW    0        ; Pointer to start of symbol table
  2419. SYMEND:    DEFW    0        ; Ptr to end of sym tbl
  2420. SYMPTR:    DEFW    0        ; Current ptr to sym tbl
  2421. SYMVAL:    DEFW    0        ; Pointer to value in sym tbl
  2422. NUMBER:    DEFW    0        ; Return value from expression evaluator
  2423. EXPOP:    DEFW    0        ; Expression evaluator operator and flags
  2424. ;
  2425. ERRTBL:    DEFW    ERRM0        ; Pointers to error messages
  2426.     DEFW    ERRM1
  2427.     DEFW    ERRM2
  2428.     DEFW    ERRM3
  2429.     DEFW    ERRM4
  2430.     DEFW    ERRM5
  2431.     DEFW    ERRM6
  2432. ;
  2433. IMSG:    DEFB    CR,LF,'UCASM Micro-controller Assembler v'
  2434.     DEFB    VER+30H,'.',REV+30H,CR,LF
  2435.     DEFB    'Copyright (c) 1987, 1988 by J. L. Post',CR,LF,0
  2436. ;
  2437. RDERMS:    DEFB    'Can''t open source file',0
  2438. AWCRAP:    DEFB    CR,LF,'Too many errors!',0
  2439. ERRMSG:    DEFB    CR,LF,'** Error, ',0
  2440. LINMSG:    DEFB    ' in line number ',0
  2441. ;
  2442. ERRM0:    DEFB    'system failure',0 ; Should never happen
  2443. ERRM1:    DEFB    'unknown opcode',0 ; Pass 1
  2444. ERRM2:    DEFB    'invalid operand',0 ; Pass 1
  2445. ERRM3:    DEFB    'multiply defined symbol',0 ; Pass 1
  2446. ERRM4:    DEFB    'out of range',0 ; Pass 2
  2447. ERRM5:    DEFB    'undefined symbol',0 ; Pass 2
  2448. ERRM6:    DEFB    'invalid expression',0 ; Pass 2
  2449. ;
  2450. OPNEMS:    DEFB    'Can''t open .',0
  2451.     DEFB    ' file',0
  2452. ;
  2453. DONMSG:    DEFB    ' byte',0
  2454.     DEFB    ' error',0
  2455. ;
  2456. LINBFP:    DEFW    LINBFR        ; Line buffer pointer
  2457. LINBFR    EQU    $        ; Input line buffer
  2458. LSTBFR    EQU    LINBFR+100    ; List output buffer
  2459. HEXBFR    EQU    LSTBFR+100    ; Hex output buffer
  2460. ;
  2461. STACK    EQU    HEXBFR+200    ; System stack space
  2462. IBFR    EQU    STACK        ; Source code input buffer
  2463. ;
  2464. ;
  2465. ; Symbol table starts at end of input buffer. Entries consist of one
  2466. ; byte for length of symbol name, ascii text of symbol, two bytes for
  2467. ; symbol value (low byte first).
  2468. ;
  2469.     END
  2470.