home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
asm_kit
/
findbad.asm
< prev
next >
Wrap
Assembly Source File
|
1985-11-08
|
8KB
|
402 lines
title scavenge Copyright (c) T. Jennings 1983
;
;****************************************
;* *
;* SCAVENGE *
;* *
;* Mark bad blocks on MSDOS *
;* as allocated in the FAT. *
;* *
;* T. Jennings 5 June 82 *
;* created 15 Sept. 82 *
;* *
;****************************************
;
;Reads all sectors in logical MSDOS blocks
;and marks the file allocation tables such
;that the blocks are permanently allocated
;where CHKDSK will not deallocate them.
;
;
;This version works on any 2.xx MSDOS or
;PCDOS, on any media type, fixed or removable.
;One (major) limitation: it will not map out
;blocks that are already allocated to a file;
;it will say "block used", but won't tell you
;which file it is in.
;
;If SCAVENGE finds any bad blocks, it will ask
;you whether or not you want the disk updated.
;You can safely run it just to see if the disk
;is OK.
;
;MASM, LINK, then EXE2BIN this to make a COM
;file. It will not run as an EXE file. NOTE:
;LINK will give you a 'Warning: no STACK
;segment' error: ignore it.
;
cr equ 0dh
lf equ 0ah
page
cgroup group code
code segment byte public 'code'
assume cs:cgroup,ds:cgroup,ss:cgroup
;
;MSDOS page 0 stuff.
;
org 5ch
tfcb label byte
org 80h
tbuff label byte
org 100h
scavenge:
jmp start
;
;Disk parameters:
;
blkcnt dw (?) ;blocks this disk
blksize dw (?) ;sectors per block
secsize dw (?) ;phys. sector size
badcnt dw (?) ;# bad blocks found
newbad dw (?) ;new bad ones
block dw (?) ;current block
sector dw (?) ;sector to read
disk db (?) ;selected disk
curdsk db (?) ;current disk.
fatsec dw (?) ;1st FAT sector,
fatcnt dw (?) ;FAT sec count.
dw 128 dup (?)
stack dw (?) ;what else
page
;
;Say who we are, describe the disk we are
;about to fix, ask to continue or abort.
;
start: mov ax,cs
mov ds,ax
mov ss,ax
mov sp,offset stack
mov dx,offset signon
call pstr
call setup ;get disk stuff
jnc st1
call pstr
int 32 ;error.
st1: call liststat ;describe dsk
mov dx,offset contstr
call pstr ;type any key..
call ina
;
;Find all the bad blocks, if any, display them,
;ask if we should update the FAT. If so, write
;it out.
;
mov dx,offset crlf
call pstr
call findbad ;map bad,
call listbad ;list them,
cmp newbad,0 ;if new bad
je st2 ;blocks...
mov dx,offset updstr ;ask if we
call pstr ;should update
call ina
and al,5fh
cmp al,'Y'
jne st2
mov al,disk ;write out the
mov dx,fatsec ;FAT,
mov cx,fatcnt
mov bx,offset fatbuf
int 26h
pop ax ;pop flags
st2: mov al,curdsk ;reselect the
call seldsk ;original disk
int 32
signon db cr,lf,'DOS version 2 Bad Sector Mapper'
db cr,lf,' T. Jennings 5 June 83'
db '$'
contstr db cr,lf,'Type ^C to abort, any '
db 'other key to continue: $'
updstr db cr,lf,lf,' Want the disk updated? [y,n] :$'
crlf db cr,lf,'$'
page
;
;Get the data on the specified disk. Return
;carry if no drive specified. Returns ES:DI
;pointing to the FAT for the selected drive.
;
setup: call initdsk ;reset dsk sys,
call getdsk ;get current,
mov curdsk,al ;save it,
mov al,tfcb ;make sure a
cmp al,0 ;new one spec'd
stc ;quit if none,
mov dx,offset strstr
jz gd1
dec al ;make 0-N,
mov disk,al
call seldsk ;select,
push ds ;save local DS,
mov ah,1bh
int 33
pop ds
mov blkcnt,dx ;save # blocks,
mov secsize,cx ;sector size,
mov ah,0
mov blksize,ax ;secs/block.
push ds ;now get the
mov dl,disk
inc dl ;drive 1=A, b=2
mov ah,50 ;FAT,
int 33 ;get the DPB,
mov cx,[bx+15] ;CX= sec count,
mov ch,0
mov dx,[bx+6] ;DX= 1st sec,
pop ds
mov fatcnt,cx ;save both,
mov fatsec,dx
mov al,disk ;AL= drive #,
mov bx,offset fatbuf ;DS:BX= buffer
int 25h ;read the FAT,
pop ax ;pop flags
mov dx,offset bscstr
gd1: ret
strstr db cr,lf,'Must specify a disk drive.$'
bscstr db cr,lf,'Bad FAT sector: disk not useable.$'
page
;
;Read the entire disk looking for bad blocks.
;When one is found, go mark it as an allocated
;bad block.
;
findbad:
mov block,0 ;1st block,
mov badcnt,0 ;none yet,
fb1: mov dx,offset blkstr ;type 'block '
call pstr
mov bx,block ;block number,
call outdec
call readblk ;read a block,
jnc fb3 ;if bad,
inc badcnt ;count it,
mov dx,offset badstr
call pstr ;type 'bad'
call mapout ;mark bad,
mov dx,offset cntstr ;error if cant
jc fb2
add newbad,cx ;count it,
mov dx,offset alrstr
jcxz fb2 ;already markd
mov dx,offset mrkstr
fb2: call pstr
fb3: inc block ;next block,
dec blkcnt ;another...
jnz fb1 ;keep looking.
ret
blkstr db cr,'Block $'
badstr db ' bad,$'
alrstr db ' already marked.',cr,lf,'$'
mrkstr db ' mapped out.',lf,'$'
cntstr db ' already used! I dont know'
db ' which file.',lf,'$'
page
;
;Mark the current block as bad in the FAT.
;Multiply the block number by 1.5 to find the
;block number, (actually *3, /2) and if not
;used, mark it bad. If used, report which file
;it's in. If it's already mapped as bad,
;return CX =0, else return CX=1.
;
mapout:
mov bx,block ;block,
shl bx,1 ;times 2,
add bx,block ;times 3,
shr bx,1 ;divide by 2,
mov ax,fatbuf[bx] ;get word,
;
;If carry is set, we want the high 12 bits in
;the word in AX, else the low 12 bits. Set CH
;as the shift count, DX as the mask.
;
mov ch,0 ;assume low,
mov dx,0fffh
jnc mo1
mov ch,4 ;else high 12,
mov dx,0fff0h
mo1: and ax,dx ;mask it,
mov cl,ch
shr ax,cl ;shift it,
;
;AX is the block number; if it's anything
;but 000 or ff7, return with carry set,
;indicating that its already used.
;
cmp ax,0ff7h ;if ff7,
je mo2 ;already marked
cmp ax,0 ;if allocated,
je mo3
stc ;error!
mo2: mov cx,0 ;none mapped,
ret
;
;Bad unused block. Mark as bad in the FAT.
;
mo3: mov ax,0ff7h ;marker,
mov cl,ch
shl ax,cl ;shift it,
or fatbuf[bx],ax ;mark it.
mov cx,1 ;1 mapped,
ret
page
;
;Read one block, return carry set if read
;error. Leave the useless data in the buffer
;following the end of this program.
;
readblk:
mov ax,block ;find start
mov cx,blksize ;sector,
mul cx ;CX= count,
mov dx,ax ;DX= sector,
mov al,disk
mov bx,offset blkbuf ;our buffer,
int 25h ;read sectors,
pop dx ;pop flags,
ret
page
;
;List the general info on the disk, like
;sector sizes, etc.
;
liststat:
mov dx,offset st1str
call pstr
mov al,disk
add al,'A'
call outa
mov dx,offset st2str
call pstr
mov bx,blkcnt
call outdec
mov dx,offset st3str
call pstr
ret
;Disk A:, total of 12345 data blocks.
st1str db cr,lf,'Disk $'
st2str db ':, total of $'
st3str db ' data blocks.$'
;
;List out the bad things about this disk.
;
listbad:
mov dx,offset bd1str
call pstr
mov bx,badcnt
call outdec
mov dx,offset bd2str
call pstr
mov bx,newbad
call outdec
mov dx,offset bd3str
call pstr
ret
;Total of 12345 bad blocks, found 12234 more this pass.
bd1str db cr,'Total of $' ;note no linefeed.
bd2str db ' bad blocks, found $'
bd3str db ' more this pass.$'
page
;
;Generally useful system calls.
;
pstr: mov ah,9
int 33
ret
;
;Type BX in decimal, suppressing leading
;zeros.
;
outdec: mov cl,0 ;0 suppress flag,
mov dx,10000
call rsdiv
mov dx,1000
call rsdiv
mov dx,100
call rsdiv
mov dx,10
call rsdiv
mov ch,bl
jmp odf
rsdiv: mov ch,-1 ;iteration -1,
rs1: inc ch ;count,
sub bx,dx ;subtract,
jnc rs1 ;til underflow,
add bx,dx ;adjust back,
cmp ch,0 ;if non-zero,
jne odf ;type it,
test cl,1 ;dont type 0's
jnz odf ;if leading,
ret
odf: push dx
mov dl,ch
add dl,'0' ;ASCII,
mov ah,2
int 33
pop dx
mov cl,1 ;no suppress,
ret
page
;
;More system calls.
;
seldsk: mov dl,al ;select disk,
mov ah,0eh
int 33
ret
getdsk: mov ah,19h
int 33
ret
initdsk:mov ah,0dh
int 33
ret
ina: mov ah,0ch ;char in with
mov al,1 ;flush.
int 33
ret
outa: mov dl,al
mov ah,2
int 33
ret
blkbuf db 16384 dup (?) ;cluster buffer
fatbuf label word ;FAT buffer.
code ends
end scavenge