home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / sigmv004.ark / SURVEY3.ASM < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  12.6 KB  |  630 lines

  1. ;***************************************;
  2. ;                    ;
  3. ;        S U R V E Y        ;
  4. ;                    ;
  5. ;***************************************;
  6.  
  7. ;By Michael Friese  9/22/79
  8.  
  9.  
  10. ;*  Lists Kbytes used and remaining plus number of files
  11. ;   on all logged disks (up to 8)
  12. ;*  Prints Memory map and synopsis of all machine memory
  13. ;*  Lists all active I/O Ports
  14. ;*  Uses disk allocation block for all disk calculations
  15. ;
  16. ;06/24/80 - Removed MACLIB statement, included required macros
  17. ;        in source.     Bruce R. Ratoff
  18. ;
  19. ;06/28/80 - Added IMS400 equate (prevents Industrial Micro Systems
  20. ;        controller from hanging up during port scan).  BRR
  21. ;
  22. ;06/29/80 - Added version number test and calculations for CP/M
  23. ;        version 2 compatibility.   This program should now work
  24. ;        properly on all versions 1.4 and later.  BRR
  25. ;
  26. ;
  27. ;
  28.  
  29. ;*******************************;
  30. ;    SYSTEM MACROS        ;
  31. ;*******************************;
  32. ;Increments 16 bit memory location X
  33. INXI    MACRO    X
  34.     LOCAL    JUST8
  35.     PUSH    H
  36.     LXI    H,X
  37.     INR    M
  38.     JNZ    JUST8
  39.     INX    H
  40.     INR    M
  41. JUST8:    POP    H
  42.     ENDM
  43. ;..................................................................
  44. ;
  45. ;    SAVE MACRO    SAVE SPECIFIED REGISTERS
  46. ;
  47. ;    SAVE    R1,R2,R3,R4
  48. ;
  49. ;        R1-R4 MAY BE B,D,H OR PSW  SAVED IN ORDER SPECIFIED
  50. ;        IF REGS ARE OMITTED SAVE B,D AND H
  51. ;
  52. SAVE    MACRO    R1,R2,R3,R4
  53.     IF NOT NUL R1&R2&R3&R4
  54.     IRP    R,<<R1>,<R2>,<R3>,<R4>>
  55.     IF    NUL R
  56.     EXITM
  57.     ENDIF
  58.     PUSH    R
  59.     ENDM
  60.     ELSE
  61.     IRPC    REG,BDH
  62.     PUSH    REG
  63.     ENDM
  64.     ENDIF
  65.     ENDM
  66. ;
  67. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  68. ;
  69. ;    RESTORE MACRO    RESTORE REGISTERS  (INVERSE OF SAVE)
  70. ;
  71. ;    RESTORE    R1,R2,R3,R4
  72. ;
  73. ;        R1-R4 MAY BE B,D,H OR PSW  RESTORED IN ORDER SPECIFIED
  74. ;        IF REGS OMITTED RESTORE H,D AND B
  75. ;
  76. RESTORE    MACRO    R1,R2,R3,R4
  77.     IF    NOT NUL R1&R2&R3&R4
  78.     IRP    R,<<R1>,<R2>,<R3>,<R4>>
  79.     IF    NUL R
  80.     EXITM
  81.     ENDIF
  82.     POP    R
  83.     ENDM
  84.     ELSE
  85.     IRPC    REG,HDB
  86.     POP    REG
  87.     ENDM
  88.     ENDIF
  89.     ENDM
  90. ;
  91. ;    . . . . . . . . . . . . . . ... ... . .. . . . . . . . .
  92. ;
  93. ;    CHAROUT MACRO    CONSOLE OUTPUT FROM A
  94. ;
  95. ;    CHAROUT    ADDR
  96. ;
  97. CHAROUT    MACRO    ADDR
  98.     IF    NOT NUL ADDR
  99.     LDA    ADDR
  100.     ENDIF
  101.     MVI    C,2        ;;CONOUT
  102.     MOV    E,A        ;;CHAR TO E
  103.     CALL    5        ;;CALL BDOS
  104.     ENDM
  105. ;
  106. ;
  107. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  108. ;
  109. ;    DECOUT MACRO    CONVERT A POSITIVE INTEGER TO DECIMAL AND OUTPUT 
  110. ;            TO THE CONSOLE.
  111. ;
  112. ;    DECOUT    ADDR
  113. ;
  114. ;        IF ADDR OMITTED, NUMBER ASSUMED TO BE IN HL, ELSE LOADED TO HL
  115. ;        LEADING ZEROS SUPRESSED. MAXIMUM NUMBER 65,767
  116. ;
  117. DECOUT    MACRO    ADDR
  118.     LOCAL    ENDDEC,DX
  119.     JMP    ENDDEC
  120. @DECOUT:SAVE            ;;PUSH STACK
  121.     LXI    B,-10        ;;RADIX FOR CONVERSION
  122.     LXI    D,-1        ;;THIS BECOMES NO DIVIDED BY RADIX
  123. DX    DAD    B        ;;SUBTRACT 10
  124.     INX    D
  125.     JC    DX
  126.     LXI    B,10
  127.     DAD    B        ;;ADD RADIX BACK IN ONCE
  128.     XCHG
  129.     MOV    A,H
  130.     ORA    L        ;;TEST FOR ZERO
  131.     CNZ    @DECOUT        ;;RECURSIVE CALL
  132.     MOV    A,E
  133.     ADI    '0'        ;;CONVERT FROM BCD TO HEX
  134.     MOV    E,A        ;;TO E FOR OUTPUT
  135.     CHAROUT            ;;CONSOLE OUTPUT
  136.     RESTORE            ;;POP STACK
  137.     RET
  138. ENDDEC:
  139. DECOUT    MACRO    ?ADDR
  140.     IF    NOT NUL ?ADDR
  141.     LHLD    ?ADDR
  142.     ENDIF
  143.     CALL    @DECOUT        ;;CALL THE SUBROUTINE
  144.     ENDM
  145.     DECOUT    ADDR
  146.     ENDM
  147. ;
  148. ;
  149. ;    . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  150. ;
  151. ;    HEXOUT MACRO    CONVERT BINARY NO AND OUTPUT TO CONSOLE
  152. ;
  153. ;    HEXOUT    ADDR
  154. ;
  155. ;        NUMBER ASSUMED IN A IF NO ARGUMENT
  156. ;
  157. HEXOUT    MACRO    ADDR
  158.     LOCAL    OUTCHR,HEXEND
  159.     JMP    HEXEND
  160. HEXPRN:    SAVE    PSW
  161.     RRC
  162.     RRC
  163.     RRC
  164.     RRC            ;;SHIFT RIGHT 4
  165.     CALL    OUTCHR
  166.     RESTORE    PSW
  167. OUTCHR: ANI    0FH        ;;MASK 4 BITS
  168.     ADI    90H        ;;ADD OFFSET
  169.     DAA            ;;DEC ADJUST
  170.     ACI    40H        ;;ADD OFFSET
  171.     DAA            ;;DEC ADJUST
  172.     MOV    E,A        ;;TO E FOR OUTPUT
  173.     MVI    C,2        ;;CONOUT
  174.     JMP    5        ;;CALL BDOS
  175. HEXEND:
  176. HEXOUT    MACRO    ?ADDR
  177.     IF    NOT NUL ?ADDR
  178.     LDA    ?ADDR
  179.     ENDIF
  180.     CALL    HEXPRN
  181.     ENDM
  182.     HEXOUT    ADDR
  183.     ENDM
  184. ;
  185. ;
  186.  
  187. ;*******************************;
  188. ;    SYSTEM EQUATES        ;
  189. ;*******************************;
  190. TRUE:    EQU    -1
  191. FALSE:    EQU    NOT TRUE
  192. TARBEL: EQU    FALSE            ; Tarbell FDC
  193. IMS400    EQU    TRUE            ; Industrial Micro Systems FDC
  194. TARBAS: EQU    0F8H            ; Base of Tarbell
  195.     IF    TARBEL
  196. SKIPORT    EQU    TARBAS+4        ; Port # to skip if Tarbell FDC
  197.     ENDIF
  198.     IF    IMS400
  199. SKIPORT    EQU    08FH            ; Port # to skip if IMS FDC
  200.     ENDIF
  201. BDOS:    EQU    5            ; Base of BDOS
  202. CRLF:    EQU    0A0DH            ; CR LF sequence
  203. CRLFE:    EQU    8A0DH            ; CR LF with EOL
  204. EOL:    EQU    80H            ; End of line
  205. TAB:    EQU    'I'-40H         ; Tab character
  206. ESC:    EQU    1BH            ; Escape character
  207. TABS:    EQU    9            ; Tab columns
  208.  
  209. ;***********************;
  210. ;    MAIN PROGRAM    ;
  211. ;***********************;
  212.     ORG    100H
  213. START:    LXI    H,0            ; Save stack pointer
  214.     DAD    SP
  215.     SHLD    OLDSP
  216.     LXI    SP,FINIS+64
  217.     CALL    TYPE            ; Type initial CRLF
  218.     DB    TAB,TAB,TAB,'*** SYSTEM SURVEY ***'
  219.     DW    CRLF,CRLFE
  220.  
  221. ;DISK SURVEY
  222.     LXI    H,8            ; Init drive counter
  223.     MVI    C,24            ; Get login vector
  224.     PUSH    H
  225.     CALL    BDOS
  226.     POP    H
  227. ROTBIT: RAR                ; RAR login bit to C
  228.     JNC    NOTLOG            ; Drive not logged
  229.     PUSH    PSW            ; Save login
  230.     PUSH    H            ; and counter
  231.  
  232. ;Print drive letter
  233.     CALL    TYPE
  234.     DB    'Drive'
  235.     DB    ' '+EOL
  236.     MVI    A,'A'            ; Get ASCII bias
  237.     ADD    H            ; Add to drive #
  238.     MOV    E,A            ; Print drive letter
  239.     CALL    TCHR
  240.     CALL    TYPE            ; and colon
  241.     DB    ':',' '+EOL
  242.     POP    H            ; Restore drive #
  243.     PUSH    H
  244.  
  245. ;Print K already allocated
  246.     MOV    E,H
  247.     MVI    C,14            ; Log drive
  248.     CALL    BDOS
  249.     MVI    C,27            ; Index allocation vect
  250.     CALL    BDOS
  251.     MOV    L,A            ; Put in decent regs
  252.     MOV    H,B
  253.     PUSH    H            ; save for later
  254.     MVI    C,12            ; get version #
  255.     CALL    BDOS
  256.     MOV    A,L            ; zero if version 1
  257.     ORA    A
  258.     JNZ    V2X            ; otherwise, use 2.x style params
  259.     LHLD    BDOS+1            ; get vers 1 style params
  260.     MVI    L,3CH
  261.     MOV    A,M            ; get block shift factor
  262.     STA    BLKSHF
  263.     INX    H
  264.     INX    H
  265.     MOV    L,M            ; get max. block number
  266.     MVI    H,0
  267.     SHLD    MAXALL
  268.     MVI    B,32            ; assume 32 bytes in block map
  269.     JMP    GETALC            ; continue
  270. V2X:    MVI    A,'?'            ; Use wild user #
  271.     STA    FCB            ; in filename search
  272.     MVI    C,31            ; Get 2.x parameter block
  273.     CALL    BDOS
  274.     INX    H
  275.     INX    H
  276.     MOV    A,M            ; Get and save ablock shift factor
  277.     STA    BLKSHF
  278.     INX    H
  279.     INX    H
  280.     INX    H
  281.     MOV    A,M            ; Get maximum block number
  282.     INX    H            ; (double precision)
  283.     MOV    H,M
  284.     MOV    L,A
  285.     SHLD    MAXALL
  286.     INX    H
  287.     MVI    B,3            ; map size is (MAXALL+1)/8
  288. V2SH:    MOV    A,H
  289.     ORA    A            ; do 16 bit right shift
  290.     RAR
  291.     MOV    H,A
  292.     MOV    A,L
  293.     RAR
  294.     MOV    L,A
  295.     DCR    B            ; 3 times
  296.     JNZ    V2SH
  297.     MOV    B,L
  298.     LDA    MAXALL            ; allow for leftover bits if any
  299.     ANI    3
  300.     JZ    GETALC
  301.     INR    B
  302. GETALC:    POP    H
  303.     LXI    D,0            ; Init group counter
  304. NXBYTE: MVI    C,8            ; Bit counter for byte
  305.     MOV    A,M            ; Get map byte
  306. NXBIT:    RAR                ; Rotate to C
  307.     JNC    NOBIT            ; No group allocated
  308.     INX    D            ; Inc group counter
  309. NOBIT:    DCR    C            ; Dec bit counter
  310.     JNZ    NXBIT
  311.     INX    H            ; Index next byte
  312.     DCR    B
  313.     JNZ    NXBYTE
  314.     CALL    SHF16
  315.     PUSH    H
  316.     CALL    BINDEC
  317.     CALL    TYPE
  318.     DB    'K bytes in',' '+EOL
  319.  
  320. ;Print number of files
  321.     LXI    D,FCB            ; Fake file cont block
  322.     MVI    C,17            ; Search for 1st file
  323.     CALL    BDOS
  324.     LXI    H,0            ; File counter
  325. LOOK:    CPI    255            ; Failure
  326.     JZ    PFILE
  327.     ADD    A            ; File offset times 2
  328.     ADD    A            ; 4
  329.     ADD    A            ; 8
  330.     ADD    A            ; 16
  331.     ADD    A            ; 32
  332.     ADI    80H            ; Make sure it's not a deleted file
  333.     MOV    E,A
  334.     MVI    D,0
  335.     LDAX    D
  336.     CPI    0E5H
  337.     JZ    LOOK1
  338.     INX    H            ; Bump file counter
  339. LOOK1:    LXI    D,FCB            ; Restore FCB
  340.     MVI    C,18            ; Look for addtl files
  341.     PUSH    H            ; Save file counter
  342.     CALL    BDOS
  343.     POP    H
  344.     JMP    LOOK
  345. PFILE:    CALL    BINDEC            ; Print # of files
  346.     CALL    TYPE
  347.     DB    ' files with',' '+EOL
  348.  
  349. ;Print K remaining
  350.     LHLD    MAXALL            ; Get number of blocks
  351.     XCHG
  352.     INX    D            ; Inc for actual value
  353.     CALL    SHF16
  354.     XCHG
  355.     POP    H
  356.     MOV    A,H            ; Ones comp & move
  357.     CMA
  358.     MOV    H,A
  359.     MOV    A,L
  360.     CMA
  361.     MOV    L,A
  362.     INX    H            ; Twos complement
  363.     DAD    D            ; and subtract
  364.     CALL    BINDEC            ; K remaining
  365.     CALL    TYPE
  366.     DB    'K bytes remaining'
  367.     DW    CRLFE
  368.  
  369. ;Set up to print next drive
  370.     POP    H            ; Restore bit counter
  371.     POP    PSW            ; and bitmap byte
  372. NOTLOG: INR    H            ; Bump drive counter
  373.     DCR    L            ; Dec bit counter
  374.     JNZ    ROTBIT
  375.  
  376. ;MEMORY SURVEY
  377. ;Create header
  378. MSURV:    CALL    TYPE
  379.     DW    CRLF
  380.     DB    'MEMORY MAP:'
  381.     DW    CRLF
  382.     DB    '0',TAB,'8',TAB,'16',TAB,'24',TAB,'32'
  383.     DB    TAB,'40',TAB,'48',TAB,'56',TAB,'64'
  384.     DW    CRLF
  385.     REPT    8
  386.     DB    '|',TAB
  387.     ENDM
  388.     DB    '|'
  389.     DW    CRLF
  390.     DB    'T'+EOL
  391.     LXI    H,RAM
  392.     MVI    M,LOW 1023        ; Init RAM counter
  393.     INX    H
  394.     MVI    M,HIGH 1023
  395.     MVI    B,4            ; Clear ROM, EMP
  396. CLREG:    INX    H
  397.     MVI    M,0
  398.     DCR    B
  399.     JNZ    CLREG
  400.     LXI    H,1024            ; Init memory pointer
  401.     MVI    C,63            ; K to be checked
  402.  
  403. ;Start of analysis loop
  404. BEGANA: LXI    D,1024            ; Byte counter
  405.     XRA    A            ; Clear flag bytes
  406.     STA    RAMF
  407.     STA    EMPF
  408. ANALP:    MOV    A,M            ; Get test byte and
  409.     MOV    B,A            ; store for later
  410.     CMA
  411.     MOV    M,A            ; Put invertd tst byte
  412.     SUB    M            ; Check for good write
  413.     MOV    M,B            ; Restore orignl data
  414.     JNZ    NOTMEM            ; Wasn't good write
  415.     INXI    RAM            ; Bump memory counter
  416.     JMP    NEXT            ; To next byte
  417.  
  418. NOTMEM: STA    RAMF            ; Not considered RAM
  419.     MVI    A,0FFH            ; Is it empty space?
  420.     SUB    B
  421.     JNZ    NOTEMP            ; Inc ROM, set flag
  422.     LDA    EMPF            ; Any non empty space
  423.     ANA    A            ; before here?
  424.     JZ    NEXT
  425.     JMP    NOTEM            ; To next byte
  426. NOTEMP: STA    EMPF            ; Set no empty flag
  427. NOTEM:    INXI    ROM
  428. NEXT:    INX    H            ; Index next byte
  429.     DCX    D            ; Decrement K counter
  430.     XRA    A
  431.     ORA    D
  432.     ORA    E
  433.     JNZ    ANALP            ; K counter not 0
  434.     PUSH    B
  435.     PUSH    H
  436.     LDA    RAMF            ; Is it RAM?
  437.     ANA    A
  438.     JNZ    NOTRAM            ; No
  439.     LDA    BDOS+2            ; Yes, get top of TPA
  440.     DCR    H
  441.     CMP    H            ; Compare with pointer
  442.     JC    NOTTPA
  443.     CALL    TYPE            ; It's TPA
  444.     DB    'T'+EOL
  445.     JMP    NEXTK
  446. NOTTPA: ADI    20            ; Get base of bios
  447.     JNC    EVALC
  448.     MVI    A,0FFH
  449. EVALC:    CMP    H
  450.     JC    NOTCPM
  451.     CALL    TYPE            ; It's CPM
  452.     DB    'C'+EOL
  453.     JMP    NEXTK
  454. NOTCPM: CALL    TYPE
  455.     DB    'M'+EOL         ; It's just memory
  456.     JMP    NEXTK
  457. NOTRAM: LDA    EMPF            ; Is it empty?
  458.     ANA    A
  459.     JZ    NOMEM            ; Yes, no memory
  460.     CALL    TYPE            ; No, must be ROM
  461.     DB    'R'+EOL
  462.     JMP    NEXTK
  463. NOMEM    CALL    TYPE
  464.     DB    ' '+EOL
  465. NEXTK:    POP    H
  466.     POP    B
  467.     DCR    C            ; Decrement K counter
  468.     JNZ    BEGANA
  469.     CALL    TYPE
  470.     DW    CRLF,CRLF
  471.     DB    'T=TPA',TAB,'C=CPM',TAB,'M=Unassigned Memory'
  472.     DB    TAB,'R=ROM or Bad Memory'
  473.     DW    CRLF,CRLFE
  474.  
  475. ;MEMORY SYNOPSIS
  476.     LHLD    RAM
  477.     PUSH    H            ; Save RAM
  478.     CALL    BINDEC            ; Type RAM
  479.     CALL    TYPE
  480.     DB    ' Bytes RAM',TAB,TAB+EOL
  481.     LHLD    ROM
  482.     PUSH    H
  483.     CALL    BINDEC            ; Type ROM
  484.     CALL    TYPE
  485.     DB    ' Bytes ROM',TAB,TAB+EOL
  486.     LHLD    BDOS+1
  487.     CALL    BINDEC
  488.     CALL    TYPE
  489.     DB    ' Bytes in TPA'
  490.     DW    CRLFE
  491.     POP    D            ; Get RAM
  492.     POP    H            ; Get RAM
  493.     DAD    D            ; Add 'em
  494.     PUSH    H            ; and save result
  495.     LXI    D,0            ; Subtract from this
  496.     MOV    A,H            ; Complement 16 bits
  497.     CMA
  498.     MOV    H,A
  499.     MOV    A,L
  500.     CMA
  501.     MOV    L,A            ; 2s comp bias in D
  502.     DAD    D            ; Subtract
  503.     CALL    BINDEC
  504.     CALL    TYPE
  505.     DB    ' Bytes Empty   ',TAB+EOL
  506.     POP    H            ; Restore RAM+ROM
  507.     CALL    BINDEC
  508.     CALL    TYPE
  509.     DB    ' Total Active Bytes'
  510.     DW    CRLF,CRLF
  511.  
  512. ;PORT SURVEY
  513.     DB    'ACTIVE I/O PORTS'
  514.     DW    CRLFE
  515.     LXI    H,1000H            ; DELAY SO MESSAGE OUTPUT
  516. PDLY:    DCX    H            ; DOESN'T GIVE A FALSE READING
  517.     MOV    A,H            ; ON CONSOLE STATUS PORT
  518.     ORA    L
  519.     JNZ    PDLY
  520.     LXI    H,0            ; Intit port counter
  521.     LXI    D,TABS            ; Init tab & port ctrs
  522. PORTLP: MOV    A,D
  523.     IF    TARBEL OR IMS400    ; Single port mask
  524.     CPI    SKIPORT
  525.     JZ    ISPORT            ; Print mask port
  526.     ENDIF
  527.     STA    INPORT+1
  528. INPORT: IN    0            ; Modifiable code
  529.     CPI    0FFH            ; Active port?
  530.     JZ    NEXTPT            ; No, get next
  531. ISPORT: MOV    A,D            ; Get port #
  532.     PUSH    D
  533.     PUSH    H
  534.     HEXOUT
  535.     POP    H
  536.     POP    D
  537.     INX    H
  538.     DCR    E            ; Dec tab counter
  539.     JNZ    TAB1
  540.     MVI    E,TABS            ; Reset tab counter
  541.     CALL    TYPE
  542.     DW    CRLFE
  543.     JMP    NEXTPT            ; Get next port
  544. TAB1:    CALL    TYPE            ; Tab out 1
  545.     DB    TAB+EOL
  546. NEXTPT: INR    D            ; Bump port counter
  547.     JNZ    PORTLP            ; Not done
  548.     CALL    TYPE            ; Done
  549.     DW    CRLFE
  550.     CALL    BINDEC
  551.     CALL    TYPE            ; Type Active Ports
  552.     DB    ' Ports active'
  553.     DW    CRLFE
  554.  CCP:    LHLD    OLDSP
  555.     SPHL
  556.     RET
  557.  
  558.  
  559. ;***********************;
  560. ;    SUBROUTINES    ;
  561. ;***********************;
  562.  
  563. ;Binary to decimal conversion
  564. BINDEC: DECOUT                ; From LIB
  565.     RET
  566.  
  567. ;Types a string of text terminated with bit 7 high
  568. TYPE:    XTHL                ; Get string address
  569.     PUSH    D
  570. TYPELP: MOV    A,M            ; Get type data
  571.     MOV    D,A            ; Save for later
  572.     ANI    7FH            ; Mask ASCII
  573.     MOV    E,A
  574.     PUSH    H
  575.     PUSH    D
  576.     CALL    TCHR
  577.     POP    D
  578.     POP    H
  579.     INX    H
  580.     MVI    A,EOL            ; End of line bit
  581.     ANA    D
  582.     JP    TYPELP            ; Not done
  583.     POP    D
  584.     XTHL                ; Get return address
  585.     RET
  586.  
  587. ;Types a single character on console
  588. TCHR:    MVI    C,2
  589.     JMP    BDOS
  590.  
  591. ;Checks sectors per block and multiplies or divides block size
  592. ;Enter with data in D. Result returned in H,L
  593. SHF16:    LDA    BLKSHF            ; Get shift factor (gives block size)
  594.     CPI    3            ; Is it 1K (std)?
  595.     JNZ    NOT3
  596.     MOV    L,E            ; Yes, use present #
  597. ZH:    MVI    H,0
  598.     RET
  599. NOT3:    CPI    2            ; Is it minifloppy?
  600.     JNZ    NOT2
  601.     MOV    A,E            ; Yes, divide by 2
  602.     RRC
  603.     ANI    7FH
  604.     MOV    L,A
  605.     JMP    ZH
  606. NOT2:    SUI    3            ; Must be something
  607.     MOV    B,A            ; larger like double
  608.     XCHG                ; sided or double dens
  609. BITSHF: DAD    H            ; 16 bit 2^(B-1)
  610.     DCR    B
  611.     JNZ    BITSHF
  612.     RET
  613.  
  614.  
  615. ;***********************;
  616. ;    DATA STORAGE    ;
  617. ;***********************;
  618.  
  619. FCB:    DB    0,'???????????',0,0,0    ; File control block
  620.     DS    17            ; Extra FCB workspace
  621. OLDSP:    DS    2            ; Old stack pointer
  622. RAM:    DS    2            ; RAM counter
  623. ROM:    DS    2            ; ROM counter
  624. RAMF:    DS    1            ; RAM good flag
  625. EMPF:    DS    1            ; Empty so far flag
  626. BLKSHF:    DS    1            ; block shift factor
  627. MAXALL:    DS    2            ; maximum block number
  628. FINIS    EQU    $            ; End of program
  629.     END
  630.