home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol5n21.zip / DISKPREP.ASM next >
Assembly Source File  |  1987-12-13  |  32KB  |  558 lines

  1. code          segment para public 'code'
  2.               assume cs:code,ds:code,es:code
  3.               org 100h
  4. begin:        jmp prep                 ;skip data area
  5. ;
  6. copy_right    db 13,10,'Copyright 1986 Ziff-Davis Publishing Co.',13,10,'$'
  7. errmsg1       db 13,10,'Invalid Drive Specifier',13,10,'$'
  8. errmsg2       db 13,10,'Illegal Disk Format',13,10,'$'
  9. errmsg3       db 13,10,'Disk Read Error',13,10,'$'
  10. errmsg4       db 13,10,'Disk Write Error',13,10,'$'
  11. errmsg5       db 13,10,'Insufficient Space in Disk Directory',13,10,'$'
  12. errmsg6       db 13,10,'Insufficient Disk Space',13,10,'$'
  13. errmsg7       db 13,10,'Allocation Chain Error',13,10,'$'
  14. errmsg8       db 13,10,'Cannot Delete System Files',13,10,'$'
  15. errmsg9       db 13,10,'Bad Sector in System Area',13,10,'$'
  16. msg1    db 13,10,'System Prep Completed',13,10,'$'
  17. msg2    db 13,10,'System Already Installed - Delete Old System (Y/N)?',13,10,'$'
  18. msg3    db 13,10,'Execution Aborted',13,10,'$'
  19. ;
  20. last_cluster      dw 41          ;last available cluster found
  21. sec_per_cluster   dw ?           ;number of sectors per cluster
  22. clusters          dw ?           ;total number of data clusters on disk
  23. DIR_entries       dw ?           ;maximum number of directory entries
  24. DIR_sectors       dw ?           ;number of sectors used for directory
  25. FAT_sectors       dw ?           ;number of sectors used for one copy of the FAT
  26. FAT_entry         dw ?           ;temporary storage for any FAT entry
  27. drive             db ?           ;current disk drive
  28. format_table  dw 64,4,2                ;S-9 disk format parameters
  29.               dw 112,7,2               ;D-9  "    "      "
  30.               dw 64,4,1                ;S-8  "    "      "
  31.               dw 112,7,1               ;D-8  "    "      "
  32. system_id     db 'IBMBIO',32,32,'COM'  ;text of system file IBMBIO.COM
  33. ibmbio        db 'B:IBMBIO.COM',0      ;ASCIIZ string for DOS file functions
  34. ibmdos        db 'B:IBMDOS.COM',0      ; "      "      "   "   "    "
  35. cbuffer   dw offset endprog     ;pointer to buffer area for cluster transfers
  36. FAT_data  dw offset endprog + 1024 ;pointer to area where FAT image is stored
  37. DIR_data  dw offset endprog + 2048 ;pointer to area where DIR image is stored
  38. ;
  39. prep          proc near                ;start of main program
  40. ;
  41. ;Parse the command line for a drive specifier. If none, use default drive.
  42. ;
  43.               cld                      ;clear DF for string operations
  44.               mov si,80h               ;point si to start of command line
  45.               lodsb                    ;get number of characters entered
  46.               cmp al,1                 ;one or less characters specified?
  47.               jbe prep1                ;yes, then use default drive
  48.               inc si                   ;skip first delimiter
  49.               lodsb                    ;get first character (drive specifier)
  50.               and al,0DFh              ;capitalize it
  51.               sub al,'A'               ;convert ASCII to drive number
  52.               cmp al,1                 ;is drive specified either A: or B:?
  53.               jbe prep2                ;yes, then parsing is finished
  54.               lea dx,errmsg1           ;no, then specifier is illegal
  55.               jmp error_exit           ;load error message address and abort
  56. prep1:        mov ah,19h               ;DOS function 19h - get current drive
  57.               int 21h                  ;get default drive number
  58.               cmp al,1                 ;is it drive A: or B:?
  59.               jbe prep2                ;yes, then skip error routine
  60.               lea dx,errmsg1           ;no, then get message address and abort
  61. ;
  62. ;Program execution is routed here when a critical error condition is detected.
  63. ;
  64. error_exit:   mov ah,9            ;DOS function number - print string
  65.               int 21h             ;print error message
  66.               mov ah,14           ;ROM BIOS teletype routine function number
  67.               mov al,7            ;ASCII code for beep
  68.               int 10h             ;'print' the beep
  69. error1:       mov ah,4Ch          ;DOS function number - exit
  70.               mov al,1            ;set ERRORLEVEL return code to 1
  71.               int 21h             ;terminate program on error
  72. ;
  73. ; Check the format of the disk to verify that it's a 40-track diskette
  74. ; (8 or 9 sectors per track, one or two sides).
  75. ; Store information pertaining to the disk format.
  76. ;
  77. prep2:        mov drive,al             ;save current drive ID
  78.               mov dl,al                ;get drive identifier in DL
  79.               inc dl                   ;adjust drive ID for DOS function call
  80.               push ds                  ;save segment register
  81.               mov ah,1Ch               ;DOS function number-get FAT information
  82.               int 21h                  ;get pointer to FAT ID byte
  83.               mov cl,[bx]              ;store ID byte in CL
  84.               pop ds                   ;restore DS
  85.               cmp cl,0FCh              ;ID byte greater than or equal to FCh?
  86.               jae prep2a               ;yes, then format is OK
  87.               lea dx,errmsg2           ;no, then format is invalid
  88.               jmp error_exit           ;abort on error
  89. prep2a:       cbw                      ;convert byte in AL to word in AX
  90.               mov sec_per_cluster,ax   ;store number of sectors per cluster
  91.               mov clusters,dx          ;store total number of data clusters
  92.               sub cl,0FCh              ;normalize ID byte by subtracting FCh
  93.               mov al,cl
  94.               mov dl,6
  95.               mul dl                   ;multiply result by 6
  96.               mov bl,al                ;transfer table index in AL to BL
  97.               xor bh,bh                ;convert byte to word
  98.               add bx,offset format_table    ;form address of disk format
  99.                                             ;parameter line
  100.               mov ax,[bx]              ;read number of dir entries from table
  101.               mov DIR_entries,ax       ;save number of entries
  102.               mov ax,[bx+2]            ;read directory length from table
  103.               mov DIR_sectors,ax       ;save directory length
  104.               mov ax,[bx+4]            ;read FAT length from table
  105.               mov FAT_sectors,ax       ;save FAT length
  106. ;
  107. ;Read root directory and one copy of FAT into memory from the selected drive.
  108. ;
  109. prep3:        call read_FAT      ;read in one copy of the File Allocation Table
  110.               jnc prep3a         ;continue if no error on read
  111.               lea dx,errmsg3     ;exit if error occurred during read
  112.               jmp error_exit
  113. prep3a:       call read_DIR      ;read in the disk directory
  114.               jnc prep4          ;continue if no error
  115.               lea dx,errmsg3     ;otherwise abort
  116.               jmp error_exit
  117. ;
  118. ;Determine if the disk is already system formatted by seeing if the first
  119. ;file in the directory is IBMBIO.COM.
  120. ;
  121. prep4:        lea si,system_id         ;point SI to 'IBMBIO.COM' text
  122.               mov di,DIR_data          ;point DI to first filename
  123.               mov cx,11                ;11 bytes to check
  124.               repe cmpsb               ;compare the two strings
  125.               jne prep6                ;skip delete routine if no system
  126. ;
  127. ;Disk already system formatted--see if user wants to delete the system files.
  128. ;
  129.               lea dx,msg2              ;get query message address
  130.               mov ah,9                 ;DOS function number - print string
  131.               int 21h                  ;print 'Delete System?' message
  132. prep5:        mov ah,0                 ;ROM BIOS function number - get keypress
  133.               int 16h                  ;get user response from keyboard
  134.               and al,0DFh              ;capitalize entry
  135.               cmp al,'Y'               ;was 'Y' pressed?
  136.               je prep5a                ;yes - delete system files
  137.               cmp al,'N'               ;was 'N' pressed?
  138.               jne prep5                ;no, then get another keypress
  139.               lea dx,msg3              ;get abort message address
  140.               mov ah,9                 ;print 'Execution Aborted' message
  141.               int 21h
  142.               jmp error1               ;exit with ERRORLEVEL set to 1
  143. ;
  144. ;Delete system files - change file attributes to 0 (eliminating read-only bit)
  145. ;before using DOS delete function.
  146. ;
  147. prep5a:       cmp drive,1        ;is B: the current drive?
  148.               je prep5b          ;yes, then continue
  149.               dec ibmbio         ;no, set ASCIIZ drive designators to A:
  150.               dec ibmdos
  151. prep5b:       lea dx,ibmbio      ;change IBMBIO.COM file attribute for deletion
  152.               mov ah,43h         ;DOS function number - change attribute
  153.               mov cx,0           ;new file attribute
  154.               mov al,1           ;specify that attribute is to be changed
  155.               int 21h            ;zero IBMBIO.COM file attribute
  156.               jc prep5c          ;exit on error if unsuccessful
  157.               lea dx,ibmdos      ;do the same for IBMDOS.COM
  158.               mov ah,43h
  159.               mov cx,0
  160.               mov al,1
  161.               int 21h
  162.               jc prep5c
  163.               lea dx,ibmbio      ;now delete IBMBIO.COM
  164.               mov ah,41h         ;DOS function number - delete file
  165.               int 21h            ;delete the file
  166.               jc prep5c          ;exit on error if unsuccessful
  167.               lea dx,ibmdos      ;do the same for IBMDOS.COM
  168.               mov ah,41h
  169.               int 21h
  170.               jc prep5c
  171.               jmp prep3          ;reread FAT and directory
  172. prep5c:       lea dx,errmsg8     ;files cannot be deleted - abort
  173.               jmp error_exit
  174. ;
  175. ;Check that the disk has adequate free space before continuing.
  176. ;
  177. prep6:        mov dl,drive             ;get drive in DL
  178.               inc dl                   ;adjust drive ID for DOS function call
  179.               mov ah,36h               ;DOS function number - get free space
  180.               int 21h                  ;get number of clusters that are free
  181.               mov ax,sec_per_cluster   ;get sectors per cluster
  182.               mul bx                   ;multiply to get free sectors
  183.               cmp ax,100               ;at least 100 sectors (50K) free?
  184.               jae prep7                ;yes, then continue
  185.               lea dx,errmsg6           ;no, then load error message address
  186.               jmp error_exit           ;exit
  187. ;
  188. ;Check first two directory entries to see whether each is used or available.
  189. ;For each one not available, transfer it to the first available space.
  190. ;
  191. prep7:        mov si,DIR_data          ;point SI to directory image
  192.               cmp byte ptr [si],0      ;is the first entry available?
  193.               je prep9                 ;yes, then goto next entry
  194.               cmp byte ptr [si],0E5h   ;erased file?
  195.               jne prep7a               ;no, then move it
  196.               mov byte ptr [si],0      ;mark entry as 'Never Used'
  197.               jmp prep9                ;jump to next entry
  198. prep7a:       mov dx,2                 ;entry is occupied
  199.               call find_entry          ;find first available directory entry
  200.               jnc prep8                ;entry found - continue
  201.               lea dx,errmsg5   ;no space in dir - load error message address
  202.               jmp error_exit           ;abort
  203. prep8:        mov ax,0
  204.               call move_entry          ;copy entry 0 into first available slot
  205. prep9:        mov si,DIR_data          ;check second entry for availability
  206.               add si,32                ;point SI to second entry
  207.               cmp byte ptr [si],0      ;first byte zero?
  208.               je prep13                ;yes, then it's available
  209.               cmp byte ptr [si],0E5h   ;erased file?
  210.               jne prep9a               ;no, then move it
  211.               mov byte ptr [si],0      ;mark entry as 'Never Used'
  212.               jmp prep13               ;continue
  213. prep9a:       mov dx,2                 ;not available
  214.               call find_entry          ;find first available entry
  215.               jnc prep10               ;continue if empty slot found
  216.               lea dx,errmsg5           ;abort if not
  217.               jmp error_exit
  218. prep10:       mov ax,1
  219.               call move_entry          ;copy entry and mark old one available
  220. ;
  221. ;Copy each of the first forty clusters currently in use to clusters beyond the
  222. ;first forty and adjust the corresponding FAT entries accordingly.
  223. ;
  224. prep13:       mov cx,40                ;check 40 clusters
  225.               mov dx,2                 ;start checking at cluster 2
  226. prep14:       push cx                  ;save loop counter
  227.               call get_FAT_entry       ;get FAT entry for current cluster
  228.               cmp ax,0                 ;is it available?
  229.               je prep17                ;yes, then proceed to next cluster
  230.               cmp ax,0FF0h             ;is FAT entry less than FF0h?
  231.               jb prep14a               ;yes, then move cluster
  232.               cmp ax,0FF7h             ;is it greater than FF7h?
  233.               ja prep14a               ;yes, then move cluster
  234.               pop cx                   ;bad cluster - clean up stack
  235.               lea dx,errmsg9           ;load error message address
  236.               jmp error_exit           ;abort
  237. prep14a:      mov FAT_entry,ax         ;save FAT entry for later
  238.               mov ax,last_cluster      ;get number of last available cluster
  239.               inc ax              ;increment to the next one to begin search
  240.               mov bx,0
  241.               call find_cluster   ;find first cluster with FAT entry of zero
  242.               mov last_cluster,ax      ;store cluster number just found
  243.               call move_cluster        ;copy the old cluster into the new
  244.               jnc prep15               ;continue if no error in disk I/O
  245.               pop cx                   ;on error, clean up stack and exit
  246.               jmp error_exit
  247. prep15:       mov ax,FAT_entry    ;retrieve the FAT entry for the old cluster
  248.               push dx                  ;save the old cluster number
  249.               mov dx,last_cluster      ;target the new cluster
  250.               call put_FAT_entry       ;put the old FAT entry into the new one
  251.               pop dx                   ;restore old cluster number
  252.               mov ax,0                 ;mark the old cluster available...
  253.               call put_FAT_entry       ;...by setting its FAT entry to zero
  254.               mov bx,dx                ;get old cluster number in BX for search
  255.               mov ax,2                 ;start search at cluster 2
  256.               call find_cluster   ;find FAT entry that referenced old cluster
  257.               jnc prep16               ;if found, then continue
  258.               call search_DIR          ;if not, then look in the directory
  259.               jnc prep15a              ;if found, then continue
  260.               pop cx                   ;clean up stack
  261.               lea dx,errmsg7      ;error - lost cluster or subdir encountered
  262.               jmp error_exit           ;abort on error
  263. prep15a:      mov ax,last_cluster      ;get new cluster number
  264.               mov [bx],ax         ;replace the starting cluster directory entry
  265.               jmp prep17               ;skip forward
  266. prep16:       push dx                  ;save current cluster number
  267.               mov dx,ax           ;change FAT entry that formerly referenced
  268.               mov ax,last_cluster      ;the old cluster to reference new one
  269.               call put_FAT_entry
  270.               pop dx                   ;restore current cluster number
  271. prep17:       pop cx                   ;restore count of clusters checked
  272.               inc dx                   ;index to next sequential cluster
  273.               loop prep14              ;loop until the first 40 are clear
  274. ;
  275. ;Write two copies of the File Allocation Table and one copy of the disk
  276. ;directory back to disk, then exit.
  277. ;
  278. prep17a:      call write_FAT           ;write two copies of the FAT
  279.               jnc prep18               ;continue if no error on write
  280.               lea dx,errmsg4           ;abort on error
  281.               jmp error_exit
  282. prep18:       call write_DIR           ;write the directory to disk
  283.               jnc prep19               ;check error status
  284.               lea dx,errmsg4           ;abort on write error
  285.               jmp error_exit
  286. prep19:       lea dx,msg1         ;message address for successful completion
  287.               mov ah,9                 ;DOS display string function
  288.               int 21h                  ;print message
  289.               mov ah,4Ch               ;DOS function number - exit
  290.               mov al,0                 ;set ERRORLEVEL return code to 0
  291.               int 21h                  ;exit program
  292. prep          endp
  293. ;
  294. ;-----------------------------------------------------------------------------
  295. ;GET_FAT_ENTRY routine returns the FAT entry for the indicated cluster.
  296. ;Entry:  DX - cluster number (2-XXX)   | Exit:  AX - FAT entry
  297. ;-----------------------------------------------------------------------------
  298. get_FAT_entry proc near
  299.               mov ax,3                 ;multiply cluster number by 3
  300.               push dx                  ;save cluster number
  301.               mul dx                   ;multiply
  302.               pop dx                   ;restore cluster number
  303.               shr ax,1                 ;divide by 2 to obtain offset into FAT
  304.               mov bx,ax                ;transfer result to bx
  305.               add bx,FAT_data          ;make address relative to code segment
  306.               mov ax,[bx]              ;get word at calculated address
  307.               test dx,1                ;is cluster number odd or even?
  308.               je getf1                 ;even, then jump
  309.               mov cl,4            ;number is odd, so keep upper 12 bits of word
  310.               shr ax,cl           ;by shifting right 4 bits
  311.               ret                      ;done - entry in AX
  312. getf1:        and ax,0FFFh             ;even number, then mask off upper 4 bits
  313.               ret                      ;done - entry in AX
  314. get_FAT_entry endp
  315. ;
  316. ;------------------------------------------------------------------------------
  317. ;PUT_FAT_ENTRY places the designated number into the FAT entry for the named
  318. ;cluster.  Entry:  DX - cluster number (2-XXX)
  319. ;                  AX - entry
  320. ;------------------------------------------------------------------------------
  321. put_FAT_entry proc near
  322.               push ax                  ;save new FAT entry
  323.               push dx                  ;save cluster number
  324.               mov ax,3                 ;multiply cluster by 3
  325.               mul dx
  326.               pop dx                   ;restore cluster number
  327.               shr ax,1                 ;divide by 2
  328.               mov bx,ax                ;transfer to BX
  329.               add bx,FAT_data          ;complete offset address of FAT entry
  330.               pop ax                   ;restore FAT entry
  331.               test dx,1                ;is the cluster odd or even?
  332.               je putf1                 ;even, then jump forward
  333.               mov cl,4                 ;odd - shift entry 4 bits left
  334.               shl ax,cl
  335.               and word ptr [bx],0Fh    ;zero upper 12 bits of word
  336.               or [bx],ax               ;install new FAT entry
  337.               ret                      ;done - exit
  338. putf1:        and [bx],0F000h          ;even - zero lower 12 bits
  339.               or [bx],ax               ;place entry in lower 12 bits
  340.               ret                      ;done - exit
  341. put_FAT_entry endp
  342. ;
  343. ;------------------------------------------------------------------------------
  344. ;The following four routines write and read complete copies of the FAT and the
  345. ;disk directory to and from the selected drive.
  346. ;------------------------------------------------------------------------------
  347. read_FAT      proc near                ;read one copy of the FAT into memory
  348.               mov al,drive             ;define drive
  349.               mov dx,1                 ;start at sector 1
  350.               mov cx,FAT_sectors       ;set number of sectors
  351.               mov bx,FAT_data          ;define buffer address
  352.               int 25h                  ;DOS absolute sector read
  353.               pop dx                   ;clean flags off stack
  354.               ret
  355. read_FAT      endp
  356. ;
  357. read_DIR      proc near                ;read one copy of directory into memory
  358.               mov al,drive             ;define drive
  359.               mov dx,FAT_sectors       ;get number of sectors per FAT
  360.               shl dx,1                 ;double it for two copies of the FAT
  361.               inc dx                   ;directory starts in next sector
  362.               mov cx,DIR_sectors       ;number of sectors to read
  363.               mov bx,DIR_data          ;address of storage buffer
  364.               int 25h                  ;read sectors
  365.               pop dx                   ;clean up the stack before exit
  366.               ret
  367. read_DIR      endp
  368. ;
  369. write_FAT     proc near                ;write two copies of the FAT to disk
  370.               mov al,drive             ;define drive
  371.               mov dx,1                 ;begin at sector 1
  372.               mov cx,FAT_sectors       ;get number of sectors per FAT
  373.               mov bx,FAT_data          ;define buffer address
  374.               int 26h                  ;DOS absolute sector write
  375.               pop dx                   ;clean up stack
  376.               jc wfat1                 ;exit on write error
  377.               mov al,drive             ;repeat process for second copy of FAT
  378.               mov dx,1
  379.               mov cx,FAT_sectors
  380.               add dx,cx                ;start second FAT after first one on disk
  381.               mov bx,FAT_data
  382.               int 26h
  383.               pop dx
  384. wfat1:        ret
  385. write_FAT     endp
  386. ;
  387. write_DIR     proc near           ;write disk directory image in memory to disk
  388.               mov al,drive             ;define drive
  389.               mov dx,FAT_sectors       ;get number of sectors per FAT
  390.               shl dx,1                 ;double it for two copies
  391.               inc dx                   ;directory starts in next sector
  392.               mov cx,DIR_sectors       ;number of sectors to read
  393.               mov bx,DIR_data          ;address of data to be written
  394.               int 26h                  ;write sectors
  395.               pop dx                   ;clean up stack
  396.               ret
  397. write_DIR     endp
  398. ;
  399. ;------------------------------------------------------------------------------
  400. ;FIND_ENTRY searches thru the image of the disk directory stored in memory and
  401. ;finds the first available directory entry.
  402. ;Entry:  DX - starting entry (0-XXX)   | Exit:  DX - first available entry
  403. ;                                      |        CF - clear: avail. entry found
  404. ;                                      |             set:   not found
  405. ;------------------------------------------------------------------------------
  406. find_entry    proc near
  407.               mov cx,DIR_entries       ;set maximum number of tries in CX
  408.               sub cx,dx
  409.               push cx                  ;save count value
  410.               mov bx,dx                ;get starting entry number in BX
  411.               mov cl,5                 ;multiply BX by 32
  412.               shl bx,cl
  413.               add bx,DIR_data          ;complete offset address
  414.               pop cx                   ;restore loop counter
  415. findent1:     cmp byte ptr [bx],0      ;is the first byte zero?
  416.               je findent2              ;yes, then it's available
  417.               cmp byte ptr [bx],0E5h   ;is it an erased file?
  418.               je findent2              ;yes, then it's available
  419.               inc dx                   ;not available - check next entry
  420.               add bx,32                ;address of next entry
  421.               loop findent1            ;loop back if some remain
  422.               stc                      ;none available - set CF
  423.               ret
  424. findent2:     clc                      ;clear CF to indicate entry found
  425.               ret
  426. find_entry    endp
  427. ;
  428. ;------------------------------------------------------------------------------
  429. ;MOVE_ENTRY routine transfers a directory entry from one space to another and
  430. ;sets the old entry to indicate that it's available.
  431. ;Entry:  AX - source entry (0-XXX)
  432. ;        DX - target entry (0-XXX)
  433. ;------------------------------------------------------------------------------
  434. move_entry    proc near
  435.               mov si,ax           ;convert entry number to offset address in SI
  436.               mov cl,5
  437.               shl si,cl
  438.               add si,DIR_data
  439.               mov di,dx                ;do the same for DI
  440.               mov cl,5
  441.               shl di,cl
  442.               add di,DIR_data
  443.               push si                  ;save address of old entry for later
  444.               mov cx,32                ;32 bytes per entry
  445.               rep movsb                ;move all 32 bytes
  446.               pop si                   ;get address of old entry
  447.               mov byte ptr [si],0      ;mark entry as 'Never Used'
  448.               ret
  449. move_entry    endp
  450. ;
  451. ;------------------------------------------------------------------------------
  452. ;FIND_CLUSTER routine finds the first cluster whose FAT entry matches the number
  453. ;specified in BX.
  454. ;Entry:  AX - starting cluster (2-XXX) | Exit:  AX - first cluster found
  455. ;        BX - FAT entry                |        CF - clear: cluster found
  456. ;                                      |             set:   not found
  457. ;------------------------------------------------------------------------------
  458. find_cluster  proc near
  459.               mov cx,clusters          ;get number of clusters
  460.               add cx,2                 ;calculate max number of search loops
  461.               sub cx,ax
  462.               push dx                  ;save DX
  463.               mov dx,ax                ;starting cluster in DX
  464. findcls1:     push cx                  ;save count of clusters checked
  465.               push bx                  ;save FAT entry value
  466.               call get_FAT_entry       ;get FAT entry for designated cluster
  467.               pop bx                   ;restore FAT entry to BX
  468.               pop cx                   ;restore count
  469.               cmp ax,bx                ;is it what we're searching for?
  470.               je findcls2              ;yes, then terminate search
  471.               inc dx                   ;no, then try next cluster
  472.               loop findcls1
  473.               pop dx                   ;restore DX
  474.               stc                      ;set CF to indicate cluster not found
  475.               ret                      ;exit
  476. findcls2:     mov ax,dx                ;put cluster number in AX
  477.               pop dx                   ;restore DX
  478.               clc                      ;clear CF to indicate success
  479.               ret                      ;exit
  480. find_cluster  endp
  481. ;
  482. ;------------------------------------------------------------------------------
  483. ;CLS2SEC routine returns the sector number that corresponds to the cluster
  484. ;number input. Entry:  DX - cluster number (2-XXX)  | Exit:  DX - sector number
  485. ;------------------------------------------------------------------------------
  486. cls2sec       proc near
  487.               sub dx,2                 ;subtract two from the cluster number
  488.               mov ax,sec_per_cluster   ;get number of sectors in each cluster
  489.               mul dx                   ;multiply DX by sectors per cluster
  490.               mov dx,ax                ;get result in DX
  491.               mov ax,FAT_sectors       ;get number of sectors in FAT
  492.               shl ax,1                 ;double it for two copies of the FAT
  493.               add dx,ax                ;add FAT sectors
  494.               add dx,DIR_sectors       ;add directory sectors
  495.               inc dx                   ;data starts in next sector
  496.               ret
  497. cls2sec       endp
  498. ;
  499. ;------------------------------------------------------------------------------
  500. ;MOVE_CLUSTER routine copies the contents of the source cluster into the 
  501. ;target cluster.
  502. ;Entry:  DX - source cluster (2-XXX)   | Exit:  CF - clear: no error in disk I/O
  503. ;        AX - target cluster (2-XXX)   |             set:   I/O error
  504. ;------------------------------------------------------------------------------
  505. move_cluster  proc near
  506.               push dx                  ;save source cluster number
  507.               push ax                  ;save target cluster number
  508.               call cls2sec             ;get sector number of source cluster
  509.               mov cx,sec_per_cluster   ;number of sectors to read
  510.               mov al,drive             ;specify drive
  511.               mov bx,cbuffer           ;set data transfer area
  512.               int 25h                  ;DOS sector read
  513.               pop ax                   ;clean up stack
  514.               pop dx                   ;target cluster in DX
  515.               jc movec1                ;exit on error
  516.               call cls2sec             ;get sector number of target cluster
  517.               mov cx,sec_per_cluster   ;number of sectors to read
  518.               mov al,drive             ;specify drive
  519.               mov bx,cbuffer           ;data transfer area
  520.               int 26h                  ;DOS sector write
  521.               pop ax                   ;clean up stack
  522.               pop dx                   ;restore source cluster
  523.               jc movec2                ;abort on error
  524.               ret                      ;exit after successful transfer
  525. movec1:       pop dx                   ;clean up stack before exit
  526.               lea dx,errmsg3        ;exit with pointer to 'Read Error' message
  527.               ret
  528. movec2:       lea dx,errmsg4           ;exit with 'Write Error' message address
  529.               ret
  530. move_cluster  endp
  531. ;
  532. ;------------------------------------------------------------------------------
  533. ;SEARCH_DIR routine searches each entry in the disk directory image for a
  534. ;starting;cluster entry that matches the one input in DX.
  535. ;Entry: DX - cluster number (2-XXX) | Exit: BX - addr of starting cluster word
  536. ;                                   |        CF - clear: match found
  537. ;                                   |             set:   not found
  538. ;------------------------------------------------------------------------------
  539. search_DIR    proc near
  540.               mov bx,DIR_data          ;get starting address of directory image
  541.               add bx,90          ;starting cluster offset - 3rd directory entry
  542.               mov cx,DIR_entries       ;get maximum number of search loops
  543.               sub cx,2                 ;skip first two entries
  544. sdir1:        cmp [bx],dx              ;do the words match for this entry?
  545.               je sdir2                 ;yes, then clear CF and exit
  546.               add bx,32                ;no, then adjust BX for next entry
  547.               loop sdir1               ;try next entry
  548.               stc                      ;no match found - set CF and exit
  549.               ret
  550. sdir2:        clc                      ;match found - clear CF
  551.               ret
  552. search_DIR    endp
  553. ;
  554. endprog       label byte               ;end of program - start of buffer area
  555. ;
  556. code          ends
  557.               end begin
  558.