📄 dirs.a86
字号:
jz gtd2
cmp cl,NEXT ; Caller wishes next dfcb?
jne gtd3 ; NO
gtd2:
mov ax,bx ; return BX (DIRP or NULLPTR)
or ax,ax ; return ZF (1 = not found)
ret
gtd3:
cmp cl,EMPTY ; Caller wishes an empty dfcb?
jne gtd4 ; NO
mov al,DNAME[bx] ; Get directory type
or al,al ; Is it free?
jz gtd2 ; YES (00 -> never used)
cmp al,0E5h ; Is the dfcb empty?
je gtd2 ; YES (E5 -> erased)
jmps gtd_next ; NO, try the next
gtd4: ; looking for particular entry
call hdsblk ; Are we at the root?
jnz gtd5 ; skip if not
mov ax,dcnt ; check for end of directory
cmp ax,dirinroot ; have we reached end of root?
mov ax,0 ; assume we have
jae gtd_exit ; exit if we have
gtd5:
mov al,DNAME[bx] ; Get dfcb type
cbw
or ax,ax ; Are we at End Of Directory(EOD)
jz gtd_exit ; YES
cmp al,0E5h ; Is this a free fcb?
je gtd_next ; Yes, try again
mov ax,finddfcb_mask ; do we want labels/pending deletes
test DATTS[bx],ah ; filter out volume labels?
jnz gtd_next ; we normally reject them
if DELWATCH
cbw ; we want labels - do we want
test word ptr DBLOCK1[bx],ax ; DELWATCH pending deletes
jnz gtd_next ; ie. labels with fat chain
endif
push cx ; we are interested - but does
mov al,ch ; the name match ?
cbw
add ax,offset info_fcb+1
xor si,si ; we want SI = entry to match and
xchg ax,si ; AL = 0 indicating assumed match
mov cx,11 ; 11 chars in filename
mov di,bx ; ES:DI -> directory entry
match3:
jcxz match4 ; stop if we have done all 11
repe cmpsb ; compare if 11 bytes the same
je match4 ; skip if all bytes the same
cmp byte ptr 0-1[si],'?' ; else was INFO_FCB byte = '?'
je match3 ; in that case it matches too
inc ax ; else we didn't match (AL<>0)
match4:
pop cx
or al,al ; did we match ?
jnz gtd_next ; no, try for another
mov bx,dirp ; Return (BX)
jmp gtd2
eject
find_hcb: ; find HCB_ for given drive
;--------
; On Entry:
; CX = cluster we are looking for
; DH = 00 if exact match required
; FF if we want to recyle oldest HCB_
; On Exit:
; CY set, AX=0 if HCB_ not found
; CY clear ES:BX = offset of HCB_ (moved to head of list)
; (AX/DX trashed, All other regs preserved)
;
les bx,hashroot ; get our hashing pointer
mov ax,es
or ax,bx ; is hashing enabled ?
jz find_hcb30
mov dl,adrive ; look for this drive
cmp cx,es:HCB_CLU[bx] ; does cluster match?
jne find_hcb10 ; goto next if not
cmp dl,es:HCB_DRV[bx] ; does drive match?
jne find_hcb10 ; goto next if not
; clc
ret ; we have a match on the 1st one
find_hcb10:
; no match, so look futher along the chain
mov ax,es:HCB_LINK[bx] ; onto the next entry
test ax,ax ; is there one ?
jz find_hcb20
xchg ax,bx ; AX = previous entry, BX = current
cmp cx,es:HCB_CLU[bx] ; does cluster match?
jne find_hcb10 ; goto next if not
cmp dl,es:HCB_DRV[bx] ; does drive match?
jne find_hcb10 ; goto next if not
; we have a match, but it's not the first so recycle it
mov dx,es:HCB_LINK[bx] ; get link to the rest of the chain
xchg ax,bx ; BX = previous entry
mov es:HCB_LINK[bx],dx ; unlink ourselves from chain
mov bx,ax ; BX = current entry
xchg ax,word ptr hashroot ; put current entry at the head
mov es:HCB_LINK[bx],ax ; and relink the rest of the chain
; clc
ret
find_hcb20:
; we have been all along the chain with no luck
xor ax,ax
test dh,dh ; no HCB_ - do we want to recyle ?
jz find_hcb30 ; if not skip
mov es:HCB_CNT[bx],ax ; we need to recycle oldest HCB_
mov es:HCB_CLU[bx],cx ; so mark as us, but with nothing
mov es:HCB_DRV[bx],dl ; in it
; clc
ret
find_hcb30:
stc ; return failure
ret
eject
;-----
mkhsh:
;-----
;
; entry: SI = 11 byte FCB to convert to hash code
; exit: AX = 1..FFFF is hash code (00/E5 == 0)
; uses: DX
; saves: BX,CX,DI,BP
;
; used for hashing the INFO_FCB &
; directory entries for DOS media
xor dx,dx ;assume hash code is 0000
lodsb
cmp al,0E5h ;if deleted file
je mkhsh2 ; or
cmp al,0 ;if virgin entry
je mkhsh2 ;then hash code = 0;
push cx ;else save CX
and al,7fh
mov dh,al ;initialize hash code MSB
mov cx,10 ;involve other 10 characters
mkhsh1:
lodsb ;get next character
rol dx,1 ;rotate hash code by one bit
and al,7fh ;strip top bit off character
xor dl,al ;XOR the character into the hash code
loop mkhsh1 ;repeat for all characters
pop cx ;restore CX
test dx,dx ;test if zero by any chance
jnz mkhsh2 ;skip if non-zero
inc dx ;else force it to 1
mkhsh2: ;return hash code in AX
xchg ax,dx
ret
eject
if DELWATCH
Public fixup_hashing
;
; update hashing for current drive if DELWATCH changes a directory entry
;
fixup_hashing:
;-------------
; On Entry:
; AX = segment of dir buffer
; CX = cluster to fixup (0 = root)
; DI = directory entry index (clipped to cluster if subdir)
; AX:SI-> dir entry (single entry for hashing)
;
; On Exit:
; None
;
push ds
push es
xor dh,dh ; we only want HCB_ if it's there
push ax ; save seg of dir entry
call find_hcb ; does an HCB_ exist for this entry ?
pop ds ; DS:SI -> entry to hash
jc fixup_ck10 ; not hashed, skip update
cmp di,es:HCB_CNT[bx] ; is this within the hashed entries ?
jae fixup_ck10 ; no, skip the fixup
call mkhsh ; AX = hash code of our entry
shl di,1 ; DI = offset of hashed entry
lea di,HCB_DATA[bx+di]
stosw ; update hash code for dir entry
fixup_ck10:
pop es
pop ds
ret ; no
endif
eject
hashsrch:
;--------
; entry: AX = starting cluster of directory
; exit: AX is possible match index
;
mov dh,0FFh ; we want HCB_ even if it's recycled
xchg ax,cx ; and this block
call find_hcb ; does an HCB_ exist for this entry ?
; mov ax,0 ; assume unhashed search required
jc hashsrch20 ; start one if no hashing
hashsrch10:
mov cx,es:HCB_CNT[bx] ; we have this many entries hashed
jcxz hashsrch30 ; skip if nothing hashed yet
mov ax,hash ; look for this hash code
lea di,HCB_DATA[bx] ; DI = offset of start of search
repne scasw ; try to find a match
jne hashsrch30 ; skip if no match found
lea ax,HCB_DATA+2[bx] ; find word offset of match
xchg ax,di ; return matching index
sub ax,di
shr ax,1 ; make dir offset
hashsrch20:
push ds ! pop es
clc ; we have found it
ret
hashsrch30:
call rehash_entry ; try and hash another entry
jnc hashsrch10 ; look again if we succeeded
mov ax,es:HCB_CNT[bx] ; failure, so return # to skip
push ds ! pop es
; stc ; for quicker search
ret
rehash_entry:
;------------
; entry: ES:BX -> HCB
; AX = hash cluster number
call hash_entries_to_do ; how many entries still to hash ?
jcxz rehash_entry40 ; if we have hashed them all exit
push dcnt ; save directory count
mov ax,dcnt ; get previous position
inc ax ; we start looking here
xor dx,dx
div dirperclu ; mask to start of cluster
mul dirperclu
add ax,es:HCB_CNT[bx] ; skip entries we already have
dec ax ; make previous entry BEFORE this
mov dcnt,ax
mov chdblk,0 ; non-sequential access
cmp cx,512/32 ; don't try reading more than 512 bytes
jb rehash_entry20 ; at a time - then with 512 byte secs
mov cx,512/32 ; we only read when we
rehash_entry20:
push es
push bx ; save hash control pointer
push cx ; save # entries to do
push ds ! pop es ; back to small model
xor cx,cx ; return any entry
call gtd_next ; unhashed search
pop cx ; restore # entries to do
pop bx ; restore hash control pointer
pop es
test ax,ax ; anything found
jz rehash_entry30 ; end of directory
xchg ax,si ; else get directory pointer
mov di,es:HCB_CNT[bx]
shl di,1 ; DI -> 1st new entry
lea di,HCB_DATA[bx+di]
push si
call mkhsh ; else calculate hash into AX
stosw ; add it to hash table
inc es:HCB_CNT[bx] ; remember we did
pop si
lodsb ; get 1st byte of hashed entry
test al,al ; is it zero (ie. never used)?
loopne rehash_entry20 ; get all hash codes
jcxz rehash_entry30 ; all done ?
call hash_entries_to_do ; how many entries still to hash ?
add es:HCB_CNT[bx],cx ; we will do them all..
rep stosw ; zap rest of cluster
rehash_entry30:
pop dcnt ; restore count
mov chdblk,0 ; non-sequential access
clc ; we have new hashing codes
ret ; HCB updated with new cluster
rehash_entry40:
stc ; cannot hash no more...
ret
hash_entries_to_do:
;------------------
; On Entry:
; ES:BX -> HCB_
; On Exit:
; CX = maximum possible entries we still need to hash for HCB_
; (All other regs preserved)
;
mov cx,dirinroot ; assume root dir
cmp es:HCB_CLU[bx],0 ; was it ?
je hash_etd10
mov cx,dirperclu ; subdir, so cluster limit
hash_etd10:
cmp cx,hashmax ; do we support this many ?
jb hash_etd20 ; yes, skip it
mov cx,hashmax ; else limit it to this many
hash_etd20:
sub cx,es:HCB_CNT[bx] ; subtract number we have already done
ret
eject
hshdscrd:
;--------
; purge hash blocks for physical drive
; On Entry:
; AL = drive to discard (FF = all drives)
; On Exit:
; None (All regs preserved)
push ds
push bx
lds bx,hashroot ; get root of hash codes
hshdsc1:
test bx,bx
jz hshdsc4 ; all blocks done
cmp al,0FFh ; FF means discard all drives
je hshdsc2
cmp al,ds:HCB_DRV[bx] ; check if matching drive
jne hshdsc3
hshdsc2:
mov ds:HCB_DRV[bx],0ffh ; h->hd = 0xff;
hshdsc3:
mov bx,ds:HCB_LINK[bx] ; get next hash code block
jmps hshdsc1
hshdsc4:
pop bx
pop ds
ret
eject
enlarge_root:
if DELWATCH
mov ah,DELW_FREERD ; lets ask DELWATCH if it can
mov al,adrive ; free a root directory entry
callf ss:fdos_stub ; for this drive
jnc allocdir ; it says it has so try again
endif
allocdir_err:
pop ax ; discard return address
mov ax,ED_MAKE
jmp fdos_error ; return "cannot make dir entry"
;--------
allocdir: ; Called by rename and MAKE
;--------
call setenddir ; search for first match
mov cx,1 ; return empty fcb
call getdir ; is there an empty fcb?
jz allocdir10 ; if so use that
ret
allocdir10:
call hdsblk ; Are we at the root?
jz enlarge_root ; YES -- Report error(no room)
; We are in a subdirectory so enlarge it
; AX has 1st block of subdirectory NOTE -- AX is never
; above 'lastcl' on entry.
allocdir20:
cmp ax,lastcl ; Are we at end of subdirectory?
ja allocdir30 ; YES
push ax
call getnblk ; NO -- get next block then
pop bx
jmps allocdir20
allocdir30:
push bx ; save last block number
xchg ax,bx ; Get a new block (start from old)
call alloc_cluster
pop bx
jc allocdir_err ; Report Error(no room on disk)
push ax ; save new block
xchg ax,bx
call fixfat ; Update fat (AX,BX) old last block
; points to new last block
pop ax ; Get new last block
push ax
mov bx,dosfat ; 12 or 16 bit fat
call fixfat ; Update fat (AX,BX) new last block
; has end of cluster marker
call update_fat ; Write out to disk
pop ax ; Get new last block
call zeroblk ; Zero it out
call setenddir ; Set up for search first
mov cx,1 ; Find empty fcb
jmp getdir ; Can not return with not found error
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -