⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dirs.a86

📁 一个dos操作系统DRDOS的源码
💻 A86
📖 第 1 页 / 共 2 页
字号:
	 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 + -