home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / PROGRAMS / SORT / SORTV14.ASM < prev    next >
Assembly Source File  |  2000-06-30  |  13KB  |  803 lines

  1. ;         SORTV.ASM ver 1.4
  2. ;        by Ward Christensen
  3. ;         (revised 6/29/81)
  4. ;
  5. ;Simple sort program for sorting lists of names,
  6. ;or any other variable length file, with CR/LF
  7. ;delimited records.
  8. ;
  9. ;This is a "simple" program: FILE MUST FIT IN MEMORY.
  10. ;
  11. ;06/29/81 Cleaned up file and re-tabified it.  (KBP)
  12. ;
  13. ;06/22/81 Changed so MAC is not needed. Changed so alternate or
  14. ;      standard CP/M may be selected. By Ted Shapin.
  15. ;
  16. ;01/03/81 Change stack init.  By Keith Petersen, W8SDZ
  17. ;
  18. ;11/15/80 Add @ command (WLC)
  19. ;
  20. ;10/24/80 Originally written by Ward Christensen
  21. ;
  22. ;FORMAT:
  23. ;    SORTV input-name output-name
  24. ; OR    SORTV name
  25. ;
  26. ;If the second format is used, the file is read into
  27. ;memory, sorted, erased, created, and written back.
  28. ;
  29. ;    The sort will be based on the first characters
  30. ;    in the file, unless the command is followed by
  31. ;    an "@" sign, then a string (1 or more characters)
  32. ;    to skip.  If these are present, the line will be
  33. ;    sorted starting after one of these characters.
  34. ;
  35. ;Example: SORTV NAMES.SUB @.
  36. ;
  37. ;Will sort NAMES.SUB by filetype, since it skips past
  38. ;the "." before doing the compare.
  39. ;
  40. EOF    EQU    1AH
  41. CR    EQU    0DH
  42. LF    EQU    0AH
  43. ;
  44. BIAS    EQU    0    ;0 FOR STANDARD CP/M, 4200H FOR ALTERNATE CP/M
  45. ;
  46. ;BDOS/CBIOS EQUATES (VERSION 10)
  47. ;
  48. RDCON    EQU    1
  49. WRCON    EQU    2
  50. PRINT    EQU    9
  51. RDCONBF EQU    10
  52. CONST    EQU    11
  53. OPEN    EQU    15
  54. CLOSE    EQU    16
  55. SRCHF    EQU    17
  56. SRCHN    EQU    18
  57. ERASE    EQU    19
  58. READ    EQU    20
  59. WRITE    EQU    21
  60. MAKE    EQU    22
  61. REN    EQU    23
  62. STDMA    EQU    26
  63. BDOS    EQU    5+BIAS
  64. FCB    EQU    5CH+BIAS
  65. FCB2    EQU    6CH+BIAS
  66. FCBEXT    EQU    FCB+12
  67. FCBRNO    EQU    FCB+32
  68. ;
  69.     ORG    100H+BIAS
  70. ;
  71. ;INIT LOCAL STACK
  72. ;
  73.     LXI    SP,STACK
  74. ;
  75.     CALL    START
  76.     DB    'SORTV rev 1.3'
  77.     DB    CR,LF,'$'
  78. ;
  79. START    POP    D    ;GET ID
  80.     MVI    C,PRINT
  81.     CALL    BDOS    ;PRINT ID
  82. ;
  83. ;START OF PROGRAM EXECUTION
  84. ;
  85.     CALL    SVSKIP    ;SAVE SKIP INFO
  86.     CALL    CKNAMES ;SEE THAT 2 NAMES ARE THERE
  87.     CALL    OPENIN    ;OPEN INPUT FILE
  88.     CALL    READN    ;READ THE NAMES
  89.     CALL    SORTN    ;SORT THE NAMES
  90.     CALL    WRITEN    ;WRITE THE NAMES
  91.     CALL    ERXIT
  92.     DB    '++DONE++$'
  93. ;
  94. ;====>    SUBROUTINES
  95. ;    ----------------
  96. ;
  97. ;====>    SAVE "SKIP TO" INFORMATION
  98. ;
  99. SVSKIP    LXI    H,81H+BIAS
  100. ;
  101. SVSKL    MOV    A,M
  102.     ORA    A
  103.     RZ        ;NO 'SKIP TO'
  104.     CPI    '@'    ;SKIP DELIMITER?
  105.     INX    H
  106.     JNZ    SVSKL
  107.     LXI    D,SKIPC ;CHARS TO SKIP
  108. ;
  109. SVSKL2    MOV    A,M
  110.     STAX    D
  111.     INX    H
  112.     INX    D
  113.     ORA    A
  114.     JNZ    SVSKL2
  115.     RET
  116. ;
  117. ;====>    CHECK THAT 2 NAMES WERE SUPPLIED
  118. ;
  119. CKNAMES LDA    FCB+1
  120.     CPI    ' '
  121.     JZ    NONAME
  122.     LDA    FCB2+1
  123.     CPI    ' '
  124.     JZ    SAMENAM
  125.     CPI    '@'    ;SKIP PARM?
  126.     JZ    SAMENAM
  127.     LXI    H,FCB2
  128.     LXI    D,OUTNAME
  129.     LXI    B,12
  130.     CALL    MOVER
  131.     RET
  132. ;
  133. ;OUTPUT NAME = INPUT NAME
  134. ;
  135. SAMENAM    LXI    H,FCB
  136.     LXI    D,OUTNAME
  137.     LXI    B,12
  138.     CALL    MOVER
  139.     RET
  140. ;
  141. NONAME    CALL    ERXIT
  142.     DB    '++Error - ',CR,LF
  143.     DB    'Command format requires an '
  144.     DB    'input name, and an output name.$'
  145. ;
  146. ;====>    OPEN THE INPUT FILE
  147. ;
  148. OPENIN    PUSH    B
  149.     PUSH    D
  150.     PUSH    H
  151.     MVI    C,OPEN
  152.     LXI    D,FCB
  153.     CALL    BDOS
  154.     POP    H
  155.     POP    D
  156.     POP    B
  157.     INR    A
  158.     RNZ        ;SUCCESSFUL?  RETURN
  159.     CALL    ERXIT
  160.     DB    '++Input file not found$'
  161. ;
  162. ;====>    READ IN THE NAMES
  163. ;
  164. READN    LXI    H,SBUFF    ;TO FIRST NAME
  165. ;
  166. READNL    CALL    READL    ;READ ONE LINE
  167.     RC        ;GOT EOF, RETURN
  168.     CALL    CHAIN    ;CHAIN THINGS TOGETHER
  169.     JMP    READNL
  170. ;
  171. ;====>    READ ONE LINE
  172. ;
  173. READL    SHLD    CURR    ;SAVE CURR LINE PTR
  174.     XRA    A    ;GET 0
  175.     MOV    M,A    ;INIT FORWARD
  176.     INX    H    ;    POINTER
  177.     MOV    M,A    ;    TO
  178.     INX    H    ;    0
  179.     LXI    D,SKIPC ;TO CK SKIP CHARS PRESENT
  180. ;
  181. READLLP LDA    BDOS+2    ;ARE WE
  182.     DCR    A    ;    OVER-
  183.     CMP    H    ;    FLOW-
  184.     JZ    OFLO    ;    ING?
  185.     PUSH    D
  186.     PUSH    H
  187.     LXI    H,EXTFCB
  188.     CALL    RDBYTE    ;READ A BYTE
  189.     POP    H
  190.     POP    D
  191.     CPI    EOF    ;SET CARRY
  192.     STC        ;    AND RETURN
  193.     RZ        ;    IF EOF
  194.     MOV    M,A    ;STORE CHAR
  195. ;TEST FOR SKIP CHAR FOUND
  196.     MOV    B,A    ;SAVE FOR COMPARE
  197.     LDAX    D
  198.     ORA    A    ;NO MORE SKIP CHARS?
  199.     JZ    READLNS ;NO MORE
  200.     CMP    B    ;A SKIP CHAR?
  201.     JNZ    READLNS ;NO, KEEP TRYIN.
  202.     INX    D    ;TO NEXT SKIP CHAR
  203. ;
  204. READLNS INX    H    ;POINT TO NEXT
  205.     MOV    A,B    ;GET CHAR
  206.     CPI    CR    ;END OF LINE?
  207.     JNZ    READLLP ;    NO, LOOP.
  208.     PUSH    D
  209.     PUSH    H
  210.     LXI    H,EXTFCB
  211.     CALL    RDBYTE    ;GOBBLE UP LF
  212.     POP    H
  213.     POP    D
  214.     LDAX    D    ;GET SKIP CHAR END
  215.     ORA    A    ;TEST IT AND SET "NO EOF"
  216.     RZ
  217. ;ERROR - NO SKIP CHAR
  218.     LHLD    CURR
  219.     INX    H    ;SKIP
  220.     INX    H    ;    POINTER
  221. ;
  222. ERPLP    MOV    E,M
  223.     PUSH    B
  224.     PUSH    D
  225.     PUSH    H
  226.     MVI    C,WRCON
  227.     CALL    BDOS
  228.     POP    H
  229.     POP    D
  230.     POP    B
  231.     MOV    A,M
  232.     INX    H
  233.     CPI    CR
  234.     JNZ    ERPLP
  235.     CALL    ERXIT
  236.     DB    LF,'++NO SKIP CHAR FOUND++$'
  237. ;
  238. OFLO    CALL    ERXIT
  239.     DB    '++File won''t fit in memory$'
  240. ;
  241. ;====>    CHAIN RECORDS TOGETHER
  242. ;
  243. CHAIN    PUSH    H    ;SAVE POINTER
  244.     LHLD    CURR    ;GET CURRENT
  245.     XCHG        ;    TO DE
  246.     LHLD    PREV    ;PREV TO HL
  247.     MOV    M,E    ;MOVE CURR
  248.     INX    H    ;    TO
  249.     MOV    M,D    ;    PREV
  250.     XCHG        ;THEN MOVE
  251.     SHLD    PREV    ;    PREV TO CURR
  252.     POP    H
  253.     RET
  254. ;
  255. ;====>    SORT THE NAMES
  256. ;
  257. SORTN    XRA    A    ;SHOW NO
  258.     STA    SWAPS    ;    SWAPS
  259.     LXI    H,PTR    ;POINT PREV
  260.     SHLD    PREV    ;    TO PTR
  261.     LHLD    PTR    ;POINT TO FIRST
  262. ;
  263. ;HANDLE WIERD CASE OF ONLY ONE NAME
  264. ;
  265.     MOV    A,M    ;GET POINTER
  266.     INX    H    ;POINT TO NEXT
  267.     ORA    M    ;OR TOGETHER
  268.     DCX    H    ;BACK UP
  269.     RZ        ;RETURN IF ONLY ONE
  270. ;
  271. SORTL    CALL    CMPR    ;COMPARE ENTRIES
  272.     CC    SWAP    ;SWAP IF WRONG ORDER
  273.     CALL    NEXT    ;POINT TO NEXT
  274.     JNC    SORTL    ;LOOP IF MORE
  275.     LDA    SWAPS    ;ANY
  276.     ORA    A    ;    SWAPS?
  277.     JNZ    SORTN    ;YES, LOOP
  278.     RET        ;NO, RETURN
  279. ;
  280. ;---->    COMPARE TWO NAMES
  281. ;
  282. CMPR    PUSH    H    ;SAVE POINTER
  283.     MOV    E,M    ;GET NEXT
  284.     INX    H    ;    POINTER
  285.     MOV    D,M    ;    TO DE
  286.     INX    D    ;ALIGN POINTERS
  287. ;
  288. ;SKIP IF NECESSARY
  289. ;
  290.     LXI    B,SKIPC
  291. ;
  292. TSTSKIP LDAX    B
  293.     ORA    A
  294.     JZ    COMPL    ;NO SKIP
  295.     INX    B
  296. ;
  297. SKIP1    INX    H
  298.     CMP    M
  299.     JNZ    SKIP1
  300.     XCHG        ;SWAP
  301. ;
  302. SKIP2    INX    H
  303.     CMP    M
  304.     JNZ    SKIP2
  305.     XCHG        ;PUT THINGS BACK
  306.     JMP    TSTSKIP
  307. ;
  308. COMPL    INX    D    ;TO NEXT
  309.     INX    H    ;TO NEXT
  310.     LDAX    D    ;GET ONE
  311.     CMP    M    ;COMPARE
  312.     JNZ    COMPNE    ;NO COMPARE
  313.     CPI    CR    ;END?
  314.     JNZ    COMPL    ;    NO, LOOP
  315. ;
  316. COMPH    POP    H    ;RESTORE POINTER
  317.     RET        ;THEY ARE EQUAL
  318. ;
  319. ;COMPARE NOT EQUAL - SEE IF END OF ELEMENT,
  320. ;AND IF SO, CALL THEM EQUAL
  321. ;
  322. COMPNE    MOV    A,M
  323.     CPI    CR
  324.     JZ    COMPH
  325.     LDAX    D
  326.     CMP    M
  327.     JMP    COMPH    ;CARRY SET AS APPROP
  328. ;
  329. ;---->    SWAP ENTRIES
  330. ;
  331. ;LOGIC: PTR POINTS TO SOME ENTRY, WHICH POINTS
  332. ;TO ANOTHER ENTRY.  THEY ARE NOT IN ORDER.  THUS:
  333. ;POINT PTR TO THE SECOND, POINT THE SECOND TO
  334. ;THE FIRST, AND POINT THE FIRST TO WHAT THE
  335. ;SECOND USED TO POINT TO.
  336. ;
  337. SWAP    MVI    A,1
  338.     STA    SWAPS    ;SHOW WE SWAPPED
  339. ;BC=NEXT
  340.     MOV    C,M
  341.     INX    H
  342.     MOV    B,M
  343.     DCX    H
  344. ;CHAIN CURRENT TO NEXT ONES CHAIN
  345.     LDAX    B
  346.     MOV    M,A
  347.     INX    B
  348.     INX    H
  349.     LDAX    B
  350.     MOV    M,A
  351.     DCX    B
  352.     DCX    H
  353. ;SAVE CURRENT POINTER IN DE
  354.     XCHG
  355. ;GET POINTER TO PREV
  356.     LHLD    PREV
  357. ;POINT PREV TO NEXT
  358.     MOV    M,C
  359.     INX    H
  360.     MOV    M,B
  361. ;STORE CURR IN NEXT
  362.     MOV    A,E
  363.     STAX    B
  364.     INX    B
  365.     MOV    A,D
  366.     STAX    B
  367.     DCX    B
  368. ;RESTORE CURRENT POINTER
  369.     XCHG
  370.     RET        ;CURRENT POINTER IN DE
  371. ;
  372. ;---->    GET NEXT ETRY, CARRY IF NOT 2 MORE
  373. ;
  374. NEXT    SHLD    PREV    ;SAVE POINTER
  375.     MOV    E,M
  376.     INX    H
  377.     MOV    D,M
  378.     XCHG        ;HL= NEXT
  379.     MOV    A,H    ;CARRY ON
  380.     ORA    L    ;    IF HL
  381.     STC        ;    =
  382.     RZ        ;    0
  383.     MOV    A,M    ;GET
  384.     INX    H    ;SEE IF THERE
  385.     ORA    M    ;    IS
  386.     DCX    H    ;    ANOTHER
  387.     RNZ        ;THERE IS ANOTHER
  388.     STC        ;SHOW NOT 2 TO SWAP
  389.     RET
  390. ;
  391. ;====>    WRITE THE NAMES
  392. ;
  393. WRITEN    LXI    H,0    ;INIT
  394.     SHLD    EXTFCB+2 ;    EFCB
  395.     XRA    A    ;INIT
  396.     STA    FCBEXT    ;    THE
  397.     STA    FCBRNO    ;    FCB
  398. ;RESTORE NAME
  399.     LXI    H,OUTNAME
  400.     LXI    D,FCB
  401.     LXI    B,12
  402.     CALL    MOVER
  403.     PUSH    B
  404.     PUSH    D
  405.     PUSH    H
  406.     MVI    C,ERASE
  407.     LXI    D,FCB
  408.     CALL    BDOS
  409.     POP    H
  410.     POP    D
  411.     POP    B
  412.     PUSH    B
  413.     PUSH    D
  414.     PUSH    H
  415.     MVI    C,MAKE
  416.     LXI    D,FCB
  417.     CALL    BDOS
  418.     POP    H
  419.     POP    D
  420.     POP    B
  421.     INR    A    ;MAKE OK?
  422.     JZ    BADOUT    ;    NO, ERROR
  423.     LHLD    PTR    ;GET FIRST
  424. ;
  425. WNLP    CALL    WRITEL    ;WRITE ONE LINE
  426.     JNC    WNLP    ;LOOP IF MORE
  427.     MVI    A,EOF    ;WRITE EOF CHAR
  428.     PUSH    H
  429.     LXI    H,EXTFCB
  430.     CALL    WRBYTE
  431.     POP    H
  432.     LXI    H,EXTFCB ;FLUSH
  433.     CALL    FLUSH     ;     BUFFERS
  434.     PUSH    B
  435.     PUSH    D
  436.     PUSH    H
  437.     MVI    C,STDMA    ;RESET DMA
  438.     LXI    D,80H+BIAS
  439.     CALL    BDOS
  440.     POP    H
  441.     POP    D
  442.     POP    B
  443.     PUSH    B
  444.     PUSH    D
  445.     PUSH    H
  446.     MVI    C,CLOSE
  447.     LXI    D,FCB
  448.     CALL    BDOS
  449.     POP    H
  450.     POP    D
  451.     POP    B
  452.     CALL    ERXIT    ;    AND EXIT
  453.     DB    '++DONE++$'
  454. ;
  455. WRITEL    PUSH    H    ;SAVE POINTER
  456.     INX    H
  457. ;
  458. WRLP    INX    H    ;TO NEXT CHAR
  459.     MOV    A,M    ;GET CHAR
  460.     PUSH    H
  461.     LXI    H,EXTFCB
  462.     CALL    WRBYTE    ;WRITE IT
  463.     POP    H
  464.     MOV    A,M    ;SEE IF END
  465.     CPI    CR    ;    OF LINE
  466.     JNZ    WRLP    ;NO, LOOP
  467.     MVI    A,LF    ;OTHERWISE
  468.     PUSH    H
  469.     LXI    H,EXTFCB
  470.     CALL    WRBYTE    ;WRITE LF
  471.     POP    H
  472.     POP    H    ;GET POINTER
  473.     MOV    E,M    ;GET
  474.     INX    H    ;    FORWARD
  475.     MOV    D,M    ;    POINTER
  476.     XCHG        ;PUT IT IN HL
  477.     MOV    A,H    ;IS POINTER
  478.     ORA    L    ;    ZERO?
  479.     RNZ        ;NO, RETURN
  480.     STC        ;CARRY SHOWS END
  481.     RET
  482. ;
  483. BADOUT    CALL    ERXIT
  484.     DB    '++Can''t make output file$'
  485. ;
  486. ;FOLLOWING FROM 'EQU10.LIB'---->
  487. ;
  488. ;MOVE, COMPARE SUBROUTINES
  489. ;
  490. MOVER    MOV    A,M
  491.     STAX    D
  492.     INX    H
  493.     INX    D
  494.     DCX    B
  495.     MOV    A,B
  496.     ORA    C
  497.     JNZ    MOVER
  498.     RET
  499. ;
  500. ;    FROM EQU10.LIB: AS OF 07/19/80
  501. ;
  502. ;RDBYTE, HL POINTS TO EXTENDED FCB:
  503. ;
  504. ;    2 BYTE BUFFER ADDR
  505. ;    2 BYTE "BYTES LEFT" (INIT TO 0)
  506. ;    1 BYTE BUFFER SIZE (IN PAGES)
  507. ;    2 BYTE FCB ADDRESS
  508. ;
  509. RDBYTE    MOV    E,M
  510.     INX    H
  511.     MOV    D,M    ;GET BUFFER ADDR
  512.     INX    H
  513.     MOV    C,M
  514.     INX    H
  515.     MOV    B,M    ;BC = BYTES LEFT
  516.     MOV    A,B    ;GET COUNT
  517.     ORA    C
  518.     JNZ    RDBNORD ;NO READ
  519. ;
  520.     INX    H    ;TO BUFFER SIZE
  521.     MOV    A,M    ;GET COUNT
  522.     ADD    A    ;MULTIPLY BY 2
  523.     MOV    B,A    ;SECTOR COUNT IN B
  524.     INX    H    ;TO FCB
  525.     PUSH    H    ;SAVE FCB POINTER
  526.     MOV    A,M    ;GET..
  527.     INX    H
  528.     MOV    H,M    ;..ADDR..
  529.     MOV    L,A    ;..TO HL
  530. ;
  531. RDBLP    MVI    A,1AH    ;GET EOF CHAR
  532.     STAX    D    ;SAVE IN CASE EOF
  533.     PUSH    D    ;SAVE DMA ADDR
  534.     PUSH    H    ;SAVE FCB ADDR
  535.     PUSH    B
  536.     PUSH    D
  537.     PUSH    H
  538.     MVI    C,STDMA
  539.     CALL    BDOS    ;SET DMA ADDR
  540.     POP    H
  541.     POP    D
  542.     POP    B
  543.     POP    D    ;GET FCB
  544.     PUSH    B
  545.     PUSH    D
  546.     PUSH    H
  547.     MVI    C,READ
  548.     CALL    BDOS
  549.     POP    H
  550.     POP    D
  551.     POP    B
  552.     ORA    A
  553.     POP    H    ;HL=DMA, DE=FCB
  554.     JNZ    RDBRET    ;GOT EOF
  555.     MOV    A,L
  556.     ADI    80H    ;TO NEXT BUFF
  557.     MOV    L,A
  558.     MOV    A,H
  559.     ACI    0
  560.     MOV    H,A
  561.     XCHG        ;DMA TO DE, FCB TO HL
  562.     DCR    B    ;MORE SECTORS?
  563.     JNZ    RDBLP    ;YES, MORE
  564. ;
  565. RDBRET    POP    H    ;GET FCB POINTER
  566.     DCX    H    ;TO LENGTH
  567.     MOV    A,M    ;GET LENGTH
  568.     DCX    H    ;TO COUNT
  569.     MOV    M,A    ;SET PAGE COUNT
  570.     DCX    H    ;TO LO COUNT
  571.     DCX    H    ;TO HI FCB
  572.     DCX    H    ;TO EFCB START
  573.     JMP    RDBYTE    ;LOOP THRU AGAIN
  574. ;
  575. RDBNORD INX    H    ;TO LENGTH
  576.     MOV    A,M    ;GET LENGTH (PAGES)
  577.     XCHG        ;BUFF TO HL
  578.     ADD    H
  579.     MOV    H,A    ;HL = END OF BUFF
  580.     MOV    A,L
  581.     SUB    C
  582.     MOV    L,A
  583.     MOV    A,H
  584.     SBB    B
  585.     MOV    H,A    ;HL = DATA POINTER
  586.     MOV    A,M    ;GET BYTE
  587.     XCHG        ;EFCB BACK TO HL
  588.     CPI    1AH    ;EOF?
  589.     RZ        ;YES, LEAVE POINTERS
  590.     DCX    B    ;DECR COUNT
  591.     DCX    H    ;"BYTES LEFT"
  592.     MOV    M,B
  593.     DCX    H
  594.     MOV    M,C    ;STORE BACK COUNT
  595.     RET
  596. ;
  597. ;SAMPLE EFCB:
  598. ;
  599. ;EFCB    DW    BUFF    ;BUFFER ADDR
  600. ;    DW    0    ;BYTES LEFT (OR TITE)
  601. ;    DB    20    ;BUFFER SIZE (IN PAGES)
  602. ;    DW    FCB    ;FCB ADDRESS
  603. ;
  604. ;
  605. ;WRBYTE, HL POINTS TO EXTENDED FCB:
  606. ;
  607. ;    2 BYTE BUFFER ADDR
  608. ;    2 BYTE "BYTES LEFT" (INIT TO 0)
  609. ;    1 BYTE BUFFER SIZE (IN PAGES)
  610. ;    2 BYTE FCB ADDRESS
  611. ;
  612. WRBYTE    MOV    E,M
  613.     INX    H
  614.     MOV    D,M    ;DE=BUF ADDR
  615.     INX    H
  616.     MOV    C,M
  617.     INX    H
  618.     MOV    B,M    ;BC=BYTES IN BUFF
  619.     PUSH    D    ;SAVE FCB
  620.     XCHG
  621.     DAD    B    ;TO NEXT BYTE
  622.     MOV    M,A    ;STORE IT
  623.     INX    B    ;ONE MORE
  624.     XCHG
  625.     POP    D
  626. ;
  627. ;SEE IF BUFFER IS FULL
  628. ;
  629.     INX    H    ;GET
  630.     MOV    A,M    ;    SIZE
  631.     CMP    B    ;FULL?
  632.     JNZ    WRBNOWR ;NO WRITE
  633. ;
  634.     ADD    A    ;MULTIPLY BY 2
  635.     MOV    B,A    ;SECTOR COUNT IN B
  636.     INX    H    ;TO FCB
  637.     PUSH    H    ;SAVE FCB POINTER
  638.     MOV    A,M    ;GET..
  639.     INX    H    ;..FCB..
  640.     MOV    H,M    ;..ADDR..
  641.     MOV    L,A    ;..TO HL
  642. ;
  643. WRBLP    PUSH    D    ;SAVE DMA ADDR
  644.     PUSH    H    ;SAVE FCB ADDR
  645.     PUSH    B
  646.     PUSH    D
  647.     PUSH    H
  648.     MVI    C,STDMA
  649.     CALL    BDOS    ;SET DMA ADDR
  650.     POP    H
  651.     POP    D
  652.     POP    B
  653.     POP    D    ;GET FCB
  654.     PUSH    B
  655.     PUSH    D
  656.     PUSH    H
  657.     MVI    C,WRITE
  658.     CALL    BDOS
  659.     POP    H
  660.     POP    D
  661.     POP    B
  662.     ORA    A
  663.     POP    H    ;HL=DMA, DE=FCB
  664.     JNZ    WRBERR    ;GOT ERR
  665.     MOV    A,L
  666.     ADI    80H    ;TO NEXT BUFF
  667.     MOV    L,A
  668.     MOV    A,H
  669.     ACI    0
  670.     MOV    H,A
  671.     XCHG        ;DMA TO DE, FCB TO HL
  672.     DCR    B    ;MORE SECTORS?
  673.     JNZ    WRBLP    ;YES, MORE
  674. ;
  675. WRBRET    POP    H    ;GET FCB POINTER
  676.     DCX    H    ;TO LENGTH
  677.     DCX    H    ;TO COUNT
  678.     MVI    M,0    ;SET 0 TO WRITE
  679.     DCX    H    ;TO LO COUNT
  680.     MVI    M,0
  681.     PUSH    B
  682.     PUSH    D
  683.     PUSH    H
  684.     MVI    C,STDMA
  685.     LXI    D,80H+BIAS
  686.     CALL    BDOS
  687.     POP    H
  688.     POP    D
  689.     POP    B
  690.     RET
  691. ;
  692. WRBNOWR DCX    H    ;TO LENGTH
  693.     MOV    M,B    ;SET NEW LENGTH
  694.     DCX    H
  695.     MOV    M,C
  696.     RET
  697. ;
  698. ;FLUSH THE EFCB BUFFERS
  699. ;
  700. FLUSH    MOV    E,M
  701.     INX    H
  702.     MOV    D,M    ;DE=BUF ADDR
  703.     INX    H
  704.     MOV    C,M
  705.     INX    H
  706.     MOV    B,M    ;BC=BYTES IN BUFF
  707.     INX    H    ;TO COUNT
  708.     MOV    A,B
  709.     ORA    C
  710.     RZ        ;NOTHING TO WRITE
  711.     MOV    A,C    ;GET LOW COUNT
  712.     ADD    A    ;SHIFT HIGH TO CARRY
  713.     MOV    A,B    ;GET LOW COUNTAL
  714.     RAL        ;MULT BY 2, + CARRY
  715.     INR    A    ;FUDGE FOR PARTIAL SECT
  716.     MOV    B,A    ;SAVE SECTOR COUNT
  717.     INX    H    ;TO FCB
  718.     MOV    A,M
  719.     INX    H
  720.     MOV    H,M
  721.     MOV    L,A    ;HL=FCB
  722. ;
  723. FLUSHL    PUSH    B
  724.     PUSH    D
  725.     PUSH    H
  726.     MVI    C,STDMA
  727.     CALL    BDOS
  728.     POP    H
  729.     POP    D
  730.     POP    B
  731.     XCHG
  732.     PUSH    B
  733.     PUSH    D
  734.     PUSH    H
  735.     MVI    C,WRITE
  736.     CALL    BDOS
  737.     POP    H
  738.     POP    D
  739.     POP    B
  740.     XCHG
  741.     ORA    A
  742.     JNZ    WRBERR
  743.     PUSH    H
  744.     LXI    H,80H
  745.     DAD    D
  746.     XCHG
  747.     POP    H
  748.     DCR    B
  749.     JNZ    FLUSHL
  750.     XCHG
  751.     PUSH    B
  752.     PUSH    D
  753.     PUSH    H
  754.     MVI    C,CLOSE
  755.     CALL    BDOS
  756.     POP    H
  757.     POP    D
  758.     POP    B
  759.     INR    A
  760.     RNZ
  761.     CALL    ERXIT
  762.     DB    '++OUTPUT FILE CLOSE ERROR ++$'
  763. ;
  764. WRBERR    CALL    ERXIT
  765.     DB    '++OUTPUT FILE WRITE ERROR++$'
  766. ;
  767. ;EXIT WITH ERROR MESSAGE
  768. ;
  769. MSGEXIT EQU    $    ;EXIT W/"INFORMATIONAL" MSG
  770. ;
  771. ERXIT    POP    D    ;GET MSG
  772.     MVI    C,PRINT
  773.     CALL    BDOS
  774. ;
  775. ;EXIT, RESTORING STACK AND RETURN
  776. ;
  777. EXIT    JMP    0+BIAS
  778. ;
  779. ;====>    START OF WORK AREA
  780. ;
  781. EXTFCB    DW    DKBUF
  782.     DW    0
  783.     DB    4
  784.     DW    FCB
  785. PREV    DW    PTR    ;POINTER TO PREV POINTER
  786. SKIPC    DB    0    ;SKIP CHARS END
  787.     DS    8    ;VARIABLE SKIP CHARS
  788. ;
  789.     DS    100    ;STACK AREA
  790. STACK    EQU    $
  791. ;
  792. OUTNAME DS    12    ;OUTPUT FILENAME
  793. SWAPS    DS    1
  794. CURR    DS    2
  795. PTR    DS    2    ;POINTER TO FIRST NAME
  796. ;
  797.     ORG    ($+255) AND 0FF00H ;TO PAGE
  798. ;
  799. DKBUF    DS    256*4    ;4 PAGES OF BUFFER
  800. SBUFF    DS    0    ;NAMES READ IN HERE
  801. ;
  802.     END
  803.