home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol097 / macro.lib < prev    next >
Encoding:
Text File  |  1984-04-29  |  17.0 KB  |  926 lines

  1. ;        -- NEW MACRO LIBRARY --
  2. ;
  3. ;    This library works with Digital Research's MAC macro assembler
  4. ;    and not (in the present form) with Macro-80.
  5. ;
  6. ;    Additional macro  double density sector set DSTSEC from SETSEC
  7. ;
  8. ;    There are some notations and there will be some modifications
  9. ;    in the various macro definitions.
  10. ;
  11. ;    SAVE MACRO    SAVE SPECIFIED REGISTERS
  12. ;
  13. ;    SAVE    R1,R2,R3,R4
  14. ;
  15. ;        R1-R4 MAY BE B,D,H OR PSW  SAVED IN ORDER SPECIFIED
  16. ;        IF REGS ARE OMITTED SAVE B,D AND H
  17. ;
  18. SAVE    MACRO    R1,R2,R3,R4
  19.     IF NOT NUL R1&R2&R3&R4
  20.     IRP    R,<<R1>,<R2>,<R3>,<R4>>
  21.     IF    NUL R
  22.     EXITM
  23.     ENDIF
  24.     PUSH    R
  25.     ENDM
  26.     ELSE
  27.     IRPC    REG,BDH
  28.     PUSH    REG
  29.     ENDM
  30.     ENDIF
  31.     ENDM
  32. ;
  33. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  34. ;
  35. ;    RESTORE MACRO    RESTORE REGISTERS  (INVERSE OF SAVE)
  36. ;
  37. ;    RESTORE    R1,R2,R3,R4
  38. ;
  39. ;        R1-R4 MAY BE B,D,H OR PSW  RESTORED IN ORDER SPECIFIED
  40. ;        IF REGS OMITTED RESTORE H,D AND B
  41. ;
  42. RESTORE    MACRO    R1,R2,R3,R4
  43.     IF    NOT NUL R1&R2&R3&R4
  44.     IRP    R,<<R1>,<R2>,<R3>,<R4>>
  45.     IF    NUL R
  46.     EXITM
  47.     ENDIF
  48.     POP    R
  49.     ENDM
  50.     ELSE
  51.     IRPC    REG,HDB
  52.     POP    REG
  53.     ENDM
  54.     ENDIF
  55.     ENDM
  56. ;
  57. ;
  58. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  59. ;
  60. ;    CHARIN MACRO    CONSOLE INPUT TO A
  61. ;
  62. ;    CHARIN    ADDR
  63. ;
  64. CHARIN    MACRO    ADDR
  65.     MVI    C,1        ;;CONSOLE INPUT
  66.     CALL    5        ;;CALL BDOS
  67.     IF    NOT NUL ADDR
  68.     STA    ADDR
  69.     ENDIF
  70.     ENDM
  71. ;
  72. ;
  73. ;    . . . . . . . . . . . . . . ... ... . .. . . . . . . . .
  74. ;
  75. ;    CHAROUT MACRO    CONSOLE OUTPUT FROM A
  76. ;
  77. ;    CHAROUT    ADDR
  78. ;
  79. CHAROUT    MACRO    ADDR
  80.     IF    NOT NUL ADDR
  81.     LDA    ADDR
  82.     ENDIF
  83.     MVI    C,2        ;;CONOUT
  84.     MOV    E,A        ;;CHAR TO E
  85.     CALL    5        ;;CALL BDOS
  86.     ENDM
  87. ;
  88. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  89. ;
  90. ;    CHARSTAT MACRO    CHECK CONSOLE STATUS
  91. ;
  92. ;            RETURN TRUE (FF) IF CHAR READY FALSE (0) IF NOT
  93. ;
  94. CHARSTAT MACRO
  95.     LOCAL    EXIT
  96.     MVI    C,11
  97.     CALL    5
  98.     ORA    A
  99.     JZ    EXIT
  100.     MVI    A,0FFH
  101. EXIT:    ENDM
  102. ;
  103. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  104. ;
  105. ;    INPUT MACRO    INPUT CHARACTER STRING FROM CONSOLE
  106. ;
  107. ;    INPUT    ADDR,BUFLEN
  108. ;
  109. ;        ADDR    START OF TEXT BUFFER
  110. ;        BUFLEN    LENGTH OF BUFFER  (DEFAULT IS 127)
  111. ;
  112. INPUT    MACRO    ADDR,BUFLEN
  113.     MVI    C,10
  114.     IF    NOT NUL ADDR
  115.     LXI    D,ADDR        ;;SET BUFFER ADDRESS
  116.     ENDIF
  117.     IF    NOT NUL BUFLEN
  118.     MVI    A,BUFLEN    ;;SET BUFFER LENGTH
  119.     STAX    D
  120.     ELSE
  121.     MVI    A,127
  122.     STAX    D        ;;SET BUFFER DEFAULT MAXIMUM
  123.     ENDIF
  124.     CALL    5        ;;BDOS ENTRY
  125.     ENDM
  126. ;
  127. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  128. ;
  129. ;    PRINT MACRO    PRINT A STRING ON CONSOLE
  130. ;
  131. ;    PRINT                (CARRIAGE RETURN, LINE FEED)
  132. ;    PRINT    'LITERAL'
  133. ;    PRINT    <'LITERAL',CR,LF,'SECOND LITERAL'>
  134. ;
  135. ;    PRINT    ADDR,$            (ASCII OUTPUT UNTIL $)
  136. ;    PRINT    ADDR,L,H        (HEX OUTPUT L CHARACTERS)
  137. ;
  138. ;    Note that for the following usage of the macro PRINT the string 
  139. ;    referenced by ADDR must contain (via db) enough characters to 
  140. ;    match the length requirement in L.  Stated another way L is 
  141. ;    --- NOT --- a character repeat specification but rather a spec.
  142. ;    to extract <L> characters from the string.
  143. ;    PRINT    ADDR,L,A        (ASCII OUTPUT L CHARACTERS)
  144. ;
  145. ;        LITERALS MUST BE IN SINGLE QUOTES  'LIT'
  146. ;        IF LITERAL CONTAINS CONTROL CODES ENTIRE STRING IN <> BRACKETS
  147. ;        MACRO ALSO ASSEMBLES
  148. ;            CR = CARRIAGE RETURN
  149. ;            LF = LINE FEED
  150. ;            BEL = BELL CODE
  151. ;
  152. ;        MACRO ASSUMES ADDR ALREADY LOADED TO HL IF ARGUMENT OMITTED
  153. ;
  154. PRINT    MACRO    ?STRING,LEN,TC
  155.     LOCAL    @OVER,@MESS,PLOOP,PASTCR,@CRLF
  156. CR    SET    0DH
  157. LF    SET    0AH
  158. BEL    SET    07H
  159.     IF    NUL ?STRING&LEN&TC
  160.     JMP    PASTCR
  161. @CRLF:    DB    CR
  162.     DB    LF
  163.     DB    '$'
  164. PASTCR:    LXI    D,@CRLF
  165.     MVI    C,9
  166.     CALL    5
  167.     ELSE
  168.     IF    NUL LEN&TC
  169.     JMP    @OVER
  170. @MESS:    DB    ?STRING
  171.     DB    '$'
  172. @OVER:    LXI    D,@MESS
  173.     MVI    C,9
  174.     CALL    5        ;;BDOS ENTRY
  175.     ELSE
  176.     IF    NUL TC
  177.     IF    NOT NUL ?STRING
  178.     LXI    D,?STRING    ;;POINTER TO STRING
  179.     ENDIF
  180.     MVI    C,9
  181.     CALL    5        ;;BDOS ENTRY
  182.     ELSE
  183.     IF    NOT NUL ?STRING
  184.     LXI    H,?STRING    ;;POINTER TO STRING
  185.     ENDIF
  186.     MVI    C,LEN        ;;LENGTH OF STRING
  187. PLOOP:    PUSH    B
  188.     PUSH    H
  189.     IF    TC=H
  190.     MOV    A,M        ;;GET A BYTE
  191.     HEXOUT            ;;CONV TO HEX & OUTPUT
  192.     ELSE
  193.     MOV    E,M        ;;GET A BYTE
  194.     MVI    C,2        ;;OUT FROM E
  195.     CALL    5
  196.     ENDIF
  197.     POP    H
  198.     POP    B
  199.     INX    H
  200.     DCR    C        ;;DECR LENGTH
  201.     JNZ    PLOOP        ;;CONTINUE TILL LEN 0
  202.     ENDIF
  203.     ENDIF
  204.     ENDIF
  205.     ENDM
  206. ;
  207. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  208. ;
  209. ;    HEXOUT MACRO    CONVERT BINARY NO AND OUTPUT TO CONSOLE
  210. ;
  211. ;    HEXOUT    ADDR
  212. ;
  213. ;        NUMBER ASSUMED IN A IF NO ARGUMENT
  214. ;
  215. HEXOUT    MACRO    ADDR
  216.     LOCAL    OUTCHR,HEXEND
  217.     JMP    HEXEND
  218. HEXPRN:    SAVE    PSW
  219.     RRC
  220.     RRC
  221.     RRC
  222.     RRC            ;;SHIFT RIGHT 4
  223.     CALL    OUTCHR
  224.     RESTORE    PSW
  225. OUTCHR: ANI    0FH        ;;MASK 4 BITS
  226.     ADI    90H        ;;ADD OFFSET
  227.     DAA            ;;DEC ADJUST
  228.     ACI    40H        ;;ADD OFFSET
  229.     DAA            ;;DEC ADJUST
  230.     MOV    E,A        ;;TO E FOR OUTPUT
  231.     MVI    C,2        ;;CONOUT
  232.     JMP    5        ;;CALL BDOS
  233. HEXEND:
  234. HEXOUT    MACRO    ?ADDR
  235.     IF    NOT NUL ?ADDR
  236.     LDA    ?ADDR
  237.     ENDIF
  238.     CALL    HEXPRN
  239.     ENDM
  240.     HEXOUT    ADDR
  241.     ENDM
  242. ;
  243. ;
  244. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  245. ;
  246. ;    HEXIN MACRO    CONVERT A NUMBER IN MEMORY FROM HEX TO BINARY
  247. ;
  248. ;            IF NO ARGUMENT MACRO ASSUMES ADDR OF HEX STRING IN HL
  249. ;            ANSWER LEFT IN HL WITH LEAST SIGNIFICANT 8 BITS IN A
  250. ;            CARRY SET ON ERROR. CONVERSION STOPS WHEN ZERO IS
  251. ;            FOUND IN HEX STRING.
  252. ;
  253. HEXIN    MACRO    ADDR
  254.     LOCAL    IN1,IN2,OVERSUB
  255.     JMP    OVERSUB
  256. @HEXIN    LXI    H,0        ;;ZERO NUMBER
  257. IN1:    LDAX    D        ;;GET A CHAR
  258.     ORA    A        ;;CHECK FOR END OF BUFFER
  259.     RZ
  260.     SUI    '0'        ;;CHECK < 0 AND CONVERT TO HEX
  261.     RC
  262.     ADI    '0'-'G'        ;;CHECK > F
  263.     RC
  264.     ADI    6
  265.     JP    IN2        ;;NO BETWEEN A AND F
  266.     ADI    7
  267.     RC
  268. IN2:    ADI    10
  269.     ORA    A        ;;CLEAR CARRY
  270.     MOV    C,A        ;;HEX DIGIT TO C
  271.     MVI    B,0        ;;ZERO TO B
  272.     DAD    H
  273.     DAD    H
  274.     DAD    H
  275.     DAD    H        ;;SHIFT LEFT 4
  276.     DAD    B        ;;ADD IN NEW DIGIT
  277.     INX    D        ;;INCR BUFFER POINTER
  278.     JMP    IN1        ;;RETURN FOR MORE INPUT
  279. OVERSUB:
  280. HEXIN    MACRO    ?ADDR
  281.     IF NOT NUL ?ADDR
  282.     LXI    D,?ADDR        ;;LOAD BUFFER ADDR
  283.     ELSE
  284.     XCHG
  285.     ENDIF
  286.     CALL    @HEXIN
  287.     MOV    A,L        ;;LEAST SIGNIFICANT 8 BITS TO A
  288.     ENDM
  289.     HEXIN    ADDR
  290.     ENDM
  291. ;
  292. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  293. ;
  294. ;    DECOUT MACRO    CONVERT A POSITIVE INTEGER TO DECIMAL AND OUTPUT 
  295. ;            TO THE CONSOLE.
  296. ;
  297. ;    DECOUT    ADDR
  298. ;
  299. ;        IF ADDR OMITTED, NUMBER ASSUMED TO BE IN HL, ELSE LOADED TO HL
  300. ;        LEADING ZEROS SUPRESSED. MAXIMUM NUMBER 65,767
  301. ;
  302. DECOUT    MACRO    ADDR
  303.     LOCAL    ENDDEC,DX
  304.     JMP    ENDDEC
  305. @DECOUT:SAVE            ;;PUSH STACK
  306.     LXI    B,-10        ;;RADIX FOR CONVERSION
  307.     LXI    D,-1        ;;THIS BECOMES NO DIVIDED BY RADIX
  308. DX    DAD    B        ;;SUBTRACT 10
  309.     INX    D
  310.     JC    DX
  311.     LXI    B,10
  312.     DAD    B        ;;ADD RADIX BACK IN ONCE
  313.     XCHG
  314.     MOV    A,H
  315.     ORA    L        ;;TEST FOR ZERO
  316.     CNZ    @DECOUT        ;;RECURSIVE CALL
  317.     MOV    A,E
  318.     ADI    '0'        ;;CONVERT FROM BCD TO HEX
  319.     MOV    E,A        ;;TO E FOR OUTPUT
  320.     CHAROUT            ;;CONSOLE OUTPUT
  321.     RESTORE            ;;POP STACK
  322.     RET
  323. ENDDEC:
  324. DECOUT    MACRO    ?ADDR
  325.     IF    NOT NUL ?ADDR
  326.     LHLD    ?ADDR
  327.     ENDIF
  328.     CALL    @DECOUT        ;;CALL THE SUBROUTINE
  329.     ENDM
  330.     DECOUT    ADDR
  331.     ENDM
  332. ;
  333. ;
  334. ;
  335. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  336. ;
  337. ;    DECIN MACRO    CONVERT A NUMBER IN MEMORY FROM ASCII TO BINARY
  338. ;
  339. ;    DECIN    ADDR
  340. ;
  341. ;        ADDR POINTS TO MEMORY LOCATION OF START OF NO, IF
  342. ;        ARG OMITTED POINTER ASSUMED LOADED TO HL
  343. ;        MACRO RETURNS WITH CARRY SET IF ALPHABETIC CHAR FOUND
  344. ;        CONVERSION STOPS WHEN CHAR LESS THAN ZERO IS FOUND.
  345. ;        BINARY NUMBER IS LEFT IN HL, MAXIMUM 65,767
  346. ;        LEAST SIGNIFICANT 8 BITS OF NUMBER IN A.
  347. ;
  348. DECIN    MACRO    ADDR
  349.     LOCAL    DLOOP,OVERSUB
  350.     JMP    OVERSUB
  351. @DECIN:    LXI    D,0        ;;ZERO DE
  352.     XCHG            ;;ADDR POINTER TO DE, ZERO TO HL
  353. DLOOP:    LDAX    D        ;;GET A ASCII DIGIT
  354.     SUI    '0'        ;;CONVERT TO BCD AND TEST
  355.     ANA    A        ;;RESET CARRY
  356.     RM            ;;TERMINATE CONVERSION IF < ZERO
  357.     CPI    10        ;;CHECK LEGITIMATE DIGIT (0-9)
  358.     CMC            ;;COMPLEMENT CARRY
  359.     RC            ;;RET WITH CARRY SET IF ERROR
  360.     INX    D        ;;INCR ADDR POINTER
  361.     DAD    H        ;;SHIFT LEFT 1
  362.     PUSH    H        ;;SAVE RESULT
  363.     DAD    H
  364.     DAD    H        ;;SHIFT LEFT 2
  365.     POP    B        ;;NO * 2 TO B
  366.     DAD    B        ;;HL NOW CONTAINS 10*NO
  367.     MOV    C,A        ;;ADD PRODUCT TO DIGIT
  368.     MVI    B,0
  369.     DAD    B
  370.     JMP    DLOOP        ;;BACK FOR ANOTHER DIGIT
  371. OVERSUB:
  372. DECIN    MACRO    ?ADDR
  373.     IF    NOT NUL    ?ADDR
  374.     LXI    H,?ADDR
  375.     ENDIF
  376.     CALL    @DECIN        ;;CALL THE SUBROUTINE
  377.     MOV    A,L        ;;LEAST SIGNIFICANT HALF OF NO TO A
  378.     ENDM
  379.     DECIN    ADDR
  380.     ENDM
  381. ;
  382. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  383. ;
  384. ;    MOVE MACRO    MOVE A BLOCK FROM SOURCE TO DEST
  385. ;
  386. ;    MOVE    SOURCE,DEST,COUNT
  387. ;
  388. ;        SOURCE TO HL    MACRO ASSUMES REGISTERS ALREADY
  389. ;        DEST TO DE    LOADED IF ARG OMITTED
  390. ;        COUNT TO BC
  391. ;
  392. MOVE    MACRO    SOURCE,DEST,COUNT
  393.     LOCAL    OVERSUB
  394.     JMP    OVERSUB
  395. @MOVE:    MOV    A,B
  396.     ORA    C
  397.     RZ            ;;EXIT COUNT ZERO
  398.     MOV    A,M        ;;GET A BYTE
  399.     STAX    D        ;;STORE IT
  400.     INX    H
  401.     INX    D
  402.     DCX    B
  403.     JMP    @MOVE        ;;BACK TO MOVE LOOP
  404. OVERSUB:
  405. MOVE    MACRO    SRC,?D,?C
  406.     IF    NOT NUL SRC
  407.     LXI    H,SRC
  408.     ENDIF
  409.     IF    NOT NUL ?D
  410.     LXI    D,?D
  411.     ENDIF
  412.     IF    NOT NUL ?C
  413.     LXI    B,?C
  414.     ENDIF
  415.     CALL    @MOVE        ;;CALL THE MOVE SUBROUTINE
  416.     ENDM
  417.     MOVE    SOURCE,DEST,COUNT
  418.     ENDM
  419. ;
  420. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  421. ;
  422. ;    FILL MACRO - FILL A BLOCK OF MEMORY WITH A CONSTANT
  423. ;
  424. ;    FILL    START,STOP,CONSTANT
  425. ;
  426. ;        CONSTANT OMITTED, FILL WITH 0
  427. ;        END OMITTED, FILL ONE BYTE
  428. ;
  429. FILL    MACRO    START,STOP,CONST
  430.     LOCAL    @FILL,BLKLEN
  431. BLKLEN    SET    STOP-START+1
  432.     LXI    H,START        ;;LOAD START ADDR
  433.     IF    NOT NUL STOP
  434.     IF    BLKLEN > 255
  435.     LXI    B,BLKLEN    ;;LOAD BLOCK LENGTH
  436.     ELSE
  437.     MVI    C,BLKLEN
  438.     ENDIF
  439.     IF    NOT NUL CONST
  440.     MVI    E,CONST        ;;LOAD CONST IF NOT NULL
  441.     ELSE
  442.     MVI    E,0
  443.     ENDIF
  444. @FILL:    MOV    M,E        ;;STORE A BYTE
  445.     INX    H        ;;INCR MEMORY POINTER
  446.     IF    BLKLEN > 255
  447.     DCX    B        ;;DECR COUNT
  448.     MOV    A,C        ;;TEST LIMIT
  449.     ORA    B
  450.     JNZ    @FILL        ;;CONTINUE
  451.     ELSE
  452.     DCR    C
  453.     JNZ    @FILL
  454.     ENDIF
  455.     ELSE
  456.     IF    NUL CONST
  457.     MVI    M,0        ;;STORE A ZERO
  458.     ELSE
  459.     MVI    M,CONST        ;;STORE SINGLE BYTE
  460.     ENDIF
  461.     ENDIF
  462.     ENDM
  463. ;
  464. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  465. ;
  466. ;
  467. ;    MATCH MACRO    COMPARE 2 STRINGS OF SAME LENGTH SET CARRY IF EQUAL
  468. ;
  469. ;    MATCH    STR1,'LITERAL STRING'
  470. ;    MATCH    STR1,STR2,LENGTH
  471. ;    MATCH
  472. ;
  473. ;        DE POINTS TO STR1    MACRO WILL LOAD REG IF ARG
  474. ;        HL POINTS TO STR2    PRESENT
  475. ;        C CONTAINS LENGTH
  476. ;
  477. ;        SUBTRACT STR2 FROM STR1 AND SET FLAGS, ZERO INDICATES MATCH.
  478. ;        NORMALLY THE SECOND ARG IS A LITERAL STRING AND THE LENGTH
  479. ;        IS OMITTED. IF THE LEN ARG IS PRESENT THE SECOND STRING
  480. ;        ARG IS ASSUMED TO BE A MEMORY ADDR. IF ALL ARGUMENTS OMITTED
  481. ;        REGISTERS ASSUMED ALREADY LOADED.
  482. ;
  483. MATCH    MACRO    STR1,STR2,LEN
  484.     LOCAL    OVERSUB,M1
  485.     JMP    OVERSUB
  486. @MATCH:    INR    C        ;;PRE INCREMENT COUNT (IT MIGHT BE ZERO)
  487. M1:    DCR    C        ;;DECR LENGTH COUNT
  488.     RZ            ;;RETURN IF MATCH FOUND
  489.     LDAX    D        ;;GET A BYTE FROM ONE STRING
  490.     SUB    M        ;;COMPARE WITH OTHER
  491.     RNZ            ;;RETURN
  492.     INX    H
  493.     INX    D        ;;INCR STRING POINTERS
  494.     JMP    M1        ;;TRY SOME MORE
  495. OVERSUB:
  496. MATCH    MACRO    ?STR1,?STR2,?LEN
  497.     LOCAL    LITSTR,ENDLIT
  498.     IF    NUL ?STR1&?STR2&?LEN
  499.     CALL    @MATCH
  500.     ELSE
  501.     IF    NOT NUL ?STR1
  502.     LXI    D,?STR1        ;;LOAD STRING1 POINTER
  503.     ENDIF
  504.     IF    NUL ?LEN    ;;TEST FOR LITERAL
  505.     MVI    C,ENDLIT-LITSTR    ;;LENGTH OF LITERAL STRING
  506.     LXI    H,LITSTR    ;;POINTER TO LITERAL
  507.     CALL    @MATCH
  508.     JMP    ENDLIT
  509. LITSTR:    DB    ?STR2        ;;LITERAL STRING
  510. ENDLIT:                ;;END OF STRING
  511.     ELSE
  512.     IF    NOT NUL ?STR2
  513.     LXI    H,?STR2        ;;LOAD POINTER TO STRING2
  514.     ENDIF
  515.     MVI    C,?LEN        ;;LOAD STRING LENGTH
  516.     CALL    @MATCH        ;;CALL MATCH SUBROUTINE
  517.     ENDIF
  518.     ENDIF
  519.     ENDM
  520.     MATCH    STR1,STR2,LEN
  521.     ENDM
  522. ;
  523. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  524. ;
  525. ;    INSTR MACRO    SEARCH STRING FOR SUBSTRING AND SET CARRY IF FOUND
  526. ;
  527. ;    INSTR    STRING,LENGTH,SUBSTR
  528. ;
  529. ;        HL    POINTS TO STRING
  530. ;        DE    POINTS TO SUBSTRING
  531. ;        B    CONTAINS STRING LENGTH
  532. ;        C    CONTAINS SUBSTRING LENGTH
  533. ;
  534. ;        MACRO RETURNS POINTER TO END OF SUBSTRING IN HL
  535. ;
  536. INSTR    MACRO    STRING,LENGTH,SUBSTR
  537.     LOCAL    OVERSUB,S1,SSX
  538.     JMP    OVERSUB
  539. @INSTR:    MOV    A,B        ;;STRING LENGTH
  540.     SUB    C        ;;SUBTRACT SUBSTR LENGTH
  541.     CMC            ;;COMP CARRY
  542.     RNC            ;;ERROR RETURN SUBSTR > STRING
  543.     MOV    B,A        ;;NEW STRING LIMIT TO B
  544. S1:    SAVE
  545.     MATCH
  546.     RESTORE
  547.     JZ    SSX        ;;MATCH IF ZERO ON RET
  548.     ANA    A        ;;RESET CARRY
  549.     DCR    B        ;;BYTES LEFT
  550.     RM            ;;FINISHED IF MINUS, NO MATCH
  551.     INX    H        ;;INCR STRING POINTER
  552.     JMP    S1        ;;TRY AGAIN
  553. SSX:    MVI    B,0        ;;SET D TO 0
  554.     DAD    B
  555.     STC            ;;SET CARRY
  556.     RET
  557. OVERSUB:
  558. INSTR    MACRO    ?STR,?LEN,?SUBSTR
  559.     LOCAL    LITSTR,ENDLIT
  560.     IF    NOT NUL ?STR
  561.     LXI    H,?STR
  562.     ENDIF
  563.     MVI    B,?LEN
  564.     MVI    C,ENDLIT-LITSTR
  565.     LXI    D,LITSTR
  566.     CALL    @INSTR
  567.     JMP    ENDLIT
  568. LITSTR:    DB    ?SUBSTR
  569. ENDLIT:
  570.     ENDM
  571.     INSTR    STRING,LENGTH,SUBSTR
  572.     ENDM
  573. ;
  574. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  575. ;
  576. ;    SCAN MACRO    SCAN A STRING UNTIL A CHAR IS FOUND, SKIP BLANKS
  577. ;            AND CONTROL CHARACTERS
  578. ;
  579. ;            CARRY SET IF NUMERIC, CARRY OFF IF ALPHABETIC
  580. ;
  581. ;
  582. SCAN    MACRO    ADDR
  583.     LOCAL    OVERSUB
  584.     JMP    OVERSUB
  585. @SCAN:    MOV    A,M        ;;GET A BYTE
  586.     CPI    21H        ;;SPACE OR LESS?
  587.     RP
  588.     INX    H        ;;INCR POINTER
  589.     JMP    @SCAN        ;;KEEP SEARCHING
  590. OVERSUB:
  591. SCAN    MACRO    ?ADDR
  592.     IF    NOT NUL ?ADDR
  593.     LXI    H,?ADDR
  594.     ENDIF
  595.     CALL    @SCAN        ;;CALL SUBROUTINE
  596.     CPI    3AH        ;;NUMBER OR ALPHA
  597.     ENDM
  598.     SCAN    ADDR
  599.     ENDM
  600. ;
  601. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  602. ;
  603. ;    DISKIO MACRO    EXECUTE BDOS DISK ACCESS PRIMITIVES
  604. ;
  605. ;    DISKIO    FUNCTION,PARAMETER
  606. ;
  607. ;        NO    FUNCTION    ENTRY PARAM
  608. ;
  609. ;        12    LIFTHEAD
  610. ;        13    INITIAL
  611. ;        14    LOGIN        DISK NO 0 - 1
  612. ;        15    OPEN        FCB
  613. ;        16    CLOSE        FCB
  614. ;        17    SEARCH        FCB
  615. ;        18    SERNXT        FCB
  616. ;        19    DELETE        FCB
  617. ;        20    READ        FCB
  618. ;        21    WRITE        FCB
  619. ;        22    MAKE        FCB
  620. ;        23    RENAME        FCB
  621. ;        24    ?LOGIN
  622. ;        25    ?DRIVE
  623. ;        26    SETDMA        BUFFER
  624. ;        27    ?ALLOC
  625. ;        SEE CP/M INTERFACE GUIDE FOR DETAILED INFORMATION ON THE
  626. ;        DISK ACCESS PRIMITIVES
  627. ;
  628. ;    DISKIO    READ,FCB    (TYPICAL MACRO CALL)
  629. ;
  630. DISKIO    MACRO    FUNCTION,PARAMETER
  631. LIFTHEAD    SET    12
  632. INITIAL        SET    13
  633. LOGIN        SET    14
  634. OPEN        SET    15
  635. CLOSE        SET    16
  636. SEARCH        SET    17
  637. SERNXT        SET    18
  638. DELETE        SET    19
  639. READ        SET    20
  640. WRITE        SET    21
  641. MAKE        SET    22
  642. RENAME        SET    23
  643. ?LOGIN        SET    24
  644. ?DRIVE        SET    25
  645. SETDMA        SET    26
  646. ?ALLOC        SET    27
  647. ;
  648. ?C    SET    FUNCTION
  649.     IF    NOT NUL PARAMETER
  650.     LXI    D,PARAMETER
  651.     ENDIF
  652.     MVI    C,?C
  653.     CALL    5        ;;BDOS ENTRY
  654.     ENDM
  655. ;
  656. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  657. ;
  658. ;    CALLBIOS MACRO    CALL BIOS ROUTINES DIRECTLY
  659. ;
  660. ;    CALLBIOS    FUNCTION,PARAM
  661. ;
  662. CALLBIOS    MACRO    FUNCT,PARAM
  663.     LOCAL    @CALL
  664. ;
  665. DCOLD    SET    00H
  666. DWBOOT    SET    03H
  667. DSTAT    SET    06H
  668. DCONIN    SET    09H
  669. DCONOUT    SET    0CH        ;;CHAR IN C
  670. DLIST    SET    0FH        ;;CHAR IN C
  671. DPUNCH    SET    12H
  672. DREADER    SET    15H
  673. DHOME    SET    18H
  674. DSELDSK    SET    1BH
  675. DSETTRK    SET    1EH
  676. DSETSEC    SET    21H        ;;SECTOR NO IN C
  677. DSETDMA    SET    24H        ;;DMA ADDR IN BC
  678. DREAD    SET    27H
  679. DWRITE    SET    2AH
  680. ;
  681. ?F    SET    FUNCT
  682.     IF    NOT NUL PARAM
  683.     MVI    C,PARAM
  684.     ENDIF
  685.     LHLD    1        ;;ADDR OF BIOS
  686.     MVI    L,?F        ;;JUMP OFFSET
  687.     SHLD    @CALL+1        ;;MODIFY CALL ADDR
  688. @CALL:    CALL    0
  689.     ENDM
  690. ;
  691. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  692. ;
  693. ;    DLOAD MACRO    DOUBLE PRECISION INDEXED LOAD HL
  694. ;
  695. ;        LOAD (ADDR + INDX) TO HL
  696. ;
  697. DLOAD    MACRO    ADDR,INDX
  698.     IF    NUL INDX
  699.     LHLD    ADDR
  700.     ELSE
  701.     LHLD    INDX
  702.     LXI    D,ADDR
  703.     DAD    D
  704.     MOV    E,M
  705.     INX    H
  706.     MOV    D,M
  707.     XCHG
  708.     ENDIF
  709.     ENDM
  710. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  711. ;
  712. ;    CPHL MACRO    SUBTRACT DE FROM HL AND SET FLAGS
  713. ;
  714. CPHL    MACRO
  715.     LOCAL    @END
  716.     MOV    A,H
  717.     CMP    D        ;;COMPARE HIGH BYTES
  718.     JNZ    @END
  719.     MOV    A,L
  720.     CMP    E        ;;COMPARE LOW BYTES
  721. @END:    ENDM
  722. ;
  723. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  724. ;
  725. ;    DJZ MACRO    DOUBLE PRECISION TEST HL AND JUMP ON ZERO
  726. ;
  727. DJZ    MACRO    ADDR
  728.     MOV    A,H
  729.     ORA    L
  730.     JZ    ADDR
  731.     ENDM
  732. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  733. ;
  734. ;    DSTORE MACRO    DOUBLE PRECISION INDEXED STORE HL
  735. ;
  736. ;        STORE (HL) IN (ADDR + INDX)
  737. ;
  738. DSTORE    MACRO    ADDR,INDX
  739.     IF    NUL INDX
  740.     SHLD    ADDR
  741.     ELSE
  742.     SAVE    H
  743.     LHLD    INDX
  744.     XCHG
  745.     LXI    H,ADDR
  746.     DAD    D
  747.     RESTORE    D
  748.     MOV    M,E
  749.     INX    H
  750.     MOV    M,D
  751.     ENDIF
  752.     ENDM
  753. ;
  754. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  755. ;
  756. ;    INDEX MACRO    INDEX AN ADDRESS POINTER BY A CONSTANT
  757. ;
  758. ;    INDEX    POINTER,INCR
  759. ;
  760. INDEX    MACRO    POINTER,INCR
  761.     LHLD    POINTER
  762.     LXI    D,INCR
  763.     DAD    D        ;;DOUBLE ADD
  764.     SHLD    POINTER
  765.     ENDM
  766. ;
  767. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . .
  768. ;
  769. ;    FILFCB    MACRO    FILL IN THE ID FIELDS OF FCB
  770. ;
  771. ;    FILFCB    FCB,IDSTRING
  772. ;
  773. ;        IDSTRING CONTAINS FILE NAME AND TYPE  (FILNAM.TYP)
  774. ;        CARRY SET IF ERROR  (NAME TOO LONG)
  775. ;
  776. FILFCB    MACRO    FCB,IDSTRING
  777.     LOCAL    OVERSUB,F1,F2,F3,F4,F5,F6
  778.     JMP    OVERSUB
  779. @FLFCB: MVI    M,0        ;;CLEAR FIRST BYTE OF FCB
  780.     INX    H
  781.     PUSH    H        ;;SAVE POINTER TO NAME
  782.     MVI    C,11        ;;SIZE OF ID FIELD
  783.     MVI    A,' '        ;;SPACE TO A
  784. F1:    MOV    M,A        ;;FILL NAME WITH SPACES
  785.     INX    H
  786.     DCR    C
  787.     JNZ    F1
  788.     POP    H        ;;RESTORE NAME POINTER
  789.     MVI    C,8        ;;MAXIMUM SIZE OF NAME
  790. F2:    LDAX    D        ;;GET BYTE FROM ID FIELD
  791.     CPI    ' '        ;;LEADING SPACES?
  792.     JNZ    F3
  793.     INX    D        ;;SKIP LEADING SPACES
  794.     JMP    F2
  795. F3:    LDAX    D        ;;GET ID BYTE
  796.     CPI    0        ;;ZERO END OF FIELD
  797.     RZ
  798.     CPI    ' '        ;;SPACE END OF FIELD
  799.     RZ
  800.     CPI    '.'        ;;PERIOD TYPE SEPARATOR
  801.     JZ    F4        ;;DO TYPE
  802.     MOV    M,A        ;;STORE NAME BYTE
  803.     INX    H
  804.     INX    D        ;;INCR POINTERS
  805.     DCR    C        ;;DECR MAXIMUM COUNT
  806.     JP    F3        ;;LOOP BACK
  807.     STC            ;;SET CARRY NAME TOO LARGE
  808.     RET
  809. F4:    INX    D        ;;SKIP THE PERIOD
  810.     MOV    A,C
  811.     ORA    A
  812.     JZ    F6        ;;TEST C FOR ZERO
  813. F5:    INX    H
  814.     DCR    C
  815.     JNZ    F5        ;;INDEX TO TYPE FIELD
  816. F6:    MVI    C,3        ;;SIZE OF TYPE FIELD
  817. F7:    LDAX    D        ;;GET ID BYTE
  818.     CPI    0        ;;ZERO?
  819.     RZ            ;;FINISHED
  820.     CPI    ' '        ;;SPACE?
  821.     RZ
  822.     MOV    M,A        ;;STORE TYPE BYTE
  823.     INX    H
  824.     INX    D        ;INCR POINTERS
  825.     DCR    C        ;;DECR MAX COUNT
  826.     JNZ    F7        ;;LOOP BACK
  827.     RET
  828. OVERSUB:
  829. FILFCB    MACRO    ?FCB,?ID
  830.     IF    NOT NUL    ?ID
  831.     LXI    D,?ID
  832.     ENDIF
  833.     IF    NOT NUL ?FCB
  834.     LXI    H,?FCB
  835.     ENDIF
  836.     CALL    @FLFCB
  837.     XCHG
  838.     ENDM
  839.     FILFCB    FCB,IDSTRING
  840.     ENDM
  841. ;
  842. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  843. ;
  844. ;    SETTRK MACRO    SET AND TEST TRACK NUMBER
  845. ;
  846. ;            CARRY SET IF > 76
  847. ;
  848. SETTRK    MACRO    TRKNO
  849.     LOCAL    ENDTRK
  850.     IF    NOT NUL TRKNO
  851.     LDA    TRKNO
  852.     ENDIF
  853.     CPI    77
  854.     CMC
  855.     JC    ENDTRK
  856.     MOV    C,A        ;;TRACK NO TO C
  857.     CALLBIOS DSETTRK
  858. ENDTRK:    ENDM
  859. ;
  860. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  861. ;
  862. ;    SETSEC MACRO    SET AND TEST SECTOR NUMBER
  863. ;
  864. ;        RETURN WITH CARRY SET < 1 OR > 26
  865. ;
  866. SETSEC    MACRO    SECNO
  867.     LOCAL    ENDSEC
  868.     IF    NOT NUL SECNO
  869.     LDA    SECNO
  870.     ENDIF
  871.     ORA    A        ;CHECK ZERO
  872.     STC
  873.     JZ    ENDSEC
  874.     CPI    27        ;CHECK > 26
  875.     CMC
  876.     JC    ENDSEC
  877.     MOV    C,A        ;MOVE TO C
  878.     CALLBIOS DSETSEC
  879. ENDSEC:    ENDM
  880. ;
  881. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  882. ;
  883. ;    DSTSEC MACRO    SET AND TEST SECTOR NUMBER (Double denstiy)
  884. ;
  885. ;        RETURN WITH CARRY SET < 1 OR > 60
  886. ;
  887. DSTSEC    MACRO    DSECNO
  888.     LOCAL    ENDDSC
  889.     IF    NOT NUL DSECNO
  890.     LDA    DSECNO
  891.     ENDIF
  892.     ORA    A        ;CHECK ZERO
  893.     STC
  894.     JZ    ENDDSC
  895.     CPI    61        ;CHECK > 60
  896.     CMC
  897.     JC    ENDDSC
  898.     MOV    C,A        ;MOVE TO C
  899.     CALLBIOS DSETSEC
  900. ENDDSC:    ENDM
  901. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  902. ;
  903. ;    HALF MACRO    DIVIDES A 16 BIT NUMBER BY 2
  904. ;
  905. HALF    MACRO    I
  906.     LOCAL    OVER
  907.     JMP    OVER
  908. @HALF:    XRA    A        ;;CLEAR CARRY
  909.     MOV    A,H
  910.     RAR            ;;SHIFT UPPER HALF
  911.     MOV    H,A
  912.     MOV    A,L
  913.     RAR            ;;SHIFT LOWER HALF
  914.     MOV    L,A
  915.     RET
  916. OVER:
  917. HALF    MACRO    ?I
  918.     IF    NOT NUL ?I
  919.     LHLD    ?I
  920.     ENDIF
  921.     CALL    @HALF
  922.     ENDM
  923.     HALF    I
  924.     ENDM
  925.