home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol164 / fxt86.asm < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  20.8 KB  |  846 lines

  1.  
  2.  
  3. ;    =======================================================
  4. ;
  5. ;    REC module containing RAM storage, I/O programs, main
  6. ;    program, and the directory. The complete set of modules
  7. ;    comprises REC.MAC, PDL.MAC, MARKOV.MAC, RECLIB.MAC, and
  8. ;    FXT.MAC.  RECLIB.MAC may be omitted if the operator X
  9. ;    isn't used, and must be substituted by another module
  10. ;    if the collection of subroutines to be called by X is
  11. ;    to be changed.
  12. ;
  13. ;    FXT.MAC contains the following REC operators and
  14. ;    predicates:
  15. ;
  16. ;        C    compile a REC expression
  17. ;        i    input from designated port
  18. ;        k    call CP/M without residue
  19. ;        K    call CP/M, preserve FCB, return value
  20. ;        o    output from designated port
  21. ;        R    read one character from console
  22. ;        t    type message given header
  23. ;        T    type argument on PDL
  24. ;        W    write argument on LST:
  25. ;        x    execute REC subroutine
  26. ;        `    test if a character waits at keyboard
  27. ;
  28. ;    REC version released during the 1980  Summer School of
  29. ;    the Microcomputer Applications Group of the I.C.U.A.P.
  30. ;
  31. ;             FXT86  -  Copyright (C) 1982
  32. ;            Universidad Autonoma de Puebla
  33. ;          49 Poniente 1102 -  Puebla, Puebla, Mexico
  34. ;             All Rights Reserved
  35. ;
  36. ;         [Harold V. McIntosh,  28 August 1980]
  37. ;
  38. ;    Modification 1 - 1 January 1981.
  39. ;        a) Main program derives the values of const,
  40. ;           conin, conou from the address rst0 supposing
  41. ;           that BIOS starts out with the standard jump
  42. ;           vector.  Thus, REC need not be reassembled
  43. ;           to have fast access to I/O when CP/M varies.
  44. ;        b) T protected by pushes and pops of dx and bx.
  45. ;        c) Some changes made in memory allocation.
  46. ;    24 May 1981 - Zero flag to restrain L from too many pops
  47. ;    25 March 1982 - Y is now a predicate
  48. ;    29 May 1983 - ~ discontinued as argument exchange
  49. ;    29 May 1983 - ~ for unary negative or complement
  50. ;    29 May 1983 - N for numerical comparison on PDL
  51. ;    29 May 1983 - h discontinued, replaced by ''w
  52. ;    30 May 1983 - CPIR: jumps to BOOT rather than RER
  53. ;    8 July 1983 - C has object program origin as argument
  54. ;    8 July 1983 - C is an operator
  55. ;    8 July 1983 - C0 defined as lower bound of compile area
  56. ;    8 July 1983 - x moved from RECLIB
  57. ;    8 July 1983 - x is a predicate to call REC subroutines
  58. ;    9 July 1983 - Buffered CP/M input if no disk file given
  59. ;    14 July 1983 - W had its arguments reversed
  60. ;    =======================================================
  61.  
  62. ;    Absolute program locations used by CP/M.
  63.  
  64. bdos    equ    224        ;CP/M-86 software interrupt vector
  65.  
  66. TFCB    equ    005CH        ;CP/M file control block
  67. TALT    equ    006CH        ;CP/M alternate file name
  68. FSIZ    equ    0010H        ;CP/M file name size
  69. HSIZ    equ    FSIZ/2
  70. TBUF    equ    0080H        ;CP/M disk buffer location
  71. TSIZ    equ    0080H        ;CP/M disk buffer size
  72.  
  73. ;    -----------------------------------------------------
  74. ;    RAM memory which is required for the operation of REC
  75. ;    -----------------------------------------------------
  76.  
  77. ;    Relay area for input and output subroutines.
  78.  
  79. read:    dw    chin        ;character input for REC compiler
  80. tyin:    dw    chin        ;single character input for R
  81. tyou:    dw    chou        ;single character output for T
  82.  
  83. ;    Temporary storage used by the REC compiler.
  84.  
  85. XPD:    dw    0000        ;colon jump back to left parenthesis
  86. YPD:    dw    0000        ;false predicate jump chain
  87. ZPD:    dw    0000        ;semicolon exit chain
  88.  
  89. ;    Pointers to the directories.
  90.  
  91. FXT:    dw    FT        ;pointer to fixed operator directory
  92. VRT:    dw    VT        ;pointer to subroutine directory
  93.  
  94. ;    Pointers to the area of compiled subroutines.
  95.  
  96. C0:    dw    KA        ;lower limit of compile area
  97. C1:    dw    KA        ;beginning of present compilation
  98. C2:    dw    EK        ;upper limit of compile area
  99.  
  100. ;    Pointers to REC/MARKOV pushdown list.
  101.  
  102. PX:    dw    PD+2        ;beginning of pushdown text
  103. PY:    dw    PD+2        ;end of pushdown text
  104. PZ:    dw    EP        ;end of available pushdown space
  105.  
  106. ;    Workspace pointers.
  107.  
  108. P0:    dw    WS        ;beginning of workspace
  109. P1:    dw    WS        ;beginning of marked segment
  110. P2:    dw    WS        ;end of marked segment
  111. P3:    dw    WS        ;end of text
  112. P4:    dw    EW        ;end of workspace
  113.  
  114. ;    I-O pointers.
  115.  
  116. RX:    dw    0000
  117. RY:    dw    0000
  118.  
  119. ;    Linkage to input-output through ports.
  120.  
  121. QIN:    DB    0ECH        ;8-bit static IN instruction
  122. QI:    DB    00H
  123.     ret
  124.  
  125. QOU:    DB    0E6H        ;8-bit static OUT instruction
  126. QO:    DB    00H
  127.     ret
  128.  
  129. ;    Error flag.
  130.  
  131. ER:    dw    0000
  132.  
  133. ;    =======================================================
  134. ;    Programs related to input-output and disk usage.
  135. ;    =======================================================
  136.  
  137. ;    bootstrap routine
  138.  
  139. boot:    ld    cl,#ze
  140.     ld    dl,#ze
  141.     int    bdos
  142.  
  143. ;    Buffer read routine.
  144.  
  145. PTY:    push    bx        ;conserve (bx)
  146.     ld    bx,RX        ;pointer to read buffer
  147.     ld    al,[bx]        ;fetch byte
  148.     inc    bx        ;advance pointer to next byte
  149.     sto    bx,RX        ;update buffer pointer
  150.     pop    bx        ;restore (bx) - preserve all reg pairs
  151.     ret
  152.  
  153. ;    Console character read routine.  Strict CP/M compatible
  154. ;    version, which has characteristics undesirable for some
  155. ;    applications, such as an automatic echo or preemption
  156. ;    of some of the control characters for editing purposes.
  157. ;    When it is used, programs must forego their own echo,
  158. ;    and do their own editing when required.  This version has
  159. ;    direct access to CONIN.
  160.  
  161. chin:    push    cx
  162.     push    dx
  163. chi:    ld    dl,#-1
  164.     ld    cl,#6
  165.     int    bdos
  166.     or    al,al
  167.     jz    chi
  168.     pop    dx
  169.     pop    cx
  170.     ret
  171.  
  172. ;    Buffered console character read routine, which is more
  173. ;    practical for use with CP/M.  Up to 126 characters may be
  174. ;    read using CP/M function 10, which is sufficient for
  175. ;    bootstrapping or generating test programs. CHIN should be
  176. ;    used for longer input sequences, which must be error-free
  177. ;    - incoming through a modem for example.
  178.  
  179. buin:    push    bx
  180.     push    cx
  181.     push    dx
  182.     ld    bx,RX
  183.     cmp    bx,RY
  184.     jnz    BI5
  185.     ld    cl,#9        ;(09) write message
  186.     ld    dx,#bume
  187.     int    bdos
  188.     ld    cl,#10        ;(0A) buffered read
  189.     ld    dx,#TBUF
  190.     int    bdos
  191.     ld    cl,#9        ;(09) write message
  192.     ld    dx,#crlf
  193.     int    bdos
  194.     ld    bx,#TBUF+2
  195.     sto    bx,RX
  196.     ld    al,[bx-1]
  197.     ld    ah,#0
  198.     add    ax,bx
  199.     sto    ax,RY
  200. BI5:    ld    al,[bx]
  201.     inc    bx
  202.     sto    bx,RX
  203.     pop    dx
  204.     pop    cx
  205.     pop    bx
  206.     ret
  207.  
  208. logo:    db    0DH,0AH,'        REC(8086)/ICUAP',0DH,0AH
  209.     db    'Universidad Autonoma de Puebla',0DH,0AH
  210.     db    '         July 20, 1983',0DH,0AH,'$'
  211. bume:    db    0DH,0AH,'REC86> $'
  212. crlf:    db    0DH,0AH,'$'
  213.  
  214. bure:    ld    al,#TSIZ-2
  215.     sto    al,TBUF
  216.     ld    ax,#buin
  217.     sto    ax,read
  218.     ld    ax,#TBUF
  219.     sto    ax,RX
  220.     sto    ax,RY
  221.     ret
  222.  
  223. ;    Console character out routine.  Strict CP/M compatible
  224. ;    version, which unfortunately makes so many tests and
  225. ;    jumps that it is unsuitable for programs such as the
  226. ;    cursor editor which frequently write a full screen.
  227. ;    This is a version with direct access to CONOUT.
  228.  
  229. chou:    push    cx
  230.     push    dx
  231.     mov    dl,al
  232.     ld    cl,#6        ;direct console I-O
  233.     int    bdos
  234.     pop    dx
  235.     pop    cx
  236.     ret
  237.  
  238. ;    (`)  Test for presence of waiting character (FALSE if
  239. ;    none waiting).  This is a version with fast access to 
  240. ;    CONST, which is required when the fast CHIN is used,
  241. ;    because CP/M has some internal buffers which will 
  242. ;    otherwise distort the results.
  243.  
  244. chaw:    push    cx
  245.     push    dx
  246.     ld    dl,#-2
  247.     ld    cl,#6        ;direct console I-O
  248.     int    bdos
  249.     pop    dx
  250.     pop    cx
  251.     ror    al
  252.     jc    chw
  253.     ret
  254. chw:    jmp    SKP
  255.  
  256. ;    Printer output routine.
  257.  
  258. PROU:    push    bx
  259.     push    dx
  260.     push    cx
  261.     ld    cl,#5        ;output through LST:
  262.     MOV    dl,al
  263.     int    bdos
  264.     pop    cx
  265.     pop    dx
  266.     pop    bx
  267.     ret
  268.  
  269. ;    (R)  REC read operator.
  270.  
  271. UCR:    ld    cx,#1        ;one byte to be inserted
  272.     call    NARG        ;close last arg, verify space
  273.     push    bx
  274.     ld    bx,tyin
  275.     call    bx        ;get byte from console input
  276.     pop    bx
  277.     sto    al,[bx]        ;store on PDL
  278.     inc    bx        ;advance pointer
  279.     sto    bx,PY        ;save as terminator
  280.     ret
  281.  
  282. ;    (t) Write indirect operator.  <org,siz,t> prints the
  283. ;    indicated message, leaves no residue.
  284.  
  285. LCT:    ld    bx,PX        ;fetch argument pointer
  286.     call    TWOL        ;move two args to 8080 stack
  287.     pop    dx        ;second arg (org) into (dx)
  288.     pop    bx        ;top arg (siz) into (bx)
  289.     add    bx,dx        ;org+siz=end
  290.     xchg    bx,dx        ;(dx)=end, (bx)=org
  291.     jmp    UT1        ;use write cycle in UCT
  292.  
  293. ;    (T)  REC write operator.  <'XXX' T> will write XXX on
  294. ;    the console, leaving it on the PDL.
  295.  
  296. uct:    ld    dx,py        ;fetch terminal address
  297.     ld    bx,px        ;beginning address to (bx)
  298. ut1:    cmp    dx,bx        ;
  299.     jz    ut2        ;they match, we're done
  300.     ld    al,[bx]        ;get byte out of memory
  301.     push    bx        ;the registers dx and bx
  302.     push    dx        ;are essential for the loop
  303.     ld    bx,tyou
  304.     call    bx
  305.     pop    dx        ;recover the saved registers
  306.     pop    bx        ;
  307.     inc    bx        ;advance pointer
  308.     jmp    UT1        ;repeat
  309. ut2:    ret
  310.  
  311. ;    (W)  REC print operator.  <org, siz, W> will print the
  312. ;    indicated text on the list device, and then erase its
  313. ;    arguments.
  314.  
  315. UCW:    ld    bx,PX        ;pointer to arguments
  316.     call    TWOL        ;2 args from PDL to 8080 stack
  317.     pop    bx        ;place text origin in (bx)
  318.     pop    dx        ;place length in (dx)
  319. UWW:    cmp    dx,dx        ;check for zero length
  320.     jz    UWX        ;no more to print
  321.     ld    al,[bx]        ;fetch a byte
  322.     push    bx        ;we need to be sure that dx and bx are
  323.     push    dx        ;preserved whatever the print routine
  324.     call    PROU        ;send it to printer
  325.     pop    dx        ;recover bx
  326.     pop    bx        ;and dx
  327.     dec    dx        ;diminish count
  328.     inc    bx        ;advance pointer
  329.     jmp    UWW        ;repeat
  330. UWX:    ret
  331.  
  332. ;    (i)  Input from designated port.  <port, i> leaves
  333. ;    <port, byte> so that after disposing of <byte>, <port>
  334. ;    can be reused.
  335.  
  336. LCI:    ld    bx,PX        ;get pointer to top argument on PDL
  337.     ld    al,[bx]        ;only the low order byte matters
  338.     sto    al,QI        ;place it in teme IN instruction
  339.     ld    cx,#1        ;we're only going to read one byte
  340.     call    NARG        ;prepare a place for it on the PDL
  341.     call    QIN        ;execute the captive IN instruction
  342.     sto    al,[bx]        ;storing the incoming byte on the PDL
  343.     inc    bx        ;always ready for the next byte
  344.     sto    bx,PY        ;close off the argument
  345.     ret            ;and we're through
  346.  
  347. ;    (o) Output from designated port  -  <port, byte, o>
  348. ;    leaves <port>, facilitating multiple OUTs through the
  349. ;    same port.
  350.  
  351. LCO:    ld    bx,PX        ;pointer to last argument - output byte
  352.     ld    CH,[bx]        ;tuck it into register b
  353.     call    UCL        ;erase the top argument
  354.     ld    al,[bx]        ;(bx) points to next argument - get it
  355.     sto    al,QO        ;store in tame OUT instruction
  356.     MOV    al,CH        ;output must be from accumulator
  357.     jmp    QOU        ;execute the prepared OUT instruction
  358.  
  359. ;    =======================================================
  360. ;
  361. ;    Communication with CP/M takes two forms:  <FCB, n, K>
  362. ;    which leaves <FCB, code> on the pushdown list, or else
  363. ;    <FCB, n, k> which leaves nothing on the pushdown list.
  364. ;    In either case - FCB is a two-byte parameter, usually
  365. ;    the address of the file control block - but it could
  366. ;    also be a DMA address or sometimes even null for the
  367. ;    sake of uniformity.  Approximately thirty options are
  368. ;    available which are numbered serially, indicated by the
  369. ;    argument n.  The difference between K and k is that the
  370. ;    former conserves the parameter FCB for possible use by
  371. ;    a subsequent CP/M call, and reports a result in the
  372. ;    one-byte result <code>.  This could be the character
  373. ;    read by an input routine or an error code for the disk
  374. ;    routines.
  375. ;
  376. ;    The options are:
  377. ;
  378. ;    num    function        "FCB"    "code"
  379. ;    ---    --------        -----    ------
  380. ;
  381. ;     0    system reset        -    -
  382. ;     1    read console        -    char
  383. ;     2    write console        char    -
  384. ;     3    read reader        -    char
  385. ;     4    write punch        char    -
  386. ;     5    write list        char    -
  387. ;     6    -            -    -
  388. ;     7    read i/o stat        -    stat
  389. ;     8    write i/ stat        stat    -
  390. ;     9    print buffer        buffer    -
  391. ;    10    read buffer        buffer    -
  392. ;    11    console status    -    stat
  393. ;
  394. ;    12    lift disk head        -    -
  395. ;    13    init disk only        -    -
  396. ;    14    select disk        disk    -
  397. ;    15    open file        fcb    code
  398. ;    16    close file        fcb    code
  399. ;    17    search once        fcb    code
  400. ;    18    search again        fcb    code
  401. ;    19    delete file        fcb    code
  402. ;    20    read 1 record        fcb    code
  403. ;    21    write 1 record        fcb    code
  404. ;    22    create file        fcb    code
  405. ;    23    rename file        fcb    code
  406. ;    24    read login        -    logv
  407. ;    25    read disklog        -    disk
  408. ;    26    set DMA address        dma    -
  409. ;    27    read bitmap        -    -
  410. ;
  411. ;    Fuller details of all the CP/M options and the way they
  412. ;    function can be obtained through consulting Digital
  413. ;    Research's manuals for CP/M, especially their "CP/M
  414. ;    Interface Guide."
  415. ;
  416. ;    =======================================================
  417.  
  418. ;    (K)  Set up communication with CP/M - top into (bx),
  419. ;    next into (dx).  Preserve next, call BDOS, (Aze) into
  420. ;    top.
  421.  
  422. CPM:    ld    bx,PX        ;fetch pointer to top argument
  423.     ld    cx,[bx]        ;load C from low byte
  424.     ld    dx,[bx-2]    ;load up (dx) with high byte
  425.     xchg    bx,dx        ;pointer into (bx)
  426.     ld    dx,[bx]        ;low byte of under argument
  427.     int    bdos        ;call BDOS with args in (bx), (dx)
  428.     ld    bx,PX        ;pointer to top argument again
  429.     sto    al,[bx]        ;save low byte from A
  430.     stob    #ZE,[bx+1]    ;make high byte a zero
  431.     ret
  432.  
  433. ;    (k)  Call to CP/M without any value returned.
  434.  
  435. CPML:    call    CXLD        ;load top arg into (cx), lift it
  436.     call    DXLD        ;load next arg into (dx), lift it too
  437.     int    bdos        ;execute indicated operation
  438.     ret
  439.  
  440. ;    -------------------------------------------------------
  441. ;    Disk input-output routine working through CP/M.
  442. ;    -------------------------------------------------------
  443.  
  444. ;    Set up a file control block with a given file name and
  445. ;    the default extension REC.  The pushdown list contains
  446. ;    the disk unit designation, then by the filename without
  447. ;    any extension. No protection is afforded against an
  448. ;    overly long file name, a nonexistent disk, or the like.
  449. ;    Some errors of this type must be caught by CP/M since
  450. ;    REC cannot know such things as the exact number of disk
  451. ;    drives that there will be.
  452.  
  453. DIIN:    cld
  454.     mov    ax,ds
  455.     mov    es,ax
  456.     ld    cx,#21H        ;FCB requires 33 bytes
  457.     ld    di,#TFCB    ;use CP/M's transient FCB
  458.     ld    al,#00H        ;    ;fill it with zeroes
  459.     rep
  460.     stosb
  461.     ld    cx,#11        ;filename field is 11 bytes long
  462.     ld    di,#TFCB+1    ;field begins at second byte
  463.     ld    al,#' '        ;fill it with blanks
  464.     rep
  465.     stosb
  466.     ld    bx,PX        ;fetch pointer to top argument
  467.     ld    al,[bx]        ;load disk unit designator
  468.     SUB    al,#'@'        ;normalize to uppercase letters
  469.     sto    al,TFCB        ;store it in file control block
  470.     call    UCL        ;pop top argument
  471.     ld    si,PX        ;fetch pointer to file name
  472.     ld    cx,PY        ;end of file name
  473.     sub    cx,si        ;place py - px in (cx)
  474.     ld    di,#TFCB+1    ;destination origin
  475.     rep
  476.     movsb
  477. CPIN:    ld    cl,#15        ;<open file>
  478.     ld    dx,#TFCB    ;file control block
  479.     int    bdos        ;
  480.     cmp    al,#0FFH    ;check for error
  481.     jz    CPIR
  482.     ld    bx,#TBUF    ;origin of CP/M's sector buffer
  483.     sto    bx,RX        ;initial address of pseudotty
  484.     sto    bx,RY        ;provoke disk read
  485.     ret
  486. CPIR:    jmp    boot
  487.  
  488. ;    Read from disk buffer, replenish buffer when empty.
  489.  
  490. DIRE:    push    bx        ;save 3 8080 register pairs
  491.     push    dx        ;
  492.     push    cx        ;
  493.     ld    bx,RX        ;pointer to current byte
  494.     cmp    bx,RY        ;skip if equal
  495.     jnz    DI5        ;still have bytes in the buffer
  496.     ld    cl,#20        ;<read next record>
  497.     ld    dx,#TFCB    ;file control block
  498.     int    bdos        ;
  499.     ld    bx,#TBUF+TSIZ    ;end of buffer
  500.     sto    bx,RY        ;store it in ry
  501.     ld    bx,#TBUF    ;beginning of buffer
  502.     sto    bx,RX        ;store it in rx
  503. DI5:    ld    al,[bx]        ;common continuation
  504.     inc    bx        ;byte in acc, advance pointer
  505.     sto    bx,RX        ;store position of next byte
  506.     pop    cx        ;replace 3 register pairs
  507.     pop    dx        ;
  508.     pop    bx        ;
  509.     ret
  510.  
  511. ;    ================
  512. ;    = main program =
  513. ;    ================
  514.  
  515. MAIN:    mov    ax,cs
  516.     mov    ss,ax
  517.     ld    sp,#STAK
  518.     ld    bx,#ZE        ;
  519.     sto    bx,PD        ;mark bottom of pushdown list
  520.     ld    al,TFCB+1
  521.     cmp    al,#' '
  522.     jz    tylo
  523.     ld    cx,#HSIZ
  524.     ld    bx,#TALT
  525. pual:    push    [bx]        ;save secondary file name
  526.     inc    bx
  527.     inc    bx
  528.     loop    pual
  529.     call    CPIN        ;open disk file for REC program
  530.     ld    bx,#DIRE    ;REC input through disk
  531.     sto    bx,read        ;REC compiler's I-O linkage
  532.     call    INRE        ;initialize REC compiler RAM
  533.     call    EMCX        ;compile the program file
  534.     ld    cx,#HSIZ
  535.     ld    bx,#TFCB+FSIZ
  536.     pop    dx
  537. poal:    dec    bx
  538.     dec    bx
  539.     pop    [bx]
  540.     loop    poal
  541.     push    dx
  542.     call    EMCU        ;execute the program file
  543.     jmps    bootie        ;return to CP/M if false
  544.     nop            ;beware jump span
  545. bootie:    jmp    boot        ;or even if it was true
  546. tylo:    ld    cl,#9        ;(09) write message
  547.     ld    dx,#logo
  548.     int    bdos
  549. nodi:    call    bure
  550.     call    INRE
  551.     call    EMCX
  552.     call    EMCU
  553.     jmps    nodi
  554.     nop
  555.     jmp    nodi
  556.  
  557. ;    (C) REC compiling operator which takes the designation
  558. ;    of the compiling source from the PDL. The alternatives
  559. ;    are:
  560. ;
  561. ;          ''C        input program from console
  562. ;        'file' 'D' C    take <file.rec> from disk D
  563. ;           pC        pushdown list
  564. ;           qC        workspace
  565. ;        <org,siz,C>        memory from address org onward
  566. ;
  567. ;    In general, if the top argument is of length zero, the
  568. ;    console is the source, if it is of length one the named
  569. ;    disk is the source [@=current disk, A, B, ... up to the
  570. ;    system's limit], and if the argument has length 2, the
  571. ;    combination of <org, siz> from the memory applies.  It
  572. ;    is the programmer's responsibility to avoid nonexistent
  573. ;    memory, disk units, and the like.
  574.  
  575. UCC:    ld    ax,PY
  576.     sub    ax,PX
  577.     jz    UC2        ;zero means console
  578.     cmp    ax,#1        ;test for one byte
  579.     jz    UC1        ;one means disk designation
  580.     cmp    ax,#2        ;verify that we've got two bytes
  581.     jnz    UC7        ;no provision for other than 1, 2 bytes
  582.     ld    bx,#PTY        ;setup readin from pseudoteletype
  583.     sto    bx,read        ;
  584.     call    CXLD        ;load two numerical arguments
  585.     ld    dx,[bx]        ;bx contains PX for second argument
  586.     sto    dx,RX        ;origin of REC source code
  587.     add    dx,cx        ;length of source code
  588.     sto    dx,RY        ;end of source code
  589.     jmp    UC4        ;compile once rx, ry set up
  590. UC1:    call    DIIN        ;setup the CP/M FCB for given file
  591.     ld    bx,#DIRE    ;setup input from disk reader
  592.     jmp    UC3        ;compile once input source set up
  593. UC2:    ld    bx,#CHIN    ;input from the console
  594. UC3:    sto    bx,read        ;
  595. UC4:    call    UCL
  596.     ld    cx,PY
  597.     sub    cx,PX
  598.     cmp    cx,#0
  599.     jnz    UC5
  600.     ld    dx,C1
  601.     jmp    UC6
  602. UC5:    cmp    cx,#2
  603.     jnz    UC7
  604.     ld    bx,PX
  605.     ld    dx,[bx]
  606.     push    dx
  607.     call    UCL
  608.     pop    dx
  609.     cmp    dx,C0
  610.     jc    UC6
  611.     cmp    C2,dx
  612.     jc    UC6
  613.     sto    dx,C1
  614. UC6:    push    dx
  615.     call    LEFT
  616.     call    RECRR
  617.     push    dx
  618.     call    PUTW
  619.     call    PUTW
  620.     ret
  621. UC7:    call    RER
  622.  
  623. ;    (x)  Call a REC subroutine
  624.  
  625. go:    ld    bx,PX
  626.     call    onel
  627.     ret
  628.  
  629.  
  630. ;    ======= here is the table of definitions of REC operators =====
  631.  
  632. FT:    dw    NOOP        ;blank
  633.     dw    NOOP
  634.     dw    RECOP        ; !    binary to hex string
  635.     dw    HX
  636.     dw    RECDQ        ; "    quoted expression
  637.     dw    QU
  638.     dw    RECOP        ; #    binary to decimal string
  639.     dw    NS
  640.     dw    RECOP        ; $    fetch a variable cell
  641.     dw    VBLE
  642.     dw    RECOP        ; %    restrict to one byte
  643.     dw    PE
  644.     dw    RECOP        ; &    exchange top numeric pair
  645.     dw    EXCH
  646.     dw    RECSQ        ; '    quoted expression
  647.     dw    QU
  648.     dw    RECLP        ; (
  649.     dw    NOOP
  650.     dw    RECRP        ; )
  651.     dw    NOOP
  652.     dw    RECOP        ; *    multiply
  653.     dw    MPY
  654.     dw    RECOP        ; +    add
  655.     dw    SUM
  656.     dw    NOOP        ; ,    separator like space
  657.     dw    NOOP
  658.     dw    RECMS        ; -    subtract
  659.     dw    DIF
  660.     dw    RECOP        ; .
  661.     dw    NOOP
  662.     dw    RECOP        ; /    divide [remainder, quotient]
  663.     dw    DVD
  664.     dw    RECDD        ; 0    number
  665.     dw    NU
  666.     dw    RECDD        ; 1    number
  667.     dw    NU
  668.     dw    RECDD        ; 2    number
  669.     dw    NU
  670.     dw    RECDD        ; 3    number
  671.     dw    NU
  672.     dw    RECDD        ; 4    number
  673.     dw    NU
  674.     dw    RECDD        ; 5    number
  675.     dw    NU
  676.     dw    RECDD        ; 6    number
  677.     dw    NU
  678.     dw    RECDD        ; 7    number
  679.     dw    NU
  680.     dw    RECDD        ; 8    number
  681.     dw    NU
  682.     dw    RECDD        ; 9    number
  683.     dw    NU
  684.     dw    RECCO        ; :
  685.     dw    NOOP
  686.     dw    RECSC        ; ;
  687.     dw    NOOP
  688.     dw    RECOP        ; <    restrict workspace
  689.     dw    BRA
  690.     dw    RECPR        ; =    test equality of top pair
  691.     dw    EQL
  692.     dw    RECOP        ; >    open workspace
  693.     dw    KET
  694.     dw    RECPR        ; ?    test for error report
  695.     dw    QM
  696.     dw    RECP1        ; @    execute subroutine
  697.     dw    AR
  698.     dw    RECPR        ; A    advance pointer 1
  699.     dw    UCA
  700.     dw    RECPR        ; B    retract pointer 1
  701.     dw    UCB
  702.     dw    RECOP        ; C    compile
  703.     dw    UCC
  704.     dw    RECOP        ; D    delete text
  705.     dw    UCD
  706.     dw    RECPR        ; E    equality between WS and PD
  707.     dw    UCE
  708.     dw    RECPR        ; F    find specified text
  709.     dw    UCF
  710.     dw    RECOP        ; G    fetch a block from memory
  711.     dw    GA
  712.     dw    RECPR        ; H    ASCII hex to binary
  713.     dw    HE
  714.     dw    RECOP        ; I    insert
  715.     dw    UCI
  716.     dw    RECOP        ; J    jump to front
  717.     dw    UCJ
  718.     dw    RECOP        ; K    call CP/M, keep (dx), put value
  719.     dw    CPM
  720.     dw    RECOP        ; L    erase top of PDL
  721.     dw    UCL
  722.     dw    RECPR        ; M    compare PDL and workspace
  723.     dw    UCM
  724.     dw    RECPR        ; N    numerical comparison
  725.     dw    UCN
  726.     dw    RECPR        ; O    decimal ASCII string to binary
  727.     dw    UCO
  728.     dw    RECOP        ; P    put block into buffered memory
  729.     dw    UCP
  730.     dw    RECOP        ; Q    put workspace segment on PD
  731.     dw    UCQ
  732.     dw    RECOP        ; R    read from keyboard
  733.     dw    UCR
  734.     dw    RECOP        ; S    store block in memory
  735.     dw    SA
  736.     dw    RECOP        ; T    write on screen
  737.     dw    UCT
  738.     dw    RECPR        ; U    search, yielding interval
  739.     dw    UCU
  740.     dw    RECPR        ; V    U, including endpoints
  741.     dw    UCV
  742.     dw    RECOP        ; W    write on printer
  743.     dw    UCW
  744.     dw    RECOP        ; X    call library subroutine
  745.     dw    LIBR
  746.     dw    RECPR        ; Y    recover previous position of p1
  747.     dw    UCY
  748.     dw    RECOP        ; Z    pointer 2 to end of text
  749.     dw    UCZ
  750.     dw    RECCM        ; [    comment
  751.     dw    NOOP
  752.     dw    RECOP        ; \    insert single byte in pair
  753.     dw    IP
  754.     dw    RECOP        ; ]
  755.     dw    NOOP
  756.     dw    RECOP        ; ^    increment top argument
  757.     dw    INCR
  758.     dw    RECOP        ; _    exit to monitor
  759.     dw    boot
  760.     dw    RECPR        ; `    true for waiting character
  761.     dw    CHAW
  762.     dw    RECPR        ; a    segment forward from p1
  763.     dw    LCA
  764.     dw    RECPR        ; b    segment backward from p2
  765.     dw    LCB
  766.     dw    RECOP        ; c    create block on PDL
  767.     dw    BLOK
  768.     dw    RECPR        ; d     decrement but skip on zero
  769.     dw    decR
  770.     dw    RECPR        ; e    extend workspace
  771.     dw    LCE
  772.     dw    RECPR        ; f    block fill
  773.     dw    LCF
  774.     dw    RECOP        ; g    non-incrementing byte fetch
  775.     dw    GB
  776.     dw    RECOP        ; h
  777.     dw    NOOP
  778.     dw    RECOP        ; i    input from designated port
  779.     dw    LCI
  780.     dw    RECOP        ; j    null interval at p1
  781.     dw    LCJ
  782.     dw    RECOP        ; k    call CP/M: no returned values
  783.     dw    CPML
  784.     dw    RECOP        ; l    put pz on PDL
  785.     dw    Lcl
  786.     dw    RECOP        ; m    set aside top argument
  787.     dw    LCM
  788.     dw    RECOP        ; n    recover set-aside argument
  789.     dw    LCN
  790.     dw    RECOP        ; o    output from designated port
  791.     dw    LCO
  792.     dw    RECOP        ; p    put px, py-px on PDL
  793.     dw    GXS
  794.     dw    RECOP        ; q    put p1, p2-p1 on PDL
  795.     dw    LCQ
  796.     dw    RECOP        ; r    indirect replacement of address
  797.     dw    IND
  798.     dw    RECOP        ; s    store block in memory wrt limit
  799.     dw    LCS
  800.     dw    RECOP        ; t    type out indicated interval
  801.     dw    LCT
  802.     dw    RECOP        ; u    incrementing byte fetch
  803.     dw    GBI
  804.     dw    RECOP        ; v    incrementing byte store
  805.     dw    SAI
  806.     dw    RECOP        ; w    store workspace header
  807.     dw    LCW
  808.     dw    RECPR        ; x    subroutine jump  - no arguments
  809.     dw    GO
  810.     dw    RECOP        ; y    fetch byte pair to PDL incr org
  811.     dw    GWI
  812.     dw    RECOP        ; z    null interval at p2
  813.     dw    LCZ
  814.     dw    LBR        ; {    start a definition string
  815.     dw    NOOP
  816.     dw    RECOP        ; |    concatinate top two arguments
  817.     dw    CONC
  818.     dw    RECOP        ; }    end a definition string
  819.     dw    NOOP
  820.     dw    RECOP        ; ~    complement or negate top arg
  821.     dw    COMP
  822.     dw    RECOP        ; del
  823.     dw    NOOP
  824.  
  825. ENDREC:    ds    0
  826.  
  827. ;    Program locations and memory allocations.  Here is where
  828. ;    the memory is sectioned up into its functional components.
  829.  
  830. STAK    equ    0FFEEH        ;8086's pushdown stack
  831.  
  832. EW    equ    STAK-0800H    ;end of the workspace
  833. WS    equ    0C000H        ;beginning of the workspace
  834.  
  835. EK    equ    WS        ;end of the compiling area
  836. KA    equ    06000H        ;beginning of the compiling area
  837.  
  838. VT    equ    KA-0400H    ;directory for programs compiled by REC
  839.  
  840. EP    equ    VT        ;end of the pushdown list
  841. PD    equ    ENDREC        ;beginning of the pushdown list
  842.  
  843.     END    MAIN
  844.  
  845.  
  846.