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

📄 funcs.fdo

📁 一个dos操作系统DRDOS的源码
💻 FDO
📖 第 1 页 / 共 5 页
字号:
; On Exit:
;	None
	lodsw				; get sector size in bytes
	mov	es:DDSC_SECSIZE[di],ax

	lodsb				; get sectors/allocation unit
	dec	ax			; get cluster mask
	mov	es:DDSC_CLMSK[di],al	; store cluster mask
	lodsw				; get FAT address
	mov	es:DDSC_FATADDR[di],ax

	lodsb				; get # of fats
	mov	es:DDSC_NFATS[di],al
	cbw				; make it a word value
	xchg	ax,dx			; and keep in DX

	lodsw				; get # of directory entries
	mov	es:DDSC_DIRENT[di],ax

	lodsw				; get # of sectors total in image
	push	ax			; save disk size for later

	lodsb				; get FAT id byte
	mov	es:DDSC_MEDIA[di],al	; set media byte

	lodsw				; get # of sectors in a fat
if DOS5
	mov	es:DDSC_NFATRECS[di],ax	; set FAT size
else
	mov	es:DDSC_NFATRECS[di],al	; set FAT size
endif

	mul	dx			; AX = FAT size
	add	ax,es:DDSC_FATADDR[di]	; AX = 1st directory sector
	mov	es:DDSC_DIRADDR[di],ax	; set root directory address

	add	si,word+word+dword	; skip SPT, NHEADS, BIGHIDDEN

	mov	cx,es:DDSC_SECSIZE[di]
	mov	ax,32			; size of single directory entry
	mul	es:DDSC_DIRENT[di]		; AX/DX = root directory bytes
	add	ax,cx			; round up sector size
	dec	ax			;  in case of odd number
	div	cx			; convert to whole sectors
	add	ax,es:DDSC_DIRADDR[di]	; add in base of root directory
	mov	es:DDSC_DATADDR[di],ax	; set this as first cluster address

	pop	ax			; recover total disk size
	xor	dx,dx			; assume 16 bit number
	test	ax,ax			; test for big drive
	 jnz	bpb2ddsc10		; skip if not large drive
	lodsw				; get low word of size
	mov	dx,[si]			; get high word of size
bpb2ddsc10:				; AX/DX = disk size in sectors
	sub	ax,es:DDSC_DATADDR[di]	; subtract non-data portion
	sbb	dx,0

	xor	cx,cx			; CL = cluster shift
	mov	ch,es:DDSC_CLMSK[di]	; CH = cluster mask
bpb2ddsc20:				; count # of 1 bits
	shr	ch,1			; shift right mask
	 jnc	bpb2ddsc30		; skip if all 1 bits shifted out
	inc	cx			; count another 1 bit
	shr	dx,1
	rcr	ax,1			; div by two
	jmps	bpb2ddsc20		; repeat until all 1's counted
bpb2ddsc30:				; CL = log2 (CH)
	mov	es:DDSC_CLSHF[di],cl	; set cluster shift
	inc	ax			; clusters 0/1 reserved (+2), and we
	mov	es:DDSC_NCLSTRS[di],ax	;  want max (-1), so +1
	xor	ax,ax
	mov	es:DDSC_BLOCK[di],ax	; next block = 0
	dec	ax
	mov	es:DDSC_FREE[di],ax	; free space = -1 (unknown)
	ret

eject
;	DIRECT DISK IO

;	+----+----+----+----+----+----+
;	|    54   |drv | op |nsectors |
;	+----+----+----+----+----+----+----+----+
;	|      startsec     |    dma address    |
;	+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	param block set up for direct disk IO 

;	exit:
;	-----
;	AX = 0, or error code
;

DIO_25_READ_OP		equ	1
DIO_26_WRITE_OP		equ	2

fdos_ddio:
;---------
;	Used by emulator for Int 25H/26H disk calls to BIOS
;
;	entry:	dio = offset of parameter block in user data segment
;
;	exit:	AX = return code from BIOS

	call	local_disk		; get the MX
	mov	ax,fdos_pb+WORD		; AX = logical drive
	call	logical2physical	; AX = physical drive
	call	get_ddsc		; make sure this drive is valid
	 jc	fdos_ddio30		; bail if not
	mov	adrive,al		; remember this unit
	mov	ax,CMD_INPUT+0*256	; disk read operation of system area
	cmp	byte ptr fdos_pb+3,DIO_26_WRITE_OP
	 jne	fdos_ddio10
	mov	ax,0FFFFh
	mov	es:DDSC_FREE[bx],ax	; free space = -1 (unknown)
	call	hshdscrd		; discard hashing info for all drives (AL=FF)
	mov	ax,CMD_OUTPUT+1*256	; disk write operation of system area
fdos_ddio10:
	mov	rwmode,ah		; save read/write of system area
	mov	req_hdr+5,ah		; (so driver can get the hint)
	mov	bx,offset req_hdr	; we will build request here
	mov	RH_CMD[bx],al		; save the command
	mov	ax,fdos_pb+4		; AX = # sectors
	mov	RH4_COUNT[bx],ax	; set requested sector count
	les	ax,dword ptr fdos_pb+6	; pick up 32-bit record address
	mov	word ptr pblock,ax
	mov	word ptr pblock+WORD,es
	les	ax,dword ptr fdos_pb+10	; ES:AX -> DMA seg
	mov	RH4_BUFOFF[bx],ax
	mov	RH4_BUFSEG[bx],es
	call	ddioif			; go do it
	 jns	fdos_ddio20		; did we have a problem ?
	cbw				; AX = base error
	add	ax,ED_PROTECT		; "add" in BIOS error code
	mov	fdos_ret,ax		; save return code
fdos_ddio20:
	ret

fdos_ddio30:
	jmp	fdos_ED_DRIVE		; return bad drive error

eject
;	EXPAND FILE NAME

;	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
;	|    55   |   relative name   |                   |   absolute name   |
;	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	relative name:	segmented address of ASCIIZ name
;	absolute name:	segmented address of ASCIIZ name

;	exit:
;	-----
;	AX = BX: 0000 or error code ( < 0)

fdos_expand:
;-----------
	call	redir_asciiz_dev_offer	; is it a networked device ?
	call	asciiz_dev_offer	; see it we are expanding a device name
	call	local_disk		; get MXdisk, switch stack
	push	ds
	les	si,dword ptr fdos_pb+2	; get relative name buffer
	mov	ax,es:[si]		; get 1st two chars of path
	call	check_dslash		; is it a '\\' form ?
	 je	fdos_expand10
	mov	bx,ED_FILE
    test    al,al           
	 jz	fdos_expand60
	call	toupper			; work on premise we have drive
	sub	al,'A'			; specified in relative name
	sub	ah,':'			; did we have ?
	 je	fdos_expand20		; if so use it
fdos_expand10:
	mov	al,current_dsk		; use current drive
fdos_expand20:
	cmp	al,last_drv		; is it a legal drive
	 jae	fdos_expand50

; we should check for a media change so select_logical_drv seems to be
; a better solution
;	call	get_ldt			; ES:BX -> LDT_ for drive
;	 jc	fdos_expand40		; no LDT at init - copy relative path
;	mov	word ptr current_ldt,bx
;	mov	word ptr current_ldt+WORD,es
	call	select_logical_drv
	les	bx,current_ldt

	test	es:LDT_FLAGS[bx],LFLG_PHYSICAL
	 jz	fdos_expand50		; make sure it's a valid drive
	push ss ! pop es
	mov	di,offset pri_pathname	; build name in pathname buffer
	lds	si,dword ptr fdos_pb+2

; we must trick redir_build_path to find the correct function number -
; otherwise we could not get correct (critical) error reporting to work
	push	bp
	mov	bp,offset fdos_pb+6
	mov	2[bp],bp
	mov	byte ptr [bp],FD_EXPAND

	call	redir_build_path	; build name from LDT
	pop	bp
	 jc	fdos_expand60		; bail out if bad name
	lds	di,ss:current_ldt	; we need to append a '\' if
	mov	bx,ds:LDT_ROOTLEN[di]	;  we are at the root
	test	ds:LDT_FLAGS[di],LFLG_SUBST
	 jz	fdos_expand30		; if drive is SUBST'd then
	mov	bx,2			;  only append if real root
fdos_expand30:
	mov	si,offset pri_pathname	; SS:SI -> full path
	push ss ! pop ds		; leave current ldt -> buffer as LAN
	mov	word ptr current_ldt,si	;  MAN 2.1 extended edition expects it
	mov	word ptr current_ldt+WORD,ds
	mov	ax,'\'			; get pathchar in AX for checks
	cmp	ds:byte ptr [si+bx],ah	; are we at the root ?
	 jne	fdos_expand40		; if so append a '\'
	mov	ds:word ptr [si+bx],ax
fdos_expand40:
	les	di,ss:dword ptr fdos_pb+10; ES:DI -> destination buffer
	call	copy_asciiz		; copy the full pathname
	pop	ds
	ret

fdos_expand50:
	mov	bx,ED_DRIVE		; return bad drive error
fdos_expand60:
	mov	ax,bx
	pop	ds
	jmp	fdos_error

expand_dev:
;----------
	les	si,dword ptr fdos_pb+2	; this is the original source
	lods	es:ax			; get the source
	les	di,dword ptr fdos_pb+10	; data will end up here
	cmp	ah,':'			; is a drive specified ?
	 je	expand_dev10
	mov	al,'A'
	add	al,ss:current_dsk
expand_dev10:
	call	toupper			; make sure drive letter is upper case
	stosb				; plant an 'd'
	mov	ax,':'+256*'/'
	stosw				; make that 'd:/'
	mov	bx,offset name_buf	; DS:BX -> name buffer
	jmp	unparse			; unparse the device name

eject
;	RENAME FILE

;	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
;	|    56   |      old name     |                   |      new name     |
;	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	old name:	segmented address of ASCIIZ name
;	new name:	segmented address of ASCIIZ name

;	exit:
;	-----
;	AX:	0000 or error code ( < 0)

;	Note:	R/O files can be renamed.
;			  ---

fdos_move:
;---------
	call	redir_move_offer
	call	local_disk		; get MXdisk, switch stack
	call	path_prep		; parse the path, go to bottom level
	call	chk_no_dev
	cmp	ss:remote_call,0	; wildcards allowed if server/FCB
	 jnz	move10
	call	chk_no_wild		; make sure not a wild card
move10:
	call	finddfcbf		; else try to locate directory entry
	 jz	fdos_ED_FILE		; error if no match occurred
move20:
	call	close_if_same_psp	; make sure not open by other PDs
if PASSWORD
	call	check_pwd_any		; check if password protected
endif
	mov	si,dirp			; get matching directory entry
	mov	di,offset save_area	; get a temporary save area
	mov	cx,32/WORD		; save it all
	rep	movsw			; so we can move it to new entry

	mov	si,offset fdos_hds
	mov	di,offset saved_hds
	mov	cl,HDS_LEN
	rep	movsb			; copy current HDS to safe place

	mov	ax,dcnt			; also save directory index
	mov	saved_dcnt,ax		; so we can release entry later

	les	di,dword ptr fdos_pb+10	; es:di -> path name
	call	path_prep_ptr		; find the destination path
	call	chk_no_dev		; no devices allowed here
	cmp	ss:remote_call,0	; wildcards allowed if server/FCB
	 jnz	move25
	call	chk_no_wild		; make sure not a wild card
move25:
	mov	al,fdos_hds_drv		; get the work drive
	cmp	al,saved_hds_drv	; make sure same drive for
	 je	move30			;   source and destination

	mov	ax,ED_DEVICE		; "not same device" error
	jmps	fdos_moverr		; return the error
fdos_ED_FILE:
	mov	ax,ED_FILE		; get error code
fdos_moverr:
	jmp	fdos_error		; return the error

move30:					; same drive for source & destination
	mov	al,byte ptr fdos_pb+8	; check attributes
if PASSWORD
	cmp	save_area+DPWD,0
	 je	move31
	or	al,DA_HIDDEN
move31:
endif
	not	al
	and	al,DA_HIDDEN+DA_SYSTEM+DA_DIR+DA_VOLUME
	test	save_area+DATTS,al
	 jnz	move80
	mov	si,offset info_fcb+1	; SI->new name (possible wildcards)
	mov	di,si			; DI->new name
	mov	bx,offset save_area	; current name on disk
    cmp byte ptr DNAME[bx],'.'  
     je move80          
	mov	cx,11
move40:					; fill in the wild card characters
	lodsb				; get next character from new name
if KANJI
	call	dbcs_lead		; is it the 1st of a kanji pair
	 jne	move45
	dec	cx			; copied this one
	 jcxz	move55			; discard if no room for kanji char
	stosb				; copy 1st byte of Kanji pair
	inc	bx
	lodsb				; copy 2nd byte
	jmps	move50
move45:
endif
	call	toupper			; make it upper case
	cmp	al,'?'			; is it just a wild card?
	 jne	move50			; no, put in destination as is
	mov	al,[bx]			; else leave original character
move50:					; AL = next char for destination
	stosb				; store next char in destination
	inc	bx			; increment all pointers
	loop	move40			; repeat for all 11 characters
move55:

	call	finddfcbf		; find first non-volume entry
	 jnz	move_access		; file already exists, return error

	call	move_comp		; source & destination in same dir?
	 jne	move60			; skip if moving to different directory
	call	move_seek		; else find old entry again
	jmps	move70			; replace name in old entry

move60:					; moving to different directory
	test	save_area+DATTS,DA_DIR	; can't move directory to new path
	 jnz	move_access		; so return error if new path
	call	allocdir		; allocate a directory entry
move70:
	mov	si,offset info_fcb+1	; get pointer to new name
	mov	di,dirp			; get pointer to directory entry
	mov	cx,11			; copy new name into buffer
	rep	movsb


	mov	si,offset save_area+11	; copy remaining info
	mov	cx,32-11
	rep	movsb
	call	update_dir		; update the disk

	call	move_comp		; did we rename across directories?
	 je	move80			; skip if in same directory
	mov	si,offset saved_hds
	mov	di,offset fdos_hds	; else need to copy HDS back
	mov	cx,HDS_LEN		; so we can get old entry again
	rep	movsb			;    (time to get rid of it)
	call	move_seek		; seek the original entry
	mov	bx,dirp
	mov	DNAME[bx],0E5h		; and bye, bye! it goes...
	call	update_dir		; update the old directory entry
move80:
	cmp	ss:remote_call,0	; wildcards allowed if server/FCB
	 jz	move90			;  so check for multiple files
	call	path_prep		; parse the path, go to bottom level

	mov	ax,saved_dcnt		; restore dcnt for remote call
	mov	dcnt,ax			; to function properly
	and	chdblk,0

	call	finddfcb		; try to locate another directory entry
	 jz	move90			; no, return now
	jmp	move20			;  round again if we do

move_access:
	jmp	fdos_ED_ACCESS		; "access denied" if file
					;     already exists
move90:
; in order to update the current directory in case part of it has been
; renamed we call fdos_chdir which does all the work for rebuilding
; the LDT_ for the given drive
	push	ss
	pop	ds
	mov	bx,offset sec_pathname
	mov	ax,path_drive
	add	ax,'A'+(':'*100h)
	mov	[bx],ax
	mov	word ptr 2[bx],'.'
	mov	fdos_pb+4,ds
	mov	fdos_pb+2,bx
	mov	byte ptr remote_call,0
	jmp	fdos_move_chdir

move_seek:				; re-seek the old directory entry
	mov	ax,saved_dcnt		; get saved directory count
	dec	ax			; move back one for GETDIR
	mov	dcnt,ax			; set search offset
	and	chdblk,0		; follow the chains, not sequential
	mov	cl,0			; return next entry
	jmp	getdir			; in current directory

move_comp:
	mov	ax,fdos_hds_blk
	cmp	ax,saved_hds_blk
	ret

eject
;	GET/SET FILE DATE/TIME

;	+----+----+----+----+----+----+----+----+----+----+
;	|    57   |  handle |   mode  |   date  |   time  |
;	+----+----+----+----+----+----+----+----+----+----+

;	entry:
;	------
;	handle:	open file handle
;	mode:	0 = get date/time, 1 = set date/time
;	date:	date as in directory FCB
;	time:	time as in directory FCB

;	exit:
;	-----
;	AX:	0000 or error code ( < 0)
;	date:	date of last modification if mode = 0
;	time:	date of last modification if mode = 0

fdos_dattim:
;-----------
	call	vfy_dhndl_ptr		; check file handle #
	call	redir_dhndl_offer
	call	local_disk		; get

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -