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