home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol092 / litl-ada.asm < prev    next >
Assembly Source File  |  1984-04-29  |  25KB  |  1,000 lines

  1.  
  2. ;Little-Ada L/0 machine interperter
  3. ;Edited June 21, 1980
  4. ;Copyright 1980 by Ralph E. Kenyon Jr.
  5. ;Version 1547 Re-designated L/1 Jan 81
  6. ;Stripped down, no debug version
  7.  
  8.         REFS SYSTEM.SY  ;Library file
  9.         REF Warm        ;Warmstart
  10.         REF WH0         ;Consol Char in
  11.         REF WH1         ;Consol Char out
  12.         REF Msg         ;Message writer
  13.         REF USER        ;Start of user memory
  14.         REF MEMTOP      ;Last good memory
  15.         REF Ret         ;Return from overlay
  16.         REF Dio         ;Disk In/Out
  17.         REF Err         ;System error handler
  18.         REF FILE        ;File data buffer
  19.         REF Ovrto       ;Overlay handler
  20.         REF CMPTR       ;Command buffer pointer
  21.         REF Ioret       ;Return from Interupt
  22.  
  23.         REFS <#>L0CODE.SY
  24. ;Open L/0 code MACRO Library
  25.         REF L0CODE
  26. ;Macro which defines all L/0 code macros.
  27.  
  28. CR      EQU 13
  29.  
  30.         ORG USER
  31.         IDNT $,$        ;$ is current value PC
  32.  
  33.         JMP Start
  34.         JMP GO
  35.  
  36.         L0CODE
  37.         LIST 0
  38.  
  39. DBZ     DB CR,'Division by zero not defined!',CR,0
  40.  
  41. Inst    DS 1    ;Instruction register
  42. Base    DS 2    ;Base register
  43. Static  DS 2    ;Static link conversion register
  44. Level   DS 1    ;Level register
  45. AR1     DS 2    ;Arithemetic storage 1
  46. AR2     DS 2    ;Arithemetic storage 2
  47. AR3     DS 2    ;Arithemetic storage 3
  48. TMStack DS 2    ;Stack start
  49. FDB     DS 44   ;File descriptor buffer
  50. IFD     DS 1    ;Input file drive
  51. IFA     DS 2    ;Input file disk address
  52. IFS     DS 2    ;Input file disk sector
  53. IFP     DS 2    ;Input file buffer pointer
  54. IFB     DS 256  ;Input file buffer
  55. OFD     DS 1    ;Output file drive
  56. OFA     DS 2    ;Output file disk address
  57. OFS     DS 2    ;Output file disk sector
  58. OFP     DS 2    ;Output file buffer pointer
  59. OFB     DS 256  ;Output file buffer
  60. Flag    DS 1    ;Output file in use flag
  61.  
  62. IFflg   DB 1    ;initialize flag
  63. OFflg   DB 1    ;initialize flag
  64.  
  65. Fetch   LDAX B  ;Instruction fetch cycle
  66.         INX B
  67.         STA Inst
  68.         ORA A
  69.         RET
  70.  
  71. Push    MOV M,E         ;DE to S(t)
  72.         DCX H           ;t+1 to HL
  73.         MOV M,D
  74.         DCX H
  75.         RET
  76.  
  77. Pop     INX H           ;S(t) to DE
  78.         MOV D,M         ;t-1 to HL
  79.         INX H
  80.         MOV E,M
  81.         RET
  82.  
  83. MinDE   PUSH PSW        ;Two's complement
  84.         MOV A,D         ;of DE. All other
  85.         CMA             ;registers preserved.
  86.         MOV D,A
  87.         MOV A,E
  88.         CMA
  89.         MOV E,A
  90.         INX D
  91.         POP PSW
  92.         RET
  93.  
  94. CONV    PUSH H          ;Requires T in DE
  95.         CALL MinDE      ;(Static)
  96.         LHLD TMStack
  97.         DAD D           ;<[(TMStack)-(Static)]
  98.         MOV A,H         ;We're going to divide by 2
  99.         CMP H           ;(Just reset carry)
  100.         RAR             ;Puts lo bit in carry
  101.         MOV D,A         ;Right shifted by 1
  102.         MOV A,L         ;Lo byte
  103.         RAR             ;Carry goes into hi bit
  104.         MOV E,A         ;(16 bits right shift)
  105.         POP H
  106.         RET             ;Result in DE
  107.  
  108. ;This section computes the static link
  109. ;by finding the ltack position base for
  110. ;L levels down.
  111.  
  112. GStL    PUSH PSW
  113.         PUSH H
  114.         LDA Inst        ;get & stow level
  115.  
  116. GStL1   ANI 0FH
  117.         LHLD Base       ;get & stow base
  118.         SHLD Static
  119.         JMP BASE
  120.  
  121. BASE1   LHLD Static     ;get base
  122.         XCHG
  123.         LHLD TMStack
  124.         INX D           ;We need to be above by 1
  125.         CALL MinDE
  126.         DAD D           ;(MEMTOP-2*T)
  127.         DAD D           ;stack address now in hl
  128.         CALL Pop        ;Get S(S(t))
  129.         XCHG
  130.         SHLD Static
  131.         LDA Level       ;get level
  132.         DCR A
  133.  
  134. BASE    STA Level
  135.         JNZ BASE1
  136.         XCHG            ;Returns static level in DE
  137.         POP H
  138.         POP PSW
  139.         RET
  140.  
  141. Out2    MVI E,2         ;Output file already exists
  142.         JMP Out0
  143.  
  144. Out3    MVI E,3         ;Input file not specified
  145.  
  146. Out0    MVI D,7
  147.  
  148. Out     JMP Err
  149.  
  150. Gf      MVI A,0E0H
  151.  
  152. Gf1     CALL Ovrto
  153.         DB 'Gfid'
  154.         RET
  155.  
  156. ;Parameters for Dio set up by start code
  157. ;Here's where we get the file to be
  158. ;interpretered
  159.  
  160. GETP    CALL Dio        ;Go get it.
  161.         JC Out          ;Something Wrong!
  162.         LXI H,Pgmaddr   ;get the program
  163.         PUSH H
  164.         POP B           ;Set TMPC to first byte
  165.         LHLD TMStack    ;Set initialize TMSP
  166.         LXI D,0         ;First position on stack for
  167.         CALL Push       ;Character in/out
  168.         CALL Push       ;Static link
  169.         INX D
  170.         XCHG
  171.         SHLD Base       ;set Base 1st
  172.         XCHG
  173.         CALL Push       ;Dynamic link same
  174.         LXI D,Origin    ;addr of that 'hlt' byte
  175.         CALL Push
  176.         CALL INB
  177.         CALL OUTB
  178.  
  179. ;This routine sets itself up as a return address
  180.  
  181. GO      PUSH H          ;Return to here
  182.         LXI H,GO
  183.         XTHL            ;Put our addr on stack
  184.         CALL Fetch
  185.         RAL
  186.         JNC branch      ;0 means br or bnz
  187.         RAL
  188.         JNC oprlic
  189.         RAL
  190.         RC              ;111XXXXX is NOP
  191.         CALL GStL       ;For both lad & call
  192.         RAL             ;Now which one
  193.         JC Call         ;do we have?
  194.  
  195. ;Here we have to get the address from
  196. ;the program immediate data (two bytes)
  197.  
  198. Lad     PUSH H
  199.         LHLD Static
  200.         CALL Fetch
  201.         MOV D,A         ;Address hi byte
  202.         CALL Fetch
  203.         MOV E,A         ;Address lo byte
  204.         DAD D           ;Add in the stack base
  205.         XCHG            ;put it in DE
  206.         POP H
  207.         JMP Push        ;Let push return
  208.  
  209. ;This routine puts links on stack
  210. ;followed by return address
  211.  
  212. Call    PUSH H          ;We need TMSP later
  213.         XCHG
  214.         LHLD Static
  215.         XCHG
  216.         CALL Push       ;Static link first
  217.         XCHG
  218.         LHLD Base
  219.         XCHG
  220.         CALL Push       ;Dynamic link second
  221.         XTHL            ;TMSP to stack
  222.         XCHG
  223.         CALL CONV
  224.         XCHG
  225.         SHLD Base       ;Set new base
  226.         CALL Fetch      ;lets get that address
  227.         MOV D,A
  228.         CALL Fetch
  229.         MOV E,A
  230.         LXI H,Pgmaddr
  231.         DAD D
  232.         XTHL            ;Addr to top of stack
  233.         PUSH B
  234.         POP D
  235.         POP B
  236.         JMP Push        ;return address
  237.  
  238. oprlic  RAL             ;Check next bit for oprlic
  239.         JC Lic
  240.  
  241. ;For opr, we must get last 5 bits from inst
  242. ;We'll use a computed goto to get the
  243. ;routine for the sub-operation.
  244.  
  245. opr     LDA Inst
  246.         ANI 1FH
  247.         ADD A           ;Times 2
  248.         MOV E,A
  249.         MVI D,0
  250.         PUSH H          ;save TMSP
  251.         LXI H,Jtbl      ;jmp table
  252.         DAD D           ;add position
  253.         MOV E,M
  254.         INX H
  255.         MOV D,M
  256.         XCHG            ;addr to HL
  257.         XTHL            ;addr to stack
  258.         RET             ;Jump to addr
  259.  
  260. ;Now we've got to sort out the number of
  261. ;bytes used for the constant in this lic
  262.  
  263. Lic     RAL
  264.         JC Lic1
  265.         LDA Inst        ;1 byte
  266.         ANI 0FH
  267.         MVI D,0
  268.         JMP lic4
  269.  
  270. Lic1    RAL
  271.         JC lic2
  272.         LDA Inst        ;2 byte
  273.         ANI 7
  274.         JMP lic3
  275.  
  276. lic2    CALL Fetch      ;3 byte
  277.  
  278. lic3    MOV D,A
  279.         CALL Fetch
  280.  
  281. lic4    MOV E,A
  282.         JMP Push        ;let push RET for us
  283.  
  284. branch  RAL
  285.         JNC Br
  286.         CALL Pop
  287.         MOV A,D
  288.         ORA A
  289.         JNZ Br          ;(bnz)
  290.         ADD E
  291.         JNZ Br          ;(bnz)
  292.         JMP Fetch       ;Skip this byte
  293.                         ;let Fetch return
  294.  
  295. Br      LDA Inst
  296.         ANI 3FH         ;Kill opcode
  297.         MOV D,A         ;Hi addr
  298.         CALL Fetch      ;rest of addr
  299.         MOV E,A         ;Lo addr
  300.         PUSH H
  301.         LXI H,Pgmaddr   ;Adjust for program
  302.         DAD D           ;load address
  303.         XTHL
  304.         POP B
  305.         RET
  306.  
  307. Jtbl    DW Halt         ;0
  308.  
  309. ; Halt closes both the input and the
  310. ; output files before invoking Exec.
  311. ; The input and output file setup routines
  312. ; are restored to IFR and OFR also.
  313.  
  314.         DW addsub       ;1
  315.         DW addsub       ;2
  316.         DW muldiv       ;3
  317.         DW muldiv       ;4
  318.         DW Mod          ;5
  319.         DW Neg          ;6
  320.         DW Not          ;7
  321.         DW Sete         ;8
  322.         DW Setlg        ;9
  323.         DW Setlg        ;A
  324.         DW Swap         ;B
  325.         DW retn         ;C
  326.         DW Rav          ;D
  327.         DW Sto          ;E
  328.         DW inc          ;F
  329.  
  330. IFR     DW INB          ;10
  331.  
  332. ; INB sets up the input file data for Dio
  333. ; and puts the address of Inb into IFR.
  334. ; If a file is not selected, INB puts the
  335. ; address of Cinb into IFR (input from consol)
  336.  
  337. OFR     DW OUTB         ;11
  338.  
  339. ; OUTB sets up the output file data for Dio
  340. ; and puts the address of Outb into OFR.
  341. ; If a file is not selected, OUTB puts the
  342. ; address of Coutb into OFR (output to consol)
  343.  
  344. ;These remaining are all treated as nop
  345.  
  346.         DW Ret          ;12 insurance
  347.         DW Ret          ;13
  348.         DW Ret          ;14
  349.         DW Ret          ;15
  350.         DW Ret          ;16
  351.         DW Ret          ;17
  352.         DW Ret          ;18
  353.         DW Ret          ;19
  354.         DW Ret          ;1A
  355.         DW Ret          ;1B
  356.         DW Ret          ;1C
  357.         DW Ret          ;1D
  358.         DW Ret          ;1E
  359.         DW Ret          ;1F
  360.  
  361. Halt    CALL TURNOFF    ;Close open output file
  362.         LXI H,INB       ;Restore Input file
  363.         SHLD IFR        ;Open sequence
  364.         POP D           ;Clean up stack
  365.         RET
  366.  
  367. addsub  CALL Pop        ;S(t)
  368.         PUSH D
  369.         CALL Pop        ;S(t-1)
  370.         XTHL            ;S(t) to HL
  371.         XCHG            ;S(t) to DE
  372.         LDA Inst
  373.         ANI 2           ;is it a subtract?
  374.         CNZ MinDE
  375.         DAD D           ;S(t-1)-S(t) IN HL
  376.         XCHG
  377.         POP H           ;Get TMSP back
  378.         JMP Push        ;let push return for us
  379.  
  380. muldiv  CALL Pop
  381.         XCHG
  382.         SHLD AR1
  383.         XCHG
  384.         CALL Pop
  385.         XCHG
  386.         SHLD AR2
  387.         LDA Inst
  388.         ANI 4           ;not multiply?
  389.         CZ MULT
  390.         CNZ DIVD
  391.         LHLD AR3
  392.         XCHG
  393.         JMP Push        ;let push return for us
  394.  
  395. MULT    PUSH PSW        ;16 bit multiply
  396.         PUSH B          ;with no overflow test
  397.         PUSH D          ;returns product mod 10000H
  398.         PUSH H
  399.         LHLD AR1
  400.         MOV A,H
  401.         ORA A
  402.         JNZ MULT1
  403.         ADD L
  404.         JZ MULT7
  405.         XCHG
  406.  
  407. MULT1   LHLD AR2
  408.         MOV A,H
  409.         ORA A
  410.         JNZ MULT2
  411.         ADD L
  412.         JZ MULT7
  413.  
  414. MULT2   MOV C,H         ;save hi byte
  415.         MOV A,L         ;do lo byte
  416.         LXI H,0
  417.         MVI B,8
  418.  
  419. MULT3   RRC
  420.         JNC MULT4
  421.         DAD D
  422.  
  423. MULT4   XCHG
  424.         DAD H
  425.         XCHG
  426.         DCR B
  427.         JNZ MULT3
  428.         MOV A,C         ;now do hi byte
  429.         MVI B,8
  430.  
  431. MULT5   RRC
  432.         JNC MULT6
  433.         DAD D
  434.  
  435. MULT6   XCHG
  436.         DAD H
  437.         XCHG
  438.         DCR B
  439.         JNZ MULT5
  440.         JMP MULT8
  441.  
  442. MULT7   LXI H,0
  443.  
  444. MULT8   SHLD AR3
  445.         JMP Ioret
  446.  
  447. DIVD    PUSH PSW
  448.         PUSH B
  449.         PUSH D
  450.         PUSH H
  451.         LXI B,0         ;Result goes here
  452.         LHLD AR1
  453.         MOV A,H         ;lets see if
  454.         ORA A           ;the idiot wants
  455.         JNZ DIVD1       ;to divide by
  456.         ADD L           ;zero.
  457.         JZ DBZER        ;He does!
  458.  
  459. DIVD1   XCHG            ;nope, so get
  460.         LHLD AR2        ;dividend
  461.         MOV A,D         ;If it's
  462.         ORA A           ;zero
  463.         JNZ DIVD2       ;then
  464.         ADD E           ;result's
  465.         JNZ DIVD2       ;also
  466.  
  467. DIVD7   LXI H,0         ;zero
  468.         JMP DIVD6
  469.  
  470. DIVD2   MOV A,H
  471.         CMP D
  472.         JC DIVD4
  473.         JZ DIVD3
  474.         INX B
  475.         JMP SUBT
  476.  
  477. DIVD3   MOV A,L
  478.         CMP E
  479.         JC DIVD4
  480.         INX B
  481.         JZ DIVD4
  482.  
  483. SUBT    PUSH D
  484.         CALL MinDE
  485.         DAD D
  486.         POP D
  487.         JMP DIVD2
  488.  
  489. DIVD4   PUSH B
  490.         POP H
  491.  
  492. DIVD6   SHLD AR3
  493.         JMP Ioret
  494.  
  495. DBZER   CALL DBZ1
  496.         JMP DIVD7
  497.  
  498. DBZ1    LXI H,DBZ
  499.         CALL Msg
  500.         RET
  501.  
  502. Mod     CALL Pop        ;S(t) to DE
  503.         PUSH D          ;S(t) to top of stack
  504.         CALL Pop        ;S(t-1) to DE
  505.         XTHL            ;S(t) to HL
  506.         MOV A,H         ;lets see if
  507.         ORA A           ;the idiot wants
  508.         JNZ Mod1        ;to divide by
  509.         ADD L           ;zero.
  510.         JNZ Mod1
  511.         CALL DBZ1
  512.         JMP Mod3        ;He does!
  513.  
  514. Mod1    MOV A,D         ;see if we
  515.         ORA A           ;start with
  516.         JNZ TEST        ;zero
  517.         ADD E
  518.         JNZ TEST
  519.         JMP Mod3
  520.  
  521. SUBTR   XCHG
  522.         PUSH D          ;Save
  523.         CALL MinDE
  524.         DAD D           ;Add -DE
  525.         POP D           ;Restore
  526.         XCHG
  527. TEST    MOV A,D         ;Hi byte of S(t)
  528.         CMP H
  529.         JC Done         ;Hi byte of S(t-1)
  530.                         ;<Hi byte of S(t)
  531.         JNZ SUBTR       ;its bigger
  532.         MOV A,E         ;It's equal so
  533.         CMP L           ;Check lo byte
  534.         JC Done
  535.         JNZ SUBTR       ;its bigger
  536.  
  537. Mod3    LXI D,0         ;its equal
  538.  
  539. Done    XCHG
  540.         XTHL
  541.         POP D
  542.         JMP Push        ;let push return for us
  543.  
  544. Neg     CALL Pop        ;S(t) to DE
  545.         CALL MinDE
  546.         JMP Push        ;DE to S(t) let push ret
  547.  
  548. Not     CALL Pop        ;look
  549.         MOV A,D         ;hi byte
  550.         ORA A           ;set flags
  551.         JNZ Not2
  552.  
  553. Not1    ADD E           ;lo byte
  554.         JNZ Not2
  555.         LXI D,1         ;its Zero so change result
  556.         JMP Push
  557.  
  558. Not2    LXI D,0
  559.         JMP Push        ;onto stack let
  560.                         ;push ret for us
  561.  
  562. Swap    CALL Pop        ;S(t)
  563.         PUSH D          ;to TOS
  564.         CALL Pop        ;S(t-1) to DE
  565.         XTHL            ;S(t) TO HL, t-1 to TOS
  566.         XCHG            ;S(t) to DE, S(t-1) to HL
  567.         XTHL            ;t-1 to HL, S(t-1) to TOS
  568.         CALL Push       ;S(t-1) to TOS
  569.         POP D           ;S(t-1) to DE
  570.         JMP Push        ;S(t-1) to TMS
  571.                         ;let push return for us.
  572.  
  573. retn    LHLD Base
  574.         LXI D,3
  575.         DAD D
  576.         DAD H
  577.         XCHG
  578.         CALL MinDE
  579.         LHLD TMStack
  580.         DAD D
  581.         CALL Pop        ;TMPC
  582.         PUSH D
  583.         POP B
  584.         CALL Pop        ;Dynamic link
  585.         XCHG
  586.         SHLD Base
  587.         XCHG
  588.         INX H           ;We don't need that
  589.         INX H           ;static link now
  590.         RET
  591.  
  592. Sete    CALL Pop
  593.         PUSH D
  594.         CALL Pop
  595.         XTHL
  596.         MOV A,D
  597.         CMP H
  598.         JNZ SETE1
  599.         MOV A,E
  600.         CMP L
  601.         JNZ SETE1
  602.         LXI D,1         ;they're equal
  603.         POP H
  604.         JMP Push        ;let push return for us
  605.  
  606. SETE1   LXI D,0         
  607.         POP H
  608.         JMP Push        ;let push return for us
  609.  
  610. Setlg   CALL Pop
  611.         PUSH D          ;S(t) to TOS
  612.         CALL Pop        ;S(t-1) to DE
  613.         XTHL            ;S(t) to HL
  614.         LDA Inst
  615.         ANI 2           ;Setgt?
  616.         JZ Set1
  617.         XCHG            ;Reverse for Setgt
  618.  
  619. Set1    CALL MinDE      ;-S(t-1)
  620.         DAD D           ;Want 0<S(t)-S(t-1)
  621.         DCX H           ;Sign test uses >= 0
  622.         MOV A,H         ;Look at sign
  623.         ORA A           ;Set flags
  624.         POP H           ;TMSP
  625.         LXI D,1         ;Assume true
  626.         JP Set2         ;Jump if true
  627.         DCX D           ;Falls thru if false
  628. Set2    JMP Push        ;Let Push return for us
  629.  
  630. ;Note: RAV assumes that the address on the stack
  631. ;is a relative address from the TM stack pointer
  632. ;with 1 for each 16 bit push or pop.  We multiply
  633. ;the two's complement by 2 and add it to
  634. ;the address in TMStack (Top of memory)
  635.  
  636. Rav     CALL Pop        ;Get S(t)
  637.         PUSH H          ;Save SP
  638.         LHLD TMStack
  639.         INX D           ;We need to be above by 1
  640.         CALL MinDE
  641.         DAD D           ;(MEMTOP-2*T)
  642.         DAD D           ;stack address now in hl
  643.         CALL Pop        ;Get S(S(t))
  644.         POP H           ;Restore TMSP
  645.         JMP Push        ;S(t):=S(S(t))
  646.  
  647. Sto     CALL Pop        ;S(t) to be stowed
  648.         PUSH D          ;save it
  649.         CALL Pop        ;address to stow S(t) in
  650.         XTHL            ;(We'll want S(t) first)
  651.         PUSH H          ;Need to use HL
  652.         CALL MinDE      ;Convert Stack
  653.         LHLD TMStack    ;address
  654.         DAD D           ;(MEMTOP-2*T)
  655.         DAD D           ;stack address now in hl
  656.         POP D           ;Get S(t)
  657.         CALL Push       ;S(S(T-1)):=S(T)
  658.         POP H           ;T-2 to TMSP
  659.         RET
  660.  
  661. Inc     CALL Pop        ;S(t) to de, t-1 in HL
  662.         CALL MinDE
  663.         DAD D
  664.         DAD D           ;S(t)+t-1 to HL
  665.         RET
  666.  
  667. INB     PUSH H          ;Save VMSP
  668.         PUSH B          ;Save VMPC
  669.         LXI H,Ifpr      ;get one from him.
  670.  
  671. IFR1    LXI D,FILE      ;File descriptor buffer
  672.         LXI B,'AD'      ;Default file extension
  673.         CALL Gf
  674.         JNC IFR2        ;Gfid found the file
  675.                         ;so go read it
  676.  
  677.         XRA A           ;Checks for error
  678.         ADD D           ;code 0503H
  679.         CPI 5
  680.         JNZ Err         ;Wrong one
  681.         ADD E
  682.         CPI 8           ;adds up to 8
  683.         JNZ Err         ;No good!
  684.         LXI H,Cinb      ;Set up to get input
  685.         SHLD IFR        ;from the consol
  686.         POP B           ;VMPC
  687.         POP H           ;VMSP
  688.         RET
  689.  
  690. ; Additional inputs jump to here
  691.  
  692. Cinb    CALL WH0        ;We're inputting from
  693.         PUSH H          ;the consol
  694.         LHLD TMStack    ;Where it goes
  695.         MOV M,A         ;Put it in
  696.         POP H           ;VMSP
  697.         RET
  698.  
  699. Ifprn   DB CR,'The input file''s empty.'
  700.     DB CR,'What''s the continuation file''s name? ',0
  701.  
  702. Ifpr    DB 'What''s the input file name? ',0
  703.  
  704. IFR2    LXI H,FILE      ;READ starts here
  705.         MOV A,M
  706.         ANI 7           ;trim down to drive no.
  707.         STA IFD         ;Drive number
  708.         INX H
  709.         MOV A,M         ;FDE flag byte
  710.         ANI 1FH         ;trim to file size
  711.         ADI 3           ;point past extension
  712.         MOV E,A         ;Put into DE
  713.         MVI D,0
  714.         DAD D           ;Add to Address in HL
  715.         XCHG            ;FDA pointer now in DE
  716.         LXI H,IFA       ;Where the addresses go
  717.         MVI C,4         ;4 bytes to copy
  718.  
  719. CIFD    LDAX D          ;Get the data
  720.         MOV M,A         ;from the FDB (FILE)
  721.         INX H           ;and copy into the
  722.         INX D           ;areas for our Dio
  723.         DCR C           ;routines
  724.         JNZ CIFD        ;More to copy
  725.         LXI H,IFB+100H  ;Reset the
  726.         SHLD IFP        ;buffer pointer too
  727.         LXI H,Inb       ;Furthur calls to Reader
  728.         SHLD IFR        ;the reader
  729.         POP B           ;VMPC
  730.         POP H           ;VMSP
  731.         RET
  732.  
  733. ; Routine to input from an open file
  734.  
  735. Inb     PUSH H          ;Save VMSP
  736.         PUSH B          ;Save VMPC
  737.  
  738. RD1     LHLD IFP
  739.         LXI D,IFB+100H
  740.         MOV A,H
  741.         CMP D
  742.         JNZ RD2
  743.         MOV A,L
  744.         CMP E
  745.         JZ RD3
  746.  
  747. RD2     MOV A,M
  748.         INX H
  749.         SHLD IFP
  750.         POP B           ;VMPC
  751.         LHLD TMStack    ;Here's where
  752.         MOV M,A         ;we put it
  753.         POP H           ;VMSP
  754.         RET
  755.  
  756. RD3     LHLD IFS
  757.         MOV A,H
  758.         ORA A
  759.         JNZ RD4
  760.         ORA L
  761.         JNZ RD4
  762.  
  763. ; We've reached the end of the input file
  764. ; so, we ask for another one
  765.  
  766.         LXI H,Ifprn
  767.         JMP IFR1
  768.  
  769. RD4     DCX H           ;Got to get another
  770.         SHLD IFS        ;sector from disk
  771.         LXI H,IFB
  772.         SHLD IFP
  773.         PUSH D
  774.         XCHG
  775.         LHLD IFA        ;Get disk address
  776.         INX H           ;update for next time
  777.         SHLD IFA        ;and save
  778.         DCX H           ;back to the one we want
  779.         PUSH B          ;going to preserve B
  780.         MVI B,1         ;Read
  781.         LDA IFD         ;Drive for input file
  782.         MOV C,A         ;into C
  783.         MVI A,1         ;1 sector
  784.         CALL Dio        ;Get it
  785.         POP B           ;restore
  786.         POP D           ;this too
  787.         JNC RD1         ;Now we can get another byte
  788.         JMP Err
  789.  
  790. Ofpr    DB 'What''s the output file name? ',0
  791.  
  792. CK1     CPI 3           ;Now lets check
  793.         JNZ Err         ;for the 0503 error
  794.         ADD D
  795.         CPI 8           ;adds up to 8
  796.         JNZ Err         ;No good!
  797.         LXI H,Coutb
  798.         SHLD OFR
  799.         POP B           ;VMPC
  800.         POP H           ;VMSP
  801.         RET
  802.  
  803. ; Ouputs jump to here
  804.  
  805. Coutb   PUSH H          ;We're outputting to the consol
  806.         LHLD TMStack
  807.         MOV A,M
  808.         CALL WH1
  809.         POP H
  810.         RET
  811.  
  812. OUTB    PUSH H          ;Save VMSP
  813.         PUSH B          ;Save VMPC
  814.         LXI H,Ofpr      ;get one from him.
  815.         LXI D,FDB       ;File descriptor buffer
  816.         LXI B,'AI'      ;('AI' is default ext)
  817.         CALL Gf
  818.         JNC Out2
  819.         XRA A           ;Checks for error
  820.         ADD E           ;code 0300H or 0503H
  821.         JNZ CK1         ;Does not return
  822.         ADD D           ;unless one was
  823.         CPI 3           ;found. Sets CARRY
  824.         JNZ Err         ;Need to have
  825.                         ;a 0300 error
  826.         LXI H,FDB       ;We need to save this
  827.                         ;for close
  828.         MOV A,M
  829.         ANI 7           ;trim down to drive no.
  830.         STA OFD         ;Drive number
  831.         INX H
  832.         MOV A,M         ;FDE flag byte
  833.         ANI 1FH         ;trim to file size
  834.         ADI 3           ;point past extension
  835.         MOV E,A         ;Put into DE
  836.         MVI D,0
  837.         DAD D           ;Add to Address in HL
  838.         XCHG            ;FDA pointer now in DE
  839.         LXI H,OFA       ;Where the addresses go
  840.         MVI C,4         ;4 bytes to copy
  841.  
  842. COFD    LDAX D          ;Get the data
  843.         MOV M,A         ;from the FDB
  844.         INX H           ;and copy into the
  845.         INX D           ;areas for our Dio
  846.         DCR C           ;routines
  847.         JNZ COFD        ;More to copy
  848.         LXI H,OFB       ;Reset the
  849.         SHLD OFP        ;buffer pointer too
  850.         LXI H,Outb      ;characters thru
  851.         SHLD OFR
  852.         POP B           ;VMPC
  853.         POP H           ;VMSP
  854.         RET
  855.  
  856. ; Routine to output to an open file
  857. ; thru calls to Outb
  858.  
  859. Outb    PUSH PSW        ;For writing
  860.         PUSH B
  861.         PUSH D
  862.         PUSH H
  863.         LXI H,Ioret
  864.         PUSH H
  865.         LHLD TMStack    ;Get the char
  866.         MOV A,M
  867.  
  868. ;The rest of this is called as a subroutine for
  869. ;filling up the last sector with zeros also.
  870.  
  871. Store   LHLD OFP
  872.         MOV M,A         ;put char in buffer
  873.         LXI D,Flag
  874.         LDAX D
  875.         ORA A
  876.         JNZ Store1
  877.         DCR A           ;We've been had!
  878.         STAX D
  879.  
  880. Store1  INX H           ;bump pointer
  881.         SHLD OFP
  882.         LXI D,OFB
  883.         DCR H
  884.         MOV A,H
  885.         CMP D
  886.         RNZ
  887.         MOV A,L
  888.         CMP E
  889.         RNZ
  890.  
  891. ;pointer now points at OFB so do DIO.
  892.  
  893.         SHLD OFP        ;DE points at OFB
  894.         LHLD OFS        ;Number of sectors
  895.         INX H           ;One more
  896.         SHLD OFS
  897.         LHLD OFA        ;Disk address
  898.         INX H           ;Up date for next time
  899.         SHLD OFA
  900.         DCX H           ;Here's where we write
  901.         LDA OFD         ;Drive
  902.         MOV C,A         ;Drive no.
  903.         MVI B,0         ;Write
  904.         MVI A,1         ;one sector
  905.         CALL Dio
  906.         JC Err
  907.         RET
  908.  
  909. ; Routines for closing the file
  910.  
  911. TURNOFF PUSH H          ;Save VMSP
  912.         PUSH B          ;Save VMPC
  913.         LDA Flag        ;See if we're
  914.                         ;still Virgin.
  915.         ORA A           ;(Also for closing
  916.         JZ TO1          ;a read file.)
  917. Fill    LDA OFP         ;Not virgin,
  918.         CPI OFB AND 0FFH
  919.         MVI A,0
  920.         JZ Close1
  921.         CALL Store      ;fill up last sector
  922.         JMP Fill        ;with zeros
  923.  
  924. Close1  LXI H,FDB+1
  925.         MOV A,M
  926.         ANI 1FH         ;strip down to length
  927.         ADI 5           ;Point past ext and FDA
  928.         MOV E,A
  929.         MVI D,0
  930.         DAD D
  931.         XCHG            ;adr of DNS now in DE
  932.         LHLD OFS
  933.         XCHG
  934.         MOV M,E
  935.         INX H
  936.         MOV M,D         ;length now updated
  937.         LXI H,FDB
  938.         MOV A,M
  939.         ANI 7FH
  940.         MOV M,A
  941.         MVI A,1         ;enter new output
  942.                         ;file in directory
  943.         CALL Gf1
  944.         JC Err
  945. TO1     XRA A           ;Virgin exit.
  946.         STA Flag
  947. Out1    LXI H,OUTB      ;Restore calling address
  948.         SHLD OFR        ;to open a file
  949.         POP B           ;VMPC
  950.         POP H           ;VMSP
  951.         RET
  952.  
  953. Origin  hlt     ;L0 MACRO instruction
  954. Origin  DB 80H
  955. Pgmaddr EQU $
  956.  
  957. ; We load the executable file on top
  958. ;of the Start code !!
  959.  
  960. Start   LHLD MEMTOP
  961.         SHLD TMStack
  962.         LXI H,USER
  963.         MVI M,RET       ;Don't START again
  964.         LHLD CMPTR      ;Cmd pointer
  965.         MOV A,M
  966.         CPI CR
  967.         JZ Out3
  968.         LXI D,FDB       ;File descriptor block
  969.                         ;built by Gfid
  970.         LXI B,4C30H     ;L/0 extension for
  971.                         ;default is L0
  972.         MVI A,60H
  973.         CALL Gf1
  974.         JC Out          ;Something Wrong!
  975.         LXI H,FDB
  976.         MOV A,M
  977.         ANI 7           ;Kill flags
  978.         MOV M,A
  979.         INX H           ;Move up to FDE flags.
  980.         MOV A,M
  981.         ANI 1FH         ;Kill flags
  982.         ADI 3           ;Point past ext
  983.         MOV E,A
  984.         MVI D,0
  985.         DAD D           ;Addr of FDA
  986.         MOV E,M
  987.         INX H
  988.         MOV D,M
  989.         INX H
  990.         LDA FDB
  991.         MOV C,A         ;Drive to C
  992.         MVI B,1         ;Read
  993.         MOV A,M         ;DNS
  994.         XCHG            ;FDA to HL
  995.         LXI D,Pgmaddr   ;Where to put it
  996.         JMP GETP
  997.  
  998.         END
  999.  
  1000.