home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / asm_programming / AS02.ZIP / SCAV30.ASM < prev    next >
Assembly Source File  |  1985-08-28  |  14KB  |  553 lines

  1.  
  2. title scavenge Copyright (c) T. Jennings 1983
  3. ;
  4. ;****************************************
  5. ;*                    *
  6. ;*        SCAVENGE        *
  7. ;*                    *
  8. ;*    Mark bad blocks on MSDOS     *
  9. ;*    as allocated in the FAT.    *
  10. ;*                    *
  11. ;*    T. Jennings 5 June 82        *
  12. ;*      created 15 Sept. 82        *
  13. ;*    Modified 14 December 1984    *
  14. ;*        by David Gwillim        *
  15. ;*                    *
  16. ;*                    *
  17. ;****************************************
  18. ;
  19. ;***********************************************************************
  20. ;**                                                                   **
  21. ;**  SCAV2XX was modified by David Gwillim to dynamically allocate    **
  22. ;**  memory to the variables BLKBUF and FATBUF when the program       **
  23. ;**  is started - this drastically reduced the size of the .COM file  **
  24. ;**  from 17K on disk to just over 1K, while still allowing the       **
  25. ;**  checking of disks with block sizes up to 16K Bytes. Also         **
  26. ;**  changed was the access to disk to determine its statistics       **
  27. ;**  (Number of Blocks, Blocksize etc) this is now done AFTER the     **
  28. ;**  pause command when the program is first started, permitting      **
  29. ;**  the program to be run with a single floppy drive. Code was       **
  30. ;**  also added to display the block size of the disk in bytes        **
  31. ;**  as part of the statistics, plus some alert tones for various     **
  32. ;**  parts of the program.                                            **
  33. ;**                                                                   **
  34. ;**  I also added a more graceful exit than via ^C or Cntrl-Break     **
  35. ;**  as this would often leave you on the wrong drive if you aborted  **
  36. ;**  mid way through the block check and also would not give you the  **
  37. ;**  chance to update the FAT with any bad blocks found so far.       **
  38. ;**                                                                   **
  39. ;**  A logical improvement to the program would be to add to the      **
  40. ;**  code so the program could report the names of the files which    **
  41. ;**  contain any bad blocks found, so the user could handle those     **
  42. ;**  files, or at least be aware that the data in them was corrupted. **
  43. ;**                                                                   **
  44. ;**  This is a very useful program and can give you great peace of    **
  45. ;**  mind if you own a hard disk and want to be sure that all is OK.  **
  46. ;**  If anyone takes a crack at doing the improvements I mentioned    **
  47. ;**  or finds and fixes any bugs, I would be delighted to hear of     **
  48. ;**  them.                                                            **
  49. ;**                                                                   **
  50. ;**                     David Gwillim                                 **
  51. ;**                     1414 N. Catalina Street                       **
  52. ;**                     Los Angeles CA 90027                          **
  53. ;**                                                                   **
  54. ;************************************************************************
  55. ;
  56. ;Reads all sectors in logical MSDOS blocks
  57. ;and marks the file allocation tables such
  58. ;that the blocks are permanently allocated
  59. ;where CHKDSK will not deallocate them.
  60. ;
  61. ;
  62. ;This version works on any 2.xx MSDOS or
  63. ;PCDOS, on any media type, fixed or removable.
  64. ;One (major) limitation: it will not map out
  65. ;blocks that are already allocated to a file;
  66. ;it will say "block used", but won't tell you
  67. ;which file it is in.
  68. ;
  69. ;If SCAVENGE finds any bad blocks, it will ask
  70. ;you whether or not you want the disk updated.
  71. ;You can safely run it just to see if the disk 
  72. ;is OK.
  73. ;
  74. ;MASM, LINK, then EXE2BIN this to make a COM
  75. ;file. It will not run as an EXE file. NOTE:
  76. ;LINK will give you a 'Warning: no STACK 
  77. ;segment' error: ignore it.
  78. ;
  79. cr    equ    0dh
  80. lf    equ    0ah
  81.  
  82. ;Beep procedure count values
  83. ;---------------------------
  84. ;To generate a given freqency note out of the speaker with the Beep procedure
  85. ;on the PC using Channel 2 of the 8253 timer, the channel 2 count register
  86. ;must be loaded with a value such that the 8253 input clock frequency
  87. ;(1.19318 MHz) divided by the count figure equals the audio frequency.
  88.  
  89. f176Hz    equ    6779    ; 176 Hz count value
  90. f352Hz    equ    3390    ; 352 Hz count value
  91. f704Hz    equ    1695    ; 704 Hz count value
  92. f1408Hz    equ    847    ; 1408 Hz count value
  93.  
  94. page
  95. cgroup group code
  96. code segment byte public 'code'
  97. assume cs:cgroup,ds:cgroup,ss:cgroup
  98. ;
  99. ;MSDOS page 0 stuff.
  100. ;
  101.     org    5ch
  102. tfcb label byte
  103.  
  104.     org    80h
  105. tbuff label byte
  106.  
  107.     org    100h
  108. scavenge:
  109.     jmp    start
  110. ;
  111. ;Disk parameters:
  112. ;
  113. blkcnt    dw    (?)    ;blocks this disk
  114. blksize    dw    (?)    ;sectors per block
  115. secsize    dw    (?)    ;phys. sector size
  116. badcnt    dw    (?)    ;# bad blocks found
  117. newbad    dw    (?)    ;new bad ones
  118. block    dw    (?)    ;current block
  119. sector    dw    (?)    ;sector to read
  120. disk    db    (?)    ;selected disk
  121. curdsk    db    (?)    ;current disk.
  122. fatsec    dw    (?)    ;1st FAT sector,
  123. fatcnt    dw    (?)    ;FAT sec count.
  124.  
  125.     dw 128 dup (?)
  126. stack    dw    (?)    ;what else
  127. page
  128. ;
  129. ;Say who we are, describe the disk we are
  130. ;about to fix, ask to continue or abort.
  131. ;
  132. start:    mov    ax,cs
  133.     mov    ds,ax
  134.     cli            ;Disable interrupts while we move stack
  135.     mov    ss,ax
  136.     mov    sp,offset stack
  137.     sti            ;Re-enable interrupts
  138.     mov    dx,offset signon
  139.     call    putstr
  140.  
  141.     mov    bx,f176Hz    ;Alert user audibly
  142.     call    beep
  143.     mov    bx,f704Hz
  144.     call    beep
  145.     mov    bx,f352Hz
  146.     call    beep
  147.     mov    bx,f1408Hz
  148.     call    beep
  149.  
  150.     call    ina
  151.     or    al,20h        ;Make character lower case
  152.     cmp    al,'q'        ;Quit?
  153.     jne    st0
  154.     mov    dx,offset abort
  155.     call    putstr
  156.     int    20h
  157.  
  158. st0:    call    setup        ;get disk stuff
  159.     jnc    st1
  160.  
  161.     call    putstr
  162.     int    20h    ;error.
  163.  
  164. st1:    call    liststat    ;describe dsk
  165. ;
  166. ;Find all the bad blocks, if any, display them,
  167. ;ask if we should update the FAT. If so, write
  168. ;it out.
  169. ;
  170.     mov    dx,offset crlf
  171.     call    putstr
  172.     call    findbad        ;map bad,
  173.     call    listbad        ;list them,
  174.     cmp    newbad,0    ;if new bad
  175.     je    st2        ;blocks...
  176.  
  177.     mov    dx,offset updstr ;ask if we
  178.     call    putstr        ;should update
  179.     call    ina
  180.     and    al,5fh
  181.     cmp    al,'Y'
  182.     jne    st1A
  183.     mov    al,disk        ;write out the
  184.     mov    dx,fatsec    ;FAT,
  185.     mov    cx,fatcnt
  186.     mov    bx,offset fatbuf
  187.     int    26h
  188.     pop    ax        ;pop flags
  189.     mov    dx,offset update
  190.     call    putstr
  191.     jmp    st2
  192. st1A:    mov    dx,offset noupdte
  193.     call    putstr
  194. st2:    mov    al,curdsk    ;reselect the
  195.     call    seldsk        ;original disk
  196.     int    20h
  197.  
  198. signon    db    cr,lf,9,'*********************************************'
  199.     db    cr,lf,9,'* DOS 2.xx Bad Sector Mapper - Version 3.00 *'
  200.     db    cr,lf,9,'* Updated by David Gwillim 18 December 1984 *'
  201.     db    cr,lf,9,'* Original program by T. Jennings 5 June 83 *'
  202.     db    cr,lf,9,'*********************************************'
  203.     db    cr,lf,lf
  204.     db    'Type Q to abort at any time, any other key to continue ...'
  205.     db    cr,lf,'$'
  206. updstr    db    cr,lf,lf,'Want the disk updated? [y,n] $'
  207. noupdte    db    cr,lf,lf,'FAT not updated',cr,lf,'$'
  208. update    db    cr,lf,lf,'FAT updated',cr,lf,'$'
  209. crlf    db    cr,lf,'$'
  210. page
  211. ;
  212. ;Get the data on the specified disk. Return 
  213. ;carry if no drive specified. Returns ES:DI
  214. ;pointing to the FAT for the selected drive.
  215. ;
  216. setup:    call    initdsk        ;reset dsk sys,
  217.     call    getdsk        ;get current,
  218.     mov    curdsk,al    ;save it,
  219.     mov    al,tfcb        ;make sure a
  220.     cmp    al,0        ;new one spec'd
  221.     stc            ;quit if none,
  222.     mov    dx,offset strstr
  223.     jz    gd1
  224.     dec    al        ;make 0-N,
  225.     mov    disk,al
  226.     call    seldsk        ;select,
  227.  
  228.     push    ds        ;save local DS,
  229.     mov    ah,1bh
  230.     int    21h
  231.     pop    ds
  232.     mov    blkcnt,dx    ;save # blocks,
  233.     mov    secsize,cx    ;sector size,
  234.     mov    ah,0
  235.     mov    blksize,ax    ;secs/block.
  236.  
  237.     push    ds        ;now get the
  238.     mov    dl,disk
  239.     inc    dl        ;drive 1=A, b=2
  240.     mov    ah,32h        ;FAT,
  241.     int    21h        ;get the DPB,
  242.  
  243.     mov    cx,[bx+15]    ;CX= sec count,
  244.     mov    ch,0
  245.     mov    dx,[bx+6]    ;DX= 1st sec,
  246.     pop    ds
  247.     mov    fatcnt,cx    ;save both,
  248.     mov    fatsec,dx
  249.  
  250.     mov    al,disk        ;AL= drive #,
  251.     mov    bx,offset fatbuf ;DS:BX= buffer
  252.     int    25h        ;read the FAT,
  253.     pop    ax        ;pop flags
  254.     mov    dx,offset bscstr
  255. gd1:    ret
  256. strstr    db    cr,lf,'Must specify a disk drive.$'
  257. bscstr    db    cr,lf,'Bad FAT sector: disk not useable.$'
  258.  
  259. page
  260. ;
  261. ;Read the entire disk looking for bad blocks.
  262. ;When one is found, go mark it as an allocated
  263. ;bad block.
  264. ;
  265. findbad:
  266.     mov    block,0        ;1st block,
  267.     mov    badcnt,0    ;none yet,
  268.  
  269. fb1:    call    kbdchk        ;QUIT character input from the keyboard?
  270.     jnc    fb1A
  271.     mov    dx,offset abort
  272.     call    putstr
  273.     ret
  274.  
  275. fb1A:    mov    dx,offset blkstr ;type 'block '
  276.     call    putstr
  277.     mov    bx,block    ;block number,
  278.     call    outdec
  279.     call    readblk        ;read a block,
  280.     jnc    fb3        ;if bad, 
  281.     inc    badcnt        ;count it,
  282.     mov    dx,offset badstr
  283.     call    putstr        ;type 'bad'
  284.     call    mapout        ;mark bad,
  285.     mov    dx,offset cntstr ;error if cant
  286.     jc    fb2
  287.     add    newbad,cx    ;count it,
  288.     mov    dx,offset alrstr
  289.     jcxz    fb2        ;already marked
  290.     mov    dx,offset mrkstr
  291.  
  292.     mov    bx,f704Hz    ;Warn user audibly
  293.     call    beep
  294.     mov    bx,f176Hz
  295.     call    beep
  296.  
  297. fb2:    call    putstr
  298.  
  299.     mov    bx,f1408Hz    ;Warn user audibly
  300.     call    beep
  301.     mov    bx,f176Hz
  302.     call    beep
  303.  
  304. fb3:    inc    block        ;next block,
  305.     dec    blkcnt        ;another...
  306.     jnz    fb1        ;keep looking.
  307.     ret
  308.  
  309.  
  310. blkstr    db    cr,'Block $'
  311. badstr    db    ' bad,$'
  312. alrstr    db    ' already marked.',cr,lf,'$'
  313. mrkstr    db    ' mapped out.',lf,'$'
  314. cntstr    db    ' already used! I dont know which file.',lf,'$'
  315. abort    db    ' ... Aborting program',cr,lf,lf,'$'
  316.  
  317. page
  318. ;
  319. ;Mark the current block as bad in the FAT.
  320. ;Multiply the block number by 1.5 to find the
  321. ;block number, (actually *3, /2) and if not
  322. ;used, mark it bad. If used, report which file
  323. ;it's in. If it's already mapped as bad, 
  324. ;return CX=0, else return CX=1.
  325. ;
  326. mapout:
  327.     mov    bx,block    ;block,
  328.     shl    bx,1        ;first times 2,
  329.     add    bx,block    ;then add one to make times 3,
  330.     shr    bx,1        ;now divide by 2,
  331.     mov    ax,word ptr fatbuf[bx]    ;get word,
  332. ;
  333. ;If carry is set, we want the high 12 bits in
  334. ;the word in AX, else the low 12 bits. Set CH
  335. ;as the shift count, DX as the mask.
  336. ;
  337.     mov    ch,0        ;assume low,
  338.     mov    dx,0fffh
  339.     jnc    mo1
  340.     mov    ch,4        ;else high 12,
  341.     mov    dx,0fff0h
  342. mo1:    and    ax,dx        ;mask it,
  343.     mov    cl,ch
  344.     shr    ax,cl        ;shift it,
  345. ;
  346. ;AX is the block number; if it's anything
  347. ;but 000 or ff7, return with carry set,
  348. ;indicating that it's already used.
  349. ;
  350.     cmp    ax,0ff7h    ;if ff7,
  351.     je    mo2        ;already marked
  352.     cmp    ax,0        ;if allocated,
  353.     je    mo3
  354.     stc            ;error!
  355. mo2:    mov    cx,0        ;none mapped,
  356.     ret
  357. ;
  358. ;Bad unused block. Mark as bad in the FAT.
  359. ;
  360. mo3:    mov    ax,0ff7h    ;marker,
  361.     mov    cl,ch
  362.     shl    ax,cl        ;shift it,
  363.     or    word ptr fatbuf[bx],ax    ;mark it.
  364.     mov    cx,1        ;1 mapped,
  365.     ret
  366. page
  367. ;
  368. ;Read one block, return carry set if read
  369. ;error. Leave the useless data in the buffer
  370. ;following the end of this program.
  371. ;
  372. readblk:
  373.     mov    ax,block    ;find start
  374.     mov    cx,blksize    ;sector,
  375.     mul    cx        ;CX= count,
  376.     mov    dx,ax        ;DX= sector,
  377.     mov    al,disk
  378.     mov    bx,offset blkbuf    ;our buffer,
  379.     int    25h        ;read sectors,
  380.     pop    dx        ;pop flags,
  381.     ret
  382. page
  383. ;
  384. ;List the general info on the disk, like
  385. ;number of blocks, block size, FAT size & location, etc.
  386. ;
  387. liststat:
  388.     mov    dx,offset st1str
  389.     call    putstr
  390.     mov    al,disk
  391.     add    al,'A'
  392.     call    outa
  393.     mov    dx,offset st2str
  394.     call    putstr
  395.     mov    bx,blkcnt
  396.     call    outdec
  397.     mov    dx,offset st3str
  398.     call    putstr
  399.     mov    ax,512
  400.     mul    blksize
  401.     mov    bx,ax
  402.     call    outdec
  403.     mov    dx,offset st4str
  404.     call    putstr
  405.     mov    bx,fatcnt
  406.     call    outdec
  407.     mov    dx,offset st5str
  408.     call    putstr
  409.     mov    bx,fatsec
  410.     call    outdec
  411.     mov    dx,offset st6str
  412.     call    putstr
  413.     ret
  414.  
  415. ;Disk A:  Total of 12345 data blocks 1024 bytes each.
  416.  
  417. st1str    db cr,lf,'Disk $'
  418. st2str    db ':  Total of $'
  419. st3str    db ' data blocks $'
  420. st4str    db ' bytes each.',cr,lf,'$'
  421. st5str    db ' FAT sectors, first FAT sector is logical sector $'
  422. st6str  db cr,lf,'$'
  423. ;
  424. ;List out the bad things about this disk.
  425. ;
  426. listbad:
  427.     mov    dx,offset bd1str
  428.     call    putstr
  429.     mov    bx,badcnt
  430.     call    outdec
  431.     mov    dx,offset bd2str
  432.     call    putstr
  433.     mov    bx,newbad
  434.     call    outdec
  435.     mov    dx,offset bd3str
  436.     call    putstr
  437.     ret
  438.  
  439. ;Total of 12345 bad blocks, found 12234 more this pass.
  440. bd1str    db cr,'Total of $'        ;note no linefeed.
  441. bd2str    db ' bad blocks, found $'
  442. bd3str    db ' more this pass.',cr,lf,'$'
  443. page
  444. ;
  445. ;Generally useful system calls.
  446. ;
  447. putstr:    mov    ah,9
  448.     int    21h
  449.     ret
  450. ;
  451. ;Type BX in decimal, suppressing leading
  452. ;zeros.
  453. ;
  454. outdec:    mov    cl,0    ;0 suppress flag,
  455.     mov    dx,10000
  456.     call    rsdiv
  457.     mov    dx,1000
  458.     call    rsdiv
  459.     mov    dx,100
  460.     call    rsdiv
  461.     mov    dx,10
  462.     call    rsdiv
  463.     mov    ch,bl
  464.     jmp    odf
  465.  
  466. rsdiv:    mov    ch,-1    ;iteration -1,
  467. rs1:    inc    ch    ;count,
  468.     sub    bx,dx    ;subtract,
  469.     jnc    rs1    ;til underflow,
  470.     add    bx,dx    ;adjust back,
  471.     cmp    ch,0    ;if non-zero,
  472.     jne    odf    ;type it,
  473.     test    cl,1    ;dont type 0's
  474.     jnz    odf    ;if leading,
  475.     ret
  476.  
  477. odf:    push    dx
  478.     mov    dl,ch
  479.     add    dl,'0'    ;ASCII,
  480.     mov    ah,2
  481.     int    21h
  482.     pop    dx
  483.     mov    cl,1    ;no suppress,
  484.     ret
  485. page
  486. ;
  487. ;More system calls.
  488. ;
  489. seldsk:    mov    dl,al        ;select disk,
  490.     mov    ah,0eh
  491.     int    21h
  492.     ret
  493.  
  494. getdsk:    mov    ah,19h
  495.     int    21h
  496.     ret
  497.  
  498. initdsk:mov    ah,0dh
  499.     int    21h
  500.     ret
  501.  
  502. ina:    mov    ah,0ch        ;char in with no echo
  503.     mov    al,8        ;and flush.
  504.     int    21h
  505.     ret
  506.  
  507. kbdchk:    mov    ah,0Bh        ;Check keyboard for character waiting
  508.     int    21h
  509.     cmp    al,0
  510.     jz    chk1
  511.     mov    ah,8        ;Character waiting - see what it is
  512.     int    21h
  513.     or    al,20h        ;Make it lower case
  514.     cmp    al,'q'        ;Time to QUIT?
  515.     je    chk2        ;Yes
  516. chk1:    clc            ;No - Make sure carry flag is cleared
  517.     ret
  518. chk2:    stc            ;Yep - set carry flag
  519.     ret
  520.  
  521. outa:    mov    dl,al
  522.     mov    ah,2
  523.     int    21h
  524.     ret
  525.  
  526. ;
  527. ; BEEP - entry conditions BX register contains count figure for frequency
  528. ;        to be generated.
  529. ;
  530. beep:    mov    al,0b6h        ; Channel 2, LSB then MSB, Square Wave, Binary
  531.     out    43h,al        ; Program 8253 command register
  532.     mov    ax,bx        ; Get the frequency to be generated
  533.     out    42h,al        ; Load Channel 2 count register LSB
  534.     mov    al,ah
  535.     out    42h,al        ; Load Channel 2 count register MSB
  536.     in    al,61h        ; Read settings from 8255 PPI I/O Port "PB"
  537.     mov    ah,al        ; Save original settings in AH
  538.     or    al,3        ; Enable Timer Channel 2 & Speaker data
  539.     out    61h,al        ; program the 8255 with new setting-speaker on
  540.     sub    cx,cx        ; Sneaky way to put 0FFFFH into CX when
  541. wait2:    loop    wait2        ; LOOP is first executed
  542.     mov    al,ah        ; Get original 8255 Port "PB" settings
  543.     out    61h,al        ; Reset port to original values-speaker off
  544.     ret
  545.  
  546. blkbuf    equ    $        ;cluster buffer
  547.  
  548. fatbuf    equ    $+16384        ;FAT buffer.
  549.  
  550. code ends
  551.  
  552. end    scavenge
  553.