home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sampler0 / owner.asm < prev    next >
Assembly Source File  |  1987-04-21  |  30KB  |  676 lines

  1. PAGE ,132
  2. TITLE Cluster Owner Program, Version 1.61, 21-Apr-1987
  3.  
  4. ;
  5. ; Written By Steven Georgiades
  6. ;
  7. ;
  8. ;       If you have any questions or comments about this or any other
  9. ;       SMG program, call or write:
  10. ;
  11. ;               Steven M. Georgiades
  12. ;               SMG Software
  13. ;               701-H South Hayward Street
  14. ;               Anaheim, CA 92804
  15. ;
  16.  
  17. CODE      SEGMENT BYTE PUBLIC 'CODE'
  18.  
  19.           ASSUME  CS:CODE,DS:CODE,ES:CODE,SS:CODE
  20.  
  21.           ORG     5CH
  22.  
  23. FCB       LABEL   BYTE
  24.  
  25.           ORG     80H
  26.  
  27. PARAM     LABEL   BYTE
  28.  
  29.           ORG     100H
  30.  
  31. OWNER:    JMP     BEGIN
  32.  
  33. DIGIT     DB      "0123456789ABCDEF"
  34. PARM_ERR  DB      "Illegal Parameter!",7
  35. CRLF      DB      13,10,"$"
  36. READERR   DB      "Error Reading Drive X:",7,13,10,"$"
  37. SIGNON    DB      "Cluster Owner Program, Version 1.61",13,10
  38.           DB      "SMG Software",13,10
  39.           DB      "(C) Copyright 1986,1987 Steven Georgiades",13,10,10,"$"
  40. USAGE     DB      "Usage:",13,10,10
  41.           DB      "  OWNER [d:] n [[d:] n [...]]",13,10,10
  42.           DB      "    d: = Optional Drive Letter",13,10
  43.           DB      "    n  = Cluster Number to Check",13,10,10,"$"
  44. CLUSTMSG  DB      "Cluster XXXXX $"
  45. OWNERMSG  DB      "is Owned by $"
  46. BADMSG    DB      "is Marked as Bad",13,10,"$"
  47. FREEMSG   DB      "is not is Use by any File",13,10,"$"
  48. INVALID   DB      "does not Exist!",7,13,10,"$"
  49. LOSTMSG   DB      "Appears to be Lost!",7,13,10,"$"
  50. RESVMSG   DB      "is Reserved",13,10,"$"
  51.  
  52. CLSTSEC   DW      ?
  53. CLSTTOT   DW      ?
  54. CLUST     DW      ?
  55. DIR_LEN   DW      ?
  56. DIRBUF    DW      ?
  57. DIRSEC    DW      ?
  58. DRIVE     DB      ?
  59. EOF       DW      0FF8H
  60. FATSEC    DW      ?
  61. FATSIZE   DB      3
  62. LASTDRV   DB      -1
  63. RDIR_LEN  DW      ?
  64. SECSIZE   DW      ?
  65. STARTSEC  DW      ?
  66.  
  67. DIRNAME   DB      14 DUP(?)
  68. FILESPEC  DB      "X:\"
  69. PATH      DB      "$",79 DUP(?)
  70. FILENAME  DB      14 DUP(?)
  71.  
  72. BEGIN:    MOV     AH,9                          ; Output Sign-On Message
  73.           MOV     DX,OFFSET SIGNON
  74.           INT     21H
  75.           MOV     AH,19H                        ; Get Default Drive Number
  76.           INT     21H
  77.           MOV     DRIVE,AL                      ;   and Save
  78.           MOV     SI,OFFSET PARAM               ; Set up Pointer to Parameter
  79.           LODSB                                 ; Read Parameter Length
  80.           CMP     AL,2
  81.           JNB     GET_PARM
  82.           MOV     DX,OFFSET USAGE
  83.           JMP     SHORT GET_OW03
  84. GET_PARM: CBW
  85.           MOV     BX,AX
  86.           MOV     BYTE PTR [SI][BX],0           ; Terminate Parameter String
  87. STRIP:    LODSB                                 ; Strip Off Leading Whitespace
  88.           CMP     AL,' '
  89.           JE      STRIP
  90.           CMP     AL,9
  91.           JE      STRIP
  92.           OR      AL,AL                         ; If End-of-Parameter,
  93.           JZ      EXIT                          ;   Continue Proccessing
  94.           CMP     BYTE PTR [SI],':'             ; If Drive Letter,
  95.           JNE     NOTDRIVE
  96.           AND     AL,0DFH                       ;   Convert to Drive Number
  97.           SUB     AL,'A'
  98.           MOV     DRIVE,AL                      ;   and Save
  99.           LODSB                                 ;   Skip Colon
  100.           JMP     SHORT STRIP                   ;   Continue
  101. NOTDRIVE: DEC     SI                            ; ReUse Last Character
  102.           CALL    GET_WORD                      ; Read Cluster Number (Hex)
  103.           JNE     PARM_OK                       ; If Error,
  104. PARMERR:  MOV     DX,OFFSET PARM_ERR            ;   Output Parameter Error
  105.           MOV     AH,9
  106.           INT     21H
  107.           MOV     AX,4C01H                      ;   Exit to DOS
  108.           INT     21H
  109. PARM_OK:  MOV     CLUST,DX                      ; Save Cluster Number
  110.           CALL    GET_OWNR                      ; Find Cluster Owner
  111.           JMP     SHORT STRIP                   ; Get Next Parameter
  112. EXIT:     MOV     AX,4C00H                      ; Exit to DOS
  113.           INT     21H
  114.  
  115. GET_OWNR: PUSH    AX                            ; Save Registers
  116.           PUSH    BX
  117.           PUSH    CX
  118.           PUSH    DX
  119.           PUSH    DI
  120.           PUSH    SI
  121.           MOV     PATH,'$'                      ; Initialize Path
  122.           MOV     AL,DRIVE                      ; If drive has changed,
  123.           CMP     AL,LASTDRV
  124.           JNE     GET_OW01
  125.           JMP     GET_OW07
  126. GET_OW01: MOV     LASTDRV,AL                    ;   Last Drive = This Drive
  127.           MOV     CX,1                          ;   Read Boot Record
  128.           MOV     DX,0
  129.           MOV     BX,OFFSET FATBUF
  130.           INT     25H
  131.           JNC     GET_OW04                      ;   If Error,
  132. GET_OW02: POPF
  133.           MOV     AL,DRIVE                      ;     Convert Drive Number
  134.           ADD     AL,'A'
  135.           MOV     READERR[20],AL
  136.           MOV     DX,OFFSET READERR             ;     Point to Read Error
  137. GET_OW03: MOV     AH,9                          ;     Output Error Message
  138.           INT     21H
  139.           MOV     AX,4C01H                      ;     Exit to DOS
  140.           INT     21H
  141. GET_OW04: POPF
  142.           MOV     AX,FATBUF[11]                 ;   Read Sector Size
  143.           MOV     SECSIZE,AX                    ;     and Save
  144.           MOV     AL,BYTE PTR FATBUF[13]        ;   Read Sectors per Cluster
  145.           XOR     AH,AH
  146.           MOV     CLSTSEC,AX                    ;     and Save
  147.           MOV     CX,FATBUF[14]                 ;   Read # of Reserved Sectors
  148.           MOV     AL,BYTE PTR FATBUF[16]        ;   Read # of FAT's
  149.           XOR     AH,AH                         ;   Convert to Word
  150.           MOV     BX,FATBUF[22]                 ;   Read Sectors per FAT
  151.           MOV     FATSEC,BX
  152.           MUL     BX                            ;   Calculate Total FAT Sectors
  153.           ADD     CX,AX                         ;   Add to Reserved Sectors
  154.           MOV     AX,FATBUF[17]                 ;   Read Number of DIR Entries
  155.           MOV     RDIR_LEN,AX
  156.           PUSH    CX                            ;   Calculate DIR Sectors
  157.           MOV     CL,5
  158.           SHL     AX,CL
  159.           POP     CX
  160.           MOV     BX,SECSIZE
  161.           XOR     DX,DX
  162.           DIV     BX
  163.           OR      DX,DX                         ;   Adjust for Partial Sector
  164.           JZ      GET_OW05
  165.           INC     AX
  166. GET_OW05: MOV     DIRSEC,AX                     ;   Save DIR Sectors
  167.           ADD     CX,AX                         ;   Add DIR Sectors to Reserved
  168.           MOV     STARTSEC,CX                   ;   Save in STARTSEC
  169.           MOV     AX,FATSEC                     ;   Determine FAT Buffer Size
  170.           MOV     BX,SECSIZE
  171.           MUL     BX
  172.           ADD     AX,OFFSET FATBUF
  173.           MOV     DIRBUF,AX                     ;   Save DIRBUF Pointer
  174.           MOV     AX,FATBUF[19]                 ;   Read Total Sectors on Media
  175.           SUB     AX,CX                         ;   Calc. Total Data Clusters
  176.           MOV     BX,CLSTSEC
  177.           XOR     DX,DX
  178.           DIV     BX
  179.           ADD     AX,2
  180.           MOV     CLSTTOT,AX                    ;     and Save
  181.           CMP     AX,4081                       ;   Adjust FAT Size
  182.           JLE     GET_OW06
  183.           MOV     FATSIZE,4
  184.           MOV     EOF,0FFF8H
  185.           JMP     SHORT GET_OW07
  186. GET_OW06: MOV     FATSIZE,3
  187.           MOV     EOF,0FF8H                      
  188. GET_OW07: MOV     AL,DRIVE                      ; Read FAT
  189.           MOV     CX,FATSEC
  190.           MOV     DX,1
  191.           MOV     BX,OFFSET FATBUF
  192.           INT     25H
  193.           JNC     GET_OW08
  194.           JMP     GET_OW02                      ; If Error, Say So
  195. GET_OW08: POPF
  196.           MOV     BX,CLUST                      ; Get Cluster Number
  197.           MOV     AX,BX                         ; Convert Cluster # to Decimal
  198.           MOV     DI,OFFSET CLUSTMSG[13]
  199.           CALL    DEC5OUT
  200.           CALL    STRIP0                        ; Strip Off Leading Zeroes
  201.           MOV     AH,9
  202.           MOV     DX,OFFSET CLUSTMSG            ; Output Cluster Message
  203.           INT     21H
  204.           CMP     BX,CLSTTOT                    ; Test Cluster Number
  205.           JNB     GET_OW09
  206.           CMP     BX,2
  207.           JNB     GET_OW10
  208. GET_OW09: MOV     DX,OFFSET INVALID             ; If Invalid, Say So
  209.           JMP     SHORT GET_OW17
  210. GET_OW10: CALL    NEXTCLST                      ; Determine Next Cluster
  211.           OR      BX,BX                         ; If Not in Use, Say So
  212.           JNZ     GET_OW11
  213.           MOV     DX,OFFSET FREEMSG
  214.           JMP     SHORT GET_OW17
  215. GET_OW11: MOV     AX,EOF                        ; If In Use, Continue
  216.           CMP     BX,AX
  217.           JAE     GET_OW13
  218.           DEC     AX                            ; If Bad, Say So
  219.           CMP     BX,AX
  220.           JNE     GET_OW12
  221.           MOV     DX,OFFSET BADMSG
  222.           JMP     SHORT GET_OW17
  223. GET_OW12: SUB     AX,7                          ; If Reserved, Say So
  224.           CMP     BX,AX
  225.           JB      GET_OW13
  226.           MOV     DX,OFFSET RESVMSG
  227.           JMP     SHORT GET_OW17
  228. GET_OW13: MOV     AX,CLUST                      ; Get Cluster Number
  229. GET_OW14: MOV     BX,AX                         ; Get Previous Cluster in Chain
  230.           CALL    PREVCLST
  231.           OR      AX,AX                         ; If Not First, Repeat
  232.           JNZ     GET_OW14
  233.           MOV     CLUST,BX                      ; Save First Cluster in Chain
  234. GET_OW15: CALL    GETDIR                        ; Load the Current Directory
  235.           CALL    SRCHCLST                      ; Search Directory for Cluster
  236.           JNC     GET_OW16                      ; If Found, Exit Search Loop
  237.           CALL    SRCHDIR                       ; Search Dir for Sub-Directory
  238.           JNC     GET_OW15                      ; If Found, Continue Search Loop
  239.           CALL    DIRNEXT                       ; Use Next Sub-Directory
  240.           JNC     GET_OW15                      ; If Found, Continue Search Loop
  241.           MOV     DX,OFFSET LOSTMSG             ; Else Couldn't find Cluster
  242.           JMP     SHORT GET_OW17
  243. GET_OW16: MOV     AL,DRIVE                      ; Convert Drive Number to Letter
  244.           ADD     AL,'A'
  245.           MOV     FILESPEC,AL
  246.           MOV     AH,9                          ; Output Owner Message
  247.           MOV     DX,OFFSET OWNERMSG
  248.           INT     21H
  249.           MOV     DX,OFFSET FILESPEC            ; Output FileSpec
  250.           INT     21H
  251.           MOV     DX,OFFSET FILENAME            ; Output FileName
  252.           INT     21H
  253.           MOV     DX,OFFSET CRLF
  254. GET_OW17: MOV     AH,9
  255.           INT     21H
  256.           POP     SI                            ; Restore Registers
  257.           POP     DI
  258.           POP     DX
  259.           POP     CX
  260.           POP     BX
  261.           POP     AX
  262.           RET                                   ; Done
  263.  
  264. GETDIR:   PUSH    AX                            ; Save Registers
  265.           PUSH    BX
  266.           PUSH    CX
  267.           PUSH    DX
  268.           PUSH    DI
  269.           PUSH    SI
  270.           MOV     AL,DRIVE                      ; Read Root Directory
  271.           MOV     CX,DIRSEC
  272.           MOV     DX,STARTSEC
  273.           SUB     DX,CX
  274.           MOV     BX,DIRBUF
  275.           INT     25H
  276.           POPF
  277.           MOV     AX,RDIR_LEN                   ; DIR Length = Root DIR Length
  278.           MOV     DIR_LEN,AX
  279.           MOV     SI,OFFSET PATH                ; Point to First Element of Path
  280. GETDIR1:  MOV     DI,OFFSET DIRNAME             ; Point to FileName Buffer
  281. GETDIR2:  LODSB                                 ; Copy Path Element to FileName
  282.           CMP     AL,'\'                        ;   until '\' or '$'
  283.           JE      GETDIR3
  284.           CMP     AL,'$'
  285.           JE      GETDIR4
  286.           STOSB
  287.           JMP     SHORT GETDIR2
  288. GETDIR3:  MOV     AL,0                          ; Read Subdirectory
  289.           STOSB
  290.           CALL    READDIR
  291.           JC      GETDIR5                       ; If Error, Say So
  292.           JMP     SHORT GETDIR1                 ; Get Next Element
  293. GETDIR4:  CLC                                   ; Clear Error Flag
  294. GETDIR5:  POP     SI                            ; Restore Registers
  295.           POP     DI
  296.           POP     DX
  297.           POP     CX
  298.           POP     BX
  299.           POP     AX
  300.           RET                                   ; Done
  301.  
  302. READDIR:  PUSH    CX                            ; Save Registers
  303.           PUSH    DI
  304.           PUSH    SI
  305.           CALL    SRCHFILE                      ; Search for DIR
  306.           JC      READDIR2                      ; If Not Found, Error
  307.           MOV     BX,[BX+26]                    ; Get Starting Cluster Number
  308.           MOV     DIR_LEN,0                     ; DIR Length = 0
  309.           OR      BX,BX                         ; If Start Cluster = 0, Error
  310.           JZ      READDIR2
  311.           MOV     AX,SECSIZE                    ; Calculate DIR Entries/Cluster
  312.           MOV     CX,CLSTSEC
  313.           MUL     CX
  314.           MOV     CL,5
  315.           SHR     AX,CL
  316.           MOV     CX,AX
  317.           MOV     DI,DIRBUF                     ; Point to DIR Buffer
  318. READDIR1: CALL    READCLST                      ; Read Cluster
  319.           ADD     DIR_LEN,CX                    ; Increment DIR Length
  320.           CMP     BX,EOF                        ; If Not Last Cluster,
  321.           JB      READDIR1                      ;   Get Next Cluster
  322.           JMP     SHORT READDIR3                ; Done Reading DIR
  323. READDIR2: STC                                   ; Set Error Flag
  324. READDIR3: POP     SI                            ; Restore Registers
  325.           POP     DI
  326.           POP     CX
  327.           RET                                   ; Done
  328.  
  329. DIRNEXT:  PUSH    AX                            ; Save Registers
  330.           PUSH    BX
  331.           PUSH    CX
  332.           PUSH    DI
  333.           PUSH    SI
  334. DIRNEXT1: MOV     DI,OFFSET PATH                ; Scan to End of Path
  335.           MOV     CX,80
  336.           MOV     AL,'$'
  337.           REPNE   SCASB
  338.           JNE     DIRNEXT3                      ; If No End, Error
  339.           CMP     CX,79                         ; If Null Path, Error
  340.           JE      DIRNEXT3
  341.           STD                                   ; Auto-Decrement
  342.           MOV     AX,78                         ; Determine Path Length
  343.           SUB     AX,CX
  344.           MOV     CX,AX
  345.           SUB     DI,2                          ; Point to End of DirName
  346.           MOV     AL,0                          ; Set End of DirName
  347.           STOSB
  348.           MOV     AL,'\'                        ; Scan to Previous DirName
  349.           REPNE   SCASB
  350.           JE      DIRNEXT2                      ; If Not Found,
  351.           MOV     DI,OFFSET PATH[-2]            ;   Point to Start of Path
  352. DIRNEXT2: CLD                                   ; Auto-Increment
  353.           ADD     DI,2                          ; Copy Last SubDir to FileName
  354.           PUSH    DI
  355.           MOV     SI,DI
  356.           MOV     DI,OFFSET FILENAME
  357.           CALL    MOVSTR
  358.           POP     DI
  359.           MOV     AL,'$'                        ; Terminate Path String
  360.           STOSB
  361.           CALL    GETDIR                        ; Read Directory
  362.           JC      DIRNEXT4                      ; If Error, Say So
  363.           MOV     SI,OFFSET FILENAME
  364.           MOV     DI,OFFSET DIRNAME
  365.           CALL    MOVSTR
  366.           CALL    SRCHFILE                      ; Search for FileName
  367.           JC      DIRNEXT4                      ; If Error, Say So
  368.           MOV     SI,BX                         ; Save Pointer
  369.           ADD     SI,32                         ; Point to Next Dir Entry
  370.           MOV     AX,SI                         ; Determine Dir Entry Count
  371.           SUB     AX,DIRBUF
  372.           MOV     CL,5
  373.           SHR     AX,CL
  374.           MOV     CX,DIR_LEN
  375.           SUB     CX,AX
  376.           CALL    FINDDIR                       ; Find Next SubDirectory
  377.           JC      DIRNEXT1
  378.           JMP     SHORT DIRNEXT4
  379. DIRNEXT3: STC                                   ; Set Error Return Flag
  380. DIRNEXT4: POP     SI                            ; Restore Registers
  381.           POP     DI
  382.           POP     CX
  383.           POP     BX
  384.           POP     AX
  385.           RET                                   ; Done
  386.  
  387. SRCHDIR:  PUSH    CX                            ; Save Registers
  388.           PUSH    SI
  389.           MOV     SI,DIRBUF                     ; Point to First DIR Entry
  390.           MOV     CX,DIR_LEN                    ; Load DIR Length
  391.           CALL    FINDDIR                       ; Find SubDirectory
  392.           POP     SI                            ; Restore Registers
  393.           POP     CX
  394.           RET                                   ; Done
  395.  
  396. FINDDIR:  PUSH    AX                            ; Save Registers
  397.           PUSH    DI
  398. FINDDIR1: JCXZ    FINDDIR4                      ; If Zero, Not Found
  399. FINDDIR2: CMP     BYTE PTR [SI],0               ; If Null, End of Search
  400.           JE      FINDDIR4
  401.           CMP     BYTE PTR [SI],'.'             ; If '.' or '..', Skip
  402.           JE      FINDDIR3
  403.           CMP     BYTE PTR [SI],0E5H            ; If Deleted, Skip
  404.           JE      FINDDIR3
  405.           TEST    BYTE PTR [SI+11],10H          ; Test File Attribute
  406.           JNZ     FINDDIR5                      ; If Match, Found
  407. FINDDIR3: ADD     SI,32                         ; Else Next DIR Entry
  408.           LOOP    FINDDIR2                      ; and Repeat
  409. FINDDIR4: STC                                   ; Set Error Flag
  410.           JMP     SHORT FINDDIR6                ; Done
  411. FINDDIR5: MOV     DI,OFFSET DIRNAME
  412.           CALL    UNPARSE                       ; UnParse Directory Name
  413.           MOV     DI,OFFSET PATH                ; Search for End of Path
  414.           MOV     AL,'$'
  415.           MOV     CX,80
  416.           REPNE   SCASB
  417.           JNE     FINDDIR4                      ; If Not Found, Error
  418.           DEC     DI
  419.           MOV     BX,SI                         ; Set Pointer to DIR Entry
  420.           MOV     SI,OFFSET DIRNAME             ; Copy Directory Name to Path
  421.           CALL    MOVSTR
  422.           DEC     DI
  423.           MOV     AX,'$\'                       ; Terminate Path
  424.           STOSW
  425.           CLC                                   ; Clear Error Flag
  426. FINDDIR6: POP     DI                            ; Restore Registers
  427.           POP     AX
  428.           RET                                   ; Done
  429.  
  430. SRCHFILE: PUSH    AX                            ; Save Register
  431.           PUSH    CX
  432.           PUSH    DI
  433.           PUSH    SI
  434.           MOV     AX,2900H                      ; Parse Filename
  435.           MOV     SI,OFFSET DIRNAME
  436.           MOV     DI,OFFSET FCB
  437.           INT     21H
  438.           INC     DI                            ; Point to Filename in FCB
  439.           MOV     SI,DIRBUF                     ; Point to Start of DIRBUF
  440.           MOV     CX,DIR_LEN                    ; Load DIR Length
  441.           JCXZ    SRCHFIL2                      ; If Zero, Not Found
  442. SRCHFIL1: PUSH    CX                            ; Save Registers
  443.           PUSH    DI
  444.           PUSH    SI
  445.           MOV     CX,11                         ; Compare Filename
  446.           REPE    CMPSB
  447.           POP     SI                            ; Restore Registers
  448.           POP     DI
  449.           POP     CX
  450.           JE      SRCHFIL3                      ; If Match, Found
  451.           ADD     SI,32                         ; Else Next DIR Entry
  452.           LOOP    SRCHFIL1                      ; and Repeat
  453. SRCHFIL2: STC                                   ; Set Error Flag
  454.           JMP     SHORT SRCHFIL4                ; Done
  455. SRCHFIL3: MOV     BX,SI                         ; Set Pointer to DIR Entry
  456.           CLC                                   ; Clear Error Flag
  457. SRCHFIL4: POP     SI                            ; Restore Registers
  458.           POP     DI
  459.           POP     CX
  460.           POP     AX
  461.           RET                                   ; Done
  462.  
  463. SRCHCLST: PUSH    AX                            ; Save Register
  464.           PUSH    CX
  465.           PUSH    DI
  466.           PUSH    SI
  467.           MOV     SI,DIRBUF                     ; Point to First DIR Entry
  468.           MOV     CX,DIR_LEN                    ; Load DIR Length
  469.           JCXZ    SRCHCLS3                      ; If Zero, Not Found
  470.           MOV     BX,CLUST
  471. SRCHCLS1: CMP     BYTE PTR [SI],0               ; If Null, End of Search
  472.           JE      SRCHCLS3
  473.           CMP     BYTE PTR [SI],'.'             ; If '.' or '..', Skip
  474.           JE      SRCHCLS2
  475.           CMP     BYTE PTR [SI],0E5H            ; If Deleted, Skip
  476.           JE      SRCHCLS2
  477.           CMP     BX,[SI+26]                    ; Compare Start Cluster Number
  478.           JE      SRCHCLS4                      ; If Match, Found
  479. SRCHCLS2: ADD     SI,32                         ; Else Next DIR Entry
  480.           LOOP    SRCHCLS1                      ; and Repeat
  481. SRCHCLS3: STC                                   ; Set Error Flag
  482.           JMP     SHORT SRCHCLS5                ; Done
  483. SRCHCLS4: MOV     DI,OFFSET FILENAME            ; UnParse File Name
  484.           CALL    UNPARSE
  485.           CLC                                   ; Clear Error Flag
  486. SRCHCLS5: POP     SI                            ; Restore Registers
  487.           POP     DI
  488.           POP     CX
  489.           POP     AX
  490.           RET                                   ; Done
  491.  
  492. READCLST: PUSH    AX                            ; Save Registers
  493.           PUSH    CX
  494.           PUSH    DX
  495.           MOV     AX,BX                         ; Calculate Absolute Sector #
  496.           SUB     AX,2
  497.           MOV     CX,CLSTSEC
  498.           MUL     CX
  499.           ADD     AX,STARTSEC
  500.           MOV     DX,AX
  501.           MOV     AL,DRIVE
  502.           PUSH    BX                            ; Save Registers
  503.           PUSH    DI
  504.           MOV     BX,DI                         ; Read Cluster
  505.           INT     25H
  506.           POPF
  507.           POP     DI                            ; Restore Registers
  508.           POP     BX
  509.           CALL    NEXTCLST                      ; Get Next Cluster Number
  510.           MOV     AX,CLSTSEC                    ; Increment Buffer Pointer
  511.           MOV     CX,SECSIZE
  512.           MUL     CX
  513.           ADD     DI,AX
  514.           POP     DX                            ; Restore Registers
  515.           POP     CX
  516.           POP     AX
  517.           RET                                   ; Done
  518.  
  519. PREVCLST: PUSH    BX                            ; Save Registers
  520.           PUSH    CX
  521.           PUSH    DX
  522.           MOV     DX,BX                         ; Reserve Cluster Number
  523.           MOV     CX,CLSTTOT                    ; Start Looking at Last Cluster
  524. PREVCLS1: MOV     BX,CX                         ; Check Cluster
  525.           INC     BX
  526.           CALL    NEXTCLST
  527.           CMP     BX,DX                         ; If Match, Use It
  528.           LOOPNE  PREVCLS1                      ; Else Repeat
  529.           JNE     PREVCLS2                      ; If No Match, Return Zero
  530.           ADD     CX,2                          ; Adjust for Cluster Number
  531. PREVCLS2: MOV     AX,CX                         ; AX = Cluster Number
  532.           POP     DX                            ; Restore Registers
  533.           POP     CX
  534.           POP     BX
  535.           RET                                   ; Done
  536.  
  537. NEXTCLST: CMP     FATSIZE,3                     ; If FAT Size = 16 Bits,
  538.           JE      NEXTCLS1
  539.           SHL     BX,1                          ;   Simply Read Next Cluster #
  540.           MOV     BX,FATBUF[BX]
  541.           RET                                   ;   Done
  542. NEXTCLS1: PUSH    AX                            ; Save Registers
  543.           PUSH    CX
  544.           MOV     AX,BX                         ; Word # = Cluster # * 1.5
  545.           SHL     AX,1
  546.           ADD     BX,AX
  547.           SHR     BX,1
  548.           MOV     BX,FATBUF[BX]
  549.           JNC     NEXTCLS2                      ; If Odd, Use 12 MSB's
  550.           MOV     CL,4
  551.           SHR     BX,CL
  552. NEXTCLS2: AND     BX,0FFFH                      ; Else Use 12 LSB's
  553.           POP     CX                            ; Restore Registers
  554.           POP     AX
  555.           RET                                   ; Done
  556.  
  557. UNPARSE:  PUSH    CX                            ; Save Registers
  558.           PUSH    DI
  559.           PUSH    SI
  560.           MOV     CX,8                          ; FileName Length = 8 Max
  561. UNPARSE1: LODSB                                 ; Read Character
  562.           CMP     AL,' '                        ; If Space, Exit Loop
  563.           JE      UNPARSE2
  564.           STOSB                                 ; Move Character
  565.           LOOP    UNPARSE1                      ; Repeat
  566. UNPARSE2: MOV     AL,'.'                        ; Put a Dot in the String
  567.           STOSB
  568.           POP     SI                            ; Point to Extension
  569.           PUSH    SI
  570.           ADD     SI,8
  571.           MOV     CX,3                          ; Extension Length = 3 Max
  572. UNPARSE3: LODSB                                 ; Read Character
  573.           CMP     AL,' '                        ; If Space, Exit Loop
  574.           JE      UNPARSE4
  575.           STOSB                                 ; Move Character
  576.           LOOP    UNPARSE3                      ; Repeat
  577. UNPARSE4: CMP     CX,3                          ; If No Extension, Remove Dot
  578.           JNE     UNPARSE5
  579.           DEC     DI
  580. UNPARSE5: MOV     AL,0                          ; Terminate FileName
  581.           STOSB
  582.           MOV     AL,'$'
  583.           STOSB
  584.           POP     SI                            ; Restore Registers
  585.           POP     DI
  586.           POP     CX
  587.           RET                                   ; Done
  588.  
  589. MOVSTR:   LODSB                                 ; Read Source
  590.           STOSB                                 ; Write Destination
  591.           OR      AL,AL                         ; If Not EOS, Repeat
  592.           JNZ     MOVSTR
  593.           RET                                   ; Done
  594.  
  595. GET_WORD: PUSH    BX                            ; Save Registers
  596.           PUSH    DI
  597.           PUSH    SI                            ; Save Pointer
  598.           XOR     DX,DX                         ; Value = 0
  599. GET_WRD1: LODSB                                 ; Read Character
  600.           CMP     AL,'0'                        ; If Not Numeric, Done
  601.           JB      GET_WRD2
  602.           CMP     AL,'9'
  603.           JA      GET_WRD2
  604.           SUB     AL,'0'                        ; Convert to BCD
  605.           CBW
  606.           MOV     BX,AX                         ; Value = Value*10+BCD
  607.           MOV     AX,10
  608.           MUL     DX
  609.           ADD     AX,BX
  610.           MOV     DX,AX
  611.           JMP     GET_WRD1                      ; Repeat
  612. GET_WRD2: DEC     SI
  613.           POP     DI                            ; Restore Pointer
  614.           CMP     DI,SI                         ; Compare Pointer
  615.           POP     DI                            ; Restore Registers
  616.           POP     BX
  617.           RET                                   ; Done
  618.  
  619. STRIP0:   CMP     BYTE PTR [DI],'0'             ; If Character != '0', Done
  620.           JNE     STRIP1
  621.           CMP     BYTE PTR [DI+1],'0'           ; If Next Character != Digit,
  622.           JL      STRIP1                        ;   Done
  623.           CMP     BYTE PTR [DI+1],'9'
  624.           JG      STRIP1
  625.           MOV     BYTE PTR [DI],' '             ; Change '0' to ' '
  626.           INC     DI                            ; Point to Next Character
  627.           JMP     SHORT STRIP0                  ; Repeat
  628. STRIP1:   RET                                   ; Done
  629.  
  630. DEC2OUT:  PUSH    AX                            ; Save Registers
  631.           PUSH    BX
  632.           XOR     AH,AH                         ; Clear AH
  633.           MOV     BL,10                         ; AH=AX%10,AL=AX/10
  634.           DIV     BL
  635.           ADD     AX,'00'                       ; Convert to ASCII
  636.           SUB     DI,2
  637.           MOV     [DI],AX                       ; Store in String
  638.           POP     BX                            ; Restore Registers
  639.           POP     AX
  640.           RET                                   ; Done
  641.  
  642. DEC4OUT:  PUSH    AX                            ; Save Registers
  643.           PUSH    BX
  644.           MOV     BL,100                        ; AH=AX%100,AL=AX/100
  645.           DIV     BL
  646.           XCHG    AH,AL                         ; Convert 2 LSD's
  647.           CALL    DEC2OUT
  648.           XCHG    AH,AL                         ; Convert 2 MSD's
  649.           CALL    DEC2OUT
  650.           POP     BX                            ; Restore Registers
  651.           POP     AX
  652.           RET                                   ; Done
  653.  
  654. DEC5OUT:  PUSH    AX                            ; Save Registers
  655.           PUSH    BX
  656.           PUSH    DX                            ; DX=AX%10000,AX=AX/10000
  657.           MOV     BX,10000
  658.           XOR     DX,DX
  659.           DIV     BX
  660.           XCHG    DX,AX                         ; Convert 4 LSD's
  661.           CALL    DEC4OUT
  662.           XCHG    DX,AX                         ; Convert MSD
  663.           ADD     AL,'0'
  664.           SUB     DI,1
  665.           MOV     [DI],AL
  666.           POP     DX                            ; Restore Registers
  667.           POP     BX
  668.           POP     AX
  669.           RET                                   ; Done
  670.  
  671. FATBUF    LABEL   WORD
  672.  
  673. CODE      ENDS
  674.  
  675.           END     OWNER
  676.