home *** CD-ROM | disk | FTP | other *** search
/ norge.freeshell.org (192.94.73.8) / 192.94.73.8.tar / 192.94.73.8 / pub / computers / cpm / alphatronic / DRIPAK.ZIP / CPM_3-0 / SOURCES / LOADER3.ASM < prev    next >
Assembly Source File  |  1982-12-31  |  17KB  |  738 lines

  1. title    'CP/M 3 - PROGRAM LOADER RSX - November 1982'
  2. ;    version 3.0b  Nov 04 1982 - Kathy Strutynski
  3. ;    version 3.0c  Nov 23 1982 - Doug Huskey
  4. ;                  Dec 22 1982 - Bruce Skidmore
  5. ;
  6. ;
  7. ;    copyright (c) 1982
  8. ;    digital research
  9. ;    box 579
  10. ;    pacific grove, ca.
  11. ;    93950
  12. ;
  13.      ****************************************************
  14.      *****  The following values must be placed in    ***
  15.      *****  equates at the front of CCP3.ASM.         ***
  16.      *****                                            ***
  17.      *****  Note: Due to placement at the front these ***
  18.      *****  equates cause PHASE errors which can be   ***
  19.      *****  ignored.                                  ***
  20. equ1    equ    rsxstart +0100h  ;set this equate in the CCP
  21. equ2    equ    fixchain +0100h  ;set this equate in the CCP
  22. equ3    equ    fixchain1+0100h  ;set this equate in the CCP
  23. equ4    equ    fixchain2+0100h  ;set this equate in the CCP
  24. equ5    equ    rsx$chain+0100h  ;set this equate in the CCP
  25. equ6    equ    reloc    +0100h  ;set this equate in the CCP
  26. equ7    equ    calcdest +0100h  ;set this equate in the CCP
  27. equ8    equ    scbaddr     +0100h  ;set this equate in the CCP
  28. equ9    equ    banked     +0100h  ;set this equate in the CCP
  29. equ10    equ    rsxend     +0100h  ;set this equate in the CCP
  30. ccporg    equ    CCP         ;set origin to this in CCP
  31. patch    equ    patcharea+0100h  ;LOADER patch area
  32.  
  33. CCP    equ    41Ah         ;ORIGIN OF CCP3.ASM
  34.  
  35.  
  36.      ****************************************************
  37.  
  38. ;    conditional assembly toggles:
  39.  
  40. true        equ    0ffffh
  41. false        equ    0h
  42. spacesaver    equ    true
  43.  
  44. stacksize    equ    32        ;16 levels of stack
  45. version        equ    30h
  46. tpa        equ    100h
  47. ccptop        equ    0Fh        ;top page of CCP
  48. osbase        equ    06h        ;base page in BDOS jump
  49. off$nxt        equ    10        ;address in next jmp field
  50. currec        equ    32        ;current record field in fcb
  51. ranrec        equ    33        ;random record field in fcb
  52.  
  53.  
  54.  
  55. ;
  56. ;
  57. ;     dsect for SCB
  58. ;
  59. bdosbase    equ    98h        ; offset from page boundary
  60. ccpflag1    equ    0b3h        ; offset from page boundary
  61. multicnt    equ    0e6h        ; offset from page boundary
  62. rsx$only$clr    equ    0FDh        ;clear load RSX flag
  63. rsx$only$set    equ    002h
  64. rscbadd        equ    3ah        ;offset of scbadd in SCB
  65. dmaad        equ    03ch        ;offset of DMA address in SCB
  66. bdosadd        equ    62h        ;offset of bdosadd in SCB
  67. ;
  68. loadflag    equ    02H        ;flag for LOADER in memory
  69. ;
  70. ;     dsect for RSX
  71. entry        equ    06h        ;RSX contain jump to start
  72. ;
  73. nextadd        equ    0bh        ;address of next RXS in chain
  74. prevadd        equ    0ch        ;address of previous RSX in chain
  75. warmflg        equ    0eh        ;remove on wboot flag
  76. endchain    equ    18h        ;end of RSX chain flag
  77. ;
  78. ;
  79. readf    equ    20    ;sequential read
  80. dmaf    equ    26    ;set DMA address
  81. scbf    equ    49    ;get/set SCB info
  82. loadf    equ    59    ;load function
  83. ;
  84. ;
  85. maxread    equ    64    ;maximum of 64 pages in MULTIO
  86. ;
  87. ;
  88. wboot    equ    0000h    ;BIOS warm start
  89. bdos    equ    0005h    ;bdos entry point
  90. print    equ    9    ;bdos print function
  91. vers    equ    12    ;get version number
  92. module    equ    200h    ;module address
  93. ;
  94. ;    DSECT for COM file header
  95. ;
  96. comsize    equ    tpa+1h
  97. scbcode    equ    tpa+3h
  98. rsxoff    equ    tpa+10h
  99. rsxlen    equ    tpa+12h
  100. ;
  101. ;
  102. cr    equ    0dh
  103. lf    equ    0ah
  104. ;
  105. ;
  106.     cseg
  107. ;
  108. ;
  109. ;     ********* LOADER  RSX HEADER ***********
  110. ;
  111. rsxstart:
  112.     jmp    ccp        ;the ccp will move this loader to 
  113.     db    0,0,0        ;high memory, these first 6 bytes
  114.                 ;will receive the serial number from
  115.                 ;the 6 bytes prior to the BDOS entry
  116.                 ;point
  117. tojump:
  118.     jmp    begin
  119. next    db    0c3h        ;jump to next module
  120. nextjmp    dw    06
  121. prevjmp    dw    07
  122.     db    0        ;warm start flag
  123.     db    0        ;bank flag
  124.     db    'LOADER  '    ;RSX name
  125.     db    0ffh        ;end of RSX chain flag
  126.     db    0        ;reserved
  127.     db    0        ;patch version number
  128.  
  129. ;     ********* LOADER  RSX ENTRY POINT ***********
  130.  
  131. begin:
  132.     mov    a,c
  133.     cpi    loadf
  134.     jnz    next
  135. beginlod:
  136.     pop    b
  137.     push    b        ;BC = return address
  138.     lxi    h,0        ;switch stacks
  139.     dad    sp
  140.     lxi    sp,stack    ;our stack
  141.     shld    ustack        ;save user stack address
  142.     push    b        ;save return address
  143.     xchg            ;save address of user's FCB
  144.     shld    usrfcb
  145.     mov    a,h        ;is .fcb = 0000h
  146.     ora    l
  147.     push    psw
  148.     cz    rsx$chain    ;if so , remove RSXs with remove flag on
  149.     pop    psw
  150.     cnz    loadfile
  151.     pop    d        ;return address
  152.     lxi    h,tpa
  153.     mov    a,m
  154.     cpi    ret
  155.     jz    rsxfile
  156.     mov    a,d        ;check return address
  157.     dcr    a        ; if CCP is calling 
  158.     ora    e        ; it will be 100H
  159.     jnz    retuser1    ;jump if not CCP
  160. retuser:
  161.     lda    prevjmp+1    ;get high byte
  162.     ora    a        ;is it the zero page (i.e. no RSXs present)
  163.     jnz    retuser1    ;jump if not
  164.     lhld    nextjmp        ;restore five....don't stay arround
  165.     shld    osbase
  166.      shld    newjmp
  167.     call    setmaxb
  168. retuser1:
  169.     lhld    ustack        ;restore the stack
  170.     sphl
  171.     xra    a
  172.     mov    l,a
  173.     mov    h,a        ;A,HL=0 (successful return)
  174.     ret            ;CCP pushed 100H on stack
  175. ;
  176. ;
  177. ;    BDOS FUNC 59 error return
  178. ;
  179. reterror:
  180.     lxi    d,0feh
  181. reterror1:
  182.     ;DE = BDOS error return
  183.     lhld    ustack
  184.     sphl
  185.     pop    h        ;get return address
  186.     push    h
  187.     dcr    h        ;is it 100H?
  188.     mov    a,h
  189.     ora    l
  190.     xchg            ;now HL = BDOS error return
  191.     mov    a,l
  192.     mov    b,h
  193.     rnz            ;return if not the CCP
  194. ;
  195. ;
  196. loaderr:
  197.     mvi    c,print
  198.     lxi    d,nogo        ;cannot load program
  199.     call    bdos        ;to print the message
  200.     jmp    wboot        ;warm boot
  201.  
  202. ;
  203. ;
  204. ;;
  205. ;************************************************************************
  206. ;
  207. ;    MOVE RSXS TO HIGH MEMORY
  208. ;
  209. ;************************************************************************
  210. ;
  211. ;
  212. ;      RSX files are present
  213. ;
  214.     
  215. rsxf1:    inx    h
  216.     mov    c,m
  217.     inx    h
  218.     mov    b,m        ;BC contains RSX length
  219.     lda    banked
  220.     ora    a        ;is this the non-banked system?
  221.     jz    rsxf2        ;jump if so
  222.     inx    h        ;HL = banked/non-banked flag
  223.     inr    m        ;is this RSX only for non-banked?
  224.     jz    rsxf3        ;skip if so
  225. rsxf2:    push    d        ;save offset
  226.     call    calcdest    ;calculate destination address and bias
  227.     pop    h        ;rsx offset in file
  228.     call    reloc        ;move and relocate file
  229.     call    fixchain    ;fix up rsx address chain
  230. rsxf3:    pop    h        ;RSX length field in header
  231.  
  232.  
  233. rsxfile:
  234.     ;HL = .RSX (n-1) descriptor 
  235.     lxi    d,10h        ;length of RSX descriptor in header
  236.     dad    d        ;HL = .RSX (n) descriptor
  237.     push    h        ;RSX offset field in COM header
  238.     mov    e,m
  239.     inx    h
  240.     mov    d,m        ;DE = RSX offset
  241.     mov    a,e
  242.     ora     d
  243.     jnz    rsxf1        ;jump if RSX offset is non-zero
  244. ;
  245. ;
  246. ;
  247. comfile:
  248.     ;RSXs are in place, now call SCB setting code 
  249.     call    scbcode        ;set SCB flags for this com file
  250.     ;is there a real COM file?
  251.     lda    module        ;is this an RSX only
  252.     cpi    ret
  253.     jnz    comfile2    ;jump if real COM file
  254.     lhld    scbaddr
  255.     mvi    l,ccpflag1
  256.     mov    a,m
  257.     ori    rsx$only$set    ;set if RSX only
  258.      mov    m,a
  259. comfile2:
  260.     lhld    comsize        ;move COM module to 100H
  261.     mov    b,h
  262.     mov    c,l        ;BC contains length of COM module
  263.     lxi    h,tpa+100h    ;address of source for COM move to 100H
  264.     lxi    d,tpa        ;destination address
  265.     call    move
  266.     jmp    retuser1        ;restore stack and return
  267. ;;
  268. ;************************************************************************
  269. ;
  270. ;    ADD AN RSX TO THE CHAIN
  271. ;
  272. ;************************************************************************
  273. ;
  274. ;
  275. fixchain:
  276.     lhld    osbase        ;next RSX link
  277.     mvi    l,0
  278.     lxi    b,6
  279.     call    move        ;move serial number down
  280.     mvi    e,endchain
  281.     stax    d        ;set loader flag=0
  282.     mvi    e,prevadd+1
  283.     stax    d        ;set previous field to 0007H
  284.     dcx    d
  285.     mvi    a,7
  286.     stax    d        ;low byte = 7H
  287.     mov    l,e        ;HL address previous field in next RSX
  288.     mvi    e,nextadd    ;change previous field in link
  289.     mov    m,e
  290.     inx    h
  291.     mov    m,d        ;current <-- next
  292. ;
  293. fixchain1:
  294.     ;entry:    H=next RSX page, 
  295.     ;    DE=.(high byte of next RSX field) in current RSX
  296.     xchg            ;HL-->current  DE-->next
  297.     mov    m,d        ;put page of next RSX in high(next field)
  298.     dcx    h
  299.     mvi    m,6
  300. ;
  301. fixchain2:
  302.     ;entry:    H=page of lowest active RSX in the TPA
  303.     ;this routine resets the BDOS address @ 6H and in the SCB
  304.     mvi    l,6
  305.     shld    osbase        ;change base page BDOS vector
  306.     shld    newjmp        ;change SCB value for BDOS vector
  307. ;
  308. ;
  309. setmaxb:
  310.     lxi    d,scbadd2
  311. scbfun:
  312.     mvi    c,scbf
  313.     jmp    bdos
  314. ;
  315. ;
  316. ;;
  317. ;************************************************************************
  318. ;
  319. ;    REMOVE TEMPORARY RSXS
  320. ;
  321. ;************************************************************************
  322. ;
  323. ;
  324. ;
  325. rsx$chain:
  326.     ;
  327.     ;    Chase up RSX chain, removing RSXs with the
  328.     ;    remove flag on (0FFH)
  329.     ;
  330.     lhld    osbase            ;base of RSX chain
  331.     mov    b,h
  332.  
  333. rsx$chain1:
  334.     ;B  = current RSX
  335.     mov    h,b
  336.     mvi    l,endchain
  337.     inr    m
  338.     dcr    m            ;is this the loader?
  339.     rnz                ;return if so (m=0ffh)
  340.     mvi    l,nextadd        ;address of next node
  341.     mov    b,m            ;DE -> next link
  342. ;
  343. ;
  344. check$remove:
  345. ;
  346.     mvi    l,warmflg        ;check remove flag
  347.      mov    a,m            ;warmflag in A
  348.     ora    a            ;FF if remove on warm start
  349.     jz    rsx$chain1        ;check next RSX if not
  350. ;
  351. remove:
  352.         ;remove this RSX from chain
  353. ;
  354.     ;first change next field of prior link to point to next RSX
  355.     ;HL = current  B = next
  356. ;
  357.     mvi    l,prevadd
  358.     mov    e,m            ;address of previous RSX link
  359.     inx    h
  360.     mov    d,m
  361.     mov    a,b            ;A = next (high byte)
  362.     stax    d            ;store in previous link
  363.     dcx    d            ;previous RSX chains to next RSX
  364.     mvi    a,6            ;initialize low byte to 6
  365.     stax    d            ;
  366.     inx    d            ;DE = .next (high byte)
  367. ;
  368.     ;now change previous field of next link to address previous RSX
  369.     mov    h,b            ;next in HL...previous in DE
  370.     mvi    l,prevadd
  371.     mov    m,e
  372.     inx    h
  373.     mov    m,d            ;next chained back to previous RSX
  374.     mov    a,d            ;check to see if this is the bottom
  375.     ora    a            ;RSX...
  376.     push    b
  377.     cz    fixchain2        ;reset BDOS BASE to page in H
  378.     pop    b
  379.     jmp    rsx$chain1        ;check next RSX in the chain
  380. ;
  381. ;
  382. ;;
  383. ;************************************************************************
  384. ;
  385. ;    PROGRAM LOADER
  386. ;
  387. ;************************************************************************
  388. ;
  389. ;
  390. ;
  391. loadfile:
  392. ;    entry: HL = .FCB
  393.     push    h
  394.     lxi    d,scbdma        
  395.     call    scbfun
  396.     xchg
  397.     pop    h            ;.fcb
  398.     push    h            ;save .fcb
  399.     lxi    b,currec
  400.     dad    b
  401.     mvi    m,0            ;set current record to 0
  402.     inx    h
  403.     mov    c,m            ;load address 
  404.     inx    h
  405.     mov    h,m
  406.     mov    l,c
  407.     dcr    h
  408.     inr    h    
  409.     jz    reterror        ;Load address < 100h
  410.     push    h            ;now save load address
  411.     push    d            ;save the user's DMA
  412.     push    h
  413.     call    multio1            ;returns A=multio
  414.     pop    h
  415.     push    psw            ;save A = user's multisector I/O
  416.     mvi    e,128            ;read 16k
  417.  
  418.     ;stack:        |return address|
  419.     ;        |.FCB          |
  420.     ;        |Load address  |
  421.     ;        |users DMA     |
  422.     ;        |users Multio  |
  423.     ;
  424.  
  425. loadf0:
  426.     ;HL= next load address (DMA)
  427.     ; E= number of records to read
  428.     lda    osbase+1        ;calculate maximum number of pages
  429.     dcr    a
  430.     sub    h
  431.     jc    endload            ;we have used all we can
  432.     inr    a
  433.     cpi    maxread            ;can we read 16k?
  434.     jnc    loadf2
  435.     rlc                ;change to sectors
  436.     mov    e,a            ;save for multi i/o call
  437.     mov    a,l            ;A = low(load address)
  438.     ora    a
  439.     jz    loadf2            ;load on a page boundary
  440.     mvi    b,2            ;(to subtract from # of sectors)
  441.     dcr    a            ;is it greater than 81h?
  442.     jm    subtract        ;080h < l(adr) <= 0FFh (subtract 2)
  443.     dcr    b            ;000h < l(adr) <= 080h (subtract 1)
  444. subtract:
  445.     mov    a,e            ;reduce the number of sectors to
  446.     sub    b            ;compensate for non-page aligned
  447.                     ;load address
  448.     jz    endload            ;can't read zero sectors
  449.     mov    e,a
  450. ;
  451. loadf2:
  452.     ;read the file
  453.     push    d            ;save number of records to read
  454.     push    h            ;save load address
  455.     call    multio            ;set multi-sector i/o
  456.     pop    h
  457.     push    h
  458.     call    readb            ;read sector
  459.     pop    h
  460.     pop    d            ;restore number of records
  461.     push    psw            ;zero flag set if no error
  462.     mov    a,e            ;number of records in A
  463.     inr    a
  464.     rar                ;convert to pages
  465.     add    h
  466.     mov    h,a            ;add to load address
  467.     shld    loadtop            ;save next free page address
  468.     pop    psw
  469.     jz    loadf0            ;loop if more to go
  470.  
  471. loadf4:
  472.     ;FINISHED load  A=1 if successful (eof)
  473.     ;        A>1 if a I/O error occured
  474.     ;
  475.     pop    b            ;B=multisector I/O count
  476.     dcr    a            ;not eof error?
  477.     mov    e,b            ;user's multisector count
  478.     call    multio
  479.     mvi    c,dmaf            ;restore the user's DMA address
  480.     pop    d    
  481.     push    psw            ;zero flag => successful load
  482.     call    bdos            ; user's DMA now restored
  483.     pop    psw
  484.     lhld    bdosret            ;BDOS error return
  485.     xchg
  486.     jnz    reterror1
  487.     pop    d            ;load address    
  488.     pop    h            ;.fcb
  489.     lxi    b,9            ;is it a PRL?
  490.     dad    b            ;.fcb(type)
  491.     mov    a,m
  492.     ani    7fh            ;get rid of attribute bit
  493.     cpi    'P'            ;is it a P?
  494.     rnz                ;return if not
  495.     inx    h
  496.     mov    a,m
  497.     ani    7fh
  498.     cpi    'R'            ;is it a R
  499.     rnz                ;return if not
  500.     inx    h
  501.     mov    a,m
  502.     ani    7fh
  503.     sui    'L'            ;is it a L?
  504.     rnz                ;return if not
  505.     ;load PRL file
  506.     mov    a,e
  507.     ora    a            ;is load address on a page boundary
  508.     jnz    reterror        ;error, if not
  509.     mov    h,d
  510.     mov    l,e            ;HL,DE = load address
  511.     inx    h
  512.     mov    c,m
  513.     inx    h
  514.     mov    b,m
  515.     mov    l,e            ;HL,DE = load address BC = length
  516. ;    jmp    reloc            ;relocate PRL file at load address
  517. ;
  518. ;;
  519. ;************************************************************************
  520. ;
  521. ;    PAGE RELOCATOR
  522. ;
  523. ;************************************************************************
  524. ;
  525. ;
  526. reloc:
  527. ;    HL,DE = load address (of PRL header)
  528. ;    BC    = length of program (offset of bit map)
  529.     inr    h        ;offset by 100h to skip header
  530.     push    d        ;save destination address
  531.     push    b        ;save length in bc
  532.     call    move        ;move rsx to correct memory location
  533.     pop    b
  534.     pop    d
  535.     push    d        ;save DE for fixchain...base of RSX
  536.     mov    e,d        ;E will contain the BIAS from 100h
  537.     dcr    e        ;base address is now 100h
  538.                 ;after move HL addresses bit map
  539.     ;
  540.     ;storage moved, ready for relocation
  541.     ;    HL addresses beginning of the bit map for relocation
  542.     ;    E contains relocation bias
  543.     ;    D contain relocation address
  544.     ;    BC contains length of code
  545. rel0:    push    h    ;save bit map base in stack
  546.     mov    h,e    ;relocation bias is in e
  547.     mvi    e,0
  548. ;
  549. rel1:    mov    a,b    ;bc=0?
  550.     ora    c
  551.     jz    endrel
  552. ;
  553. ;    not end of the relocation, may be into next byte of bit map
  554.      dcx    b    ;count length down
  555.     mov    a,e
  556.     ani    111b    ;0 causes fetch of next byte
  557.     jnz    rel2
  558. ;    fetch bit map from stacked address
  559.     xthl
  560.     mov    a,m    ;next 8 bits of map
  561.     inx    h
  562.     xthl        ;base address goes back to stack
  563.     mov    l,a    ;l holds the map as we process 8 locations
  564. rel2:    mov    a,l
  565.     ral        ;cy set to 1 if relocation necessary
  566.     mov    l,a    ;back to l for next time around
  567.     jnc    rel3    ;skip relocation if cy=0
  568. ;
  569. ;    current address requires relocation
  570.     ldax    d
  571.     add    h    ;apply bias in h
  572.     stax    d
  573. rel3:    inx    d    ;to next address
  574.     jmp    rel1    ;for another byte to relocate
  575. ;
  576. endrel:    ;end of relocation
  577.     pop    d    ;clear stacked address
  578.     pop    d    ;restore DE to base of PRL
  579.     ret
  580.  
  581.  
  582. ;
  583. ;;
  584. ;************************************************************************
  585. ;
  586. ;    PROGRAM LOAD TERMINATION
  587. ;
  588. ;************************************************************************
  589. ;
  590. ;;    
  591. ;;
  592. endload:
  593.     call    multio1        ;try to read after memory is filled
  594.     lxi    h,80h        ;set load address = default buffer
  595.     call    readb
  596.     jnz    loadf4        ;eof => successful
  597.     lxi    h,0feh        ;set BDOSRET to indicate an error
  598.     shld    bdosret
  599.     jmp    loadf4        ;unsuccessful (file to big)
  600. ;
  601. ;;
  602. ;
  603. ;;
  604. ;************************************************************************
  605. ;
  606. ;    SUBROUTINES
  607. ;
  608. ;************************************************************************
  609. ;
  610. ;
  611. ;
  612. ;    Calculate RSX base in the top of the TPA
  613. ;
  614. calcdest:
  615. ;
  616. ;    calcdest returns destination in DE
  617. ;    BC contains length of RSX
  618. ;
  619.     lda    osbase+1    ;a has high order address of memory top
  620.     dcr    a        ;page directly below bdos
  621.     dcx    b        ;subtract 1 to reflect last byte of code
  622.     sub    b        ;a has high order address of reloc area
  623.     inx    b        ;add 1 back get bit map offset
  624.     cpi    ccptop        ;are we below the CCP
  625.     jc    loaderr
  626.     lhld    loadtop
  627.     cmp    h        ;are we below top of this module
  628.     jc    loaderr
  629.     mov    d,a
  630.     mvi    e,0        ;d,e addresses base of reloc area
  631.     ret
  632. ;
  633. ;;
  634. ;;-----------------------------------------------------------------------
  635. ;;
  636. ;;    move memory routine
  637.  
  638. move:
  639. ;    move source to destination
  640. ;    where source is in HL and destination is in DE
  641. ;    and length is in BC
  642. ;
  643.     mov    a,b    ;bc=0?
  644.     ora    c
  645.     rz
  646.     dcx    b    ;count module size down to zero
  647.     mov    a,m    ;get next absolute location
  648.     stax    d    ;place it into the reloc area
  649.     inx    d
  650.     inx    h
  651.     jmp    move
  652. ;;
  653. ;;-----------------------------------------------------------------------
  654. ;;
  655. ;;    Multi-sector I/O 
  656. ;;    (BDOS function #44)
  657. ;
  658. multio1:
  659.     mvi    e,1        ;set to read 1 sector
  660. ;
  661. multio:
  662.     ;entry: E = new multisector count
  663.     ;exit:    A = old multisector count
  664.     lhld    scbaddr
  665.     mvi    l,multicnt
  666.     mov    a,m
  667.     mov    m,e
  668.     ret    
  669. ;;
  670. ;;-----------------------------------------------------------------------
  671. ;;
  672. ;;    read file 
  673. ;;    (BDOS function #20)
  674. ;;
  675. ;;    entry:    hl = buffer address (readb only)
  676. ;;    exit    z  = set if read ok
  677. ;;
  678. readb:    xchg
  679. setbuf:    mvi    c,dmaf
  680.     push    h        ;save number of records
  681.     call    bdos
  682.     mvi    c,readf
  683.     lhld    usrfcb
  684.     xchg
  685.     call    bdos
  686.     shld    bdosret        ;save bdos return
  687.     pop    d        ;restore number of records
  688.     ora    a
  689.     rz                ;no error on read
  690.     mov    e,h        ;change E to number records read
  691.     ret
  692. ;
  693. ;
  694. ;************************************************************************
  695. ;
  696. ;    DATA AREA
  697. ;
  698. ;************************************************************************
  699. ;
  700.  
  701. nogo    db    cr,lf,'Cannot load Program$'
  702.  
  703. patcharea:
  704.     ds    36            ;36 byte patch area
  705.  
  706. scbaddr    dw    0
  707. banked    db    0
  708.  
  709. scbdma    db    dmaad
  710.     db    00h            ;getting the value
  711. scbadd2    db    bdosadd            ;current top of TPA
  712.     db    0feh            ;set the value
  713. ;
  714.  
  715.     if not spacesaver
  716.  
  717. newjmp    ds    2            ;new BDOS vector
  718. loadtop    ds    2            ;page above loaded program
  719. usrfcb    ds    2            ;contains user FCB add
  720. ustack:    ds    2            ; user stack on entry
  721. bdosret    ds    2            ;bdos error return
  722. ;
  723. rsxend    :
  724. stack    equ    rsxend+stacksize
  725.  
  726.     else
  727.  
  728. rsxend:
  729. newjmp    equ    rsxend
  730. loadtop    equ    rsxend+2
  731. usrfcb    equ    rsxend+4
  732. ustack    equ    rsxend+6
  733. bdosret    equ    rsxend+8
  734. stack    equ    rsxend+10+stacksize
  735.  
  736.     endif
  737.     end
  738.