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

📄 dkio.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 3 页
字号:
	ADC	FileDB.FD_OUTPS,0	;add 1 if printing character
SoutExit:
cEnd					;exit


	SUBTTL	disk OPEN
	page
;***
;DISK_OPEN -- open a file
;
;Purpose:
;	Open a file.  Code is in dkopen.asm.
;*******************************************************************************

DISK_OPEN	EQU	B$DISKOPEN

	SUBTTL	disk block input/output
	page
;***
;DISK_BLKIN -- disk block input
;DISK_BLKOUT -- disk block output
;
;Purpose:
;	Rewritten as part of revision [11].
;	DISK_BLKIN - disk block input, used for BLOAD only.
;	DISK_BLKOUT - disk block output, used for BSAVE only.
;		File position is assumed as already set, the read
;		or write will position the file to the next byte
;		after the operation.
;Entry:
;	(ES:)[SI]   = DGROUP offset of FDB of file to be loaded/saved
;	DX:BX   = source (segment:offset)
;	CX	= maximum number of bytes to read/write
;Exit:
;	CY set - error in read or write.
;	   clear - no error.
;Uses:
;	AX,CX,DX.
;Exceptions:
;	None.
;*******************************************************************************


cProc	DISK_BLKOUT,<NEAR>
cBegin
	MOV	AH,C_WRITE	;set DOS 3 function to write file
	SKIP	2		; skip over DISK_BLKIN
cEnd	nogen

cProc	DISK_BLKIN,<NEAR>
cBegin
	MOV	AH,C_READ	;set DOS 3 function to read file
cEnd	nogen

cProc	DISK_BLK,<NEAR>,<BX,DS>
cBegin
	PUSH	FileDB.FD_HANDLE ;handle on stack while DS=DGROUP
	MOV	DS,DX		;set DS to segment of memory to operate upon

	ASSUME	DS:NOTHING	

	MOV	DX,BX		;set to offset of memory
	POP	BX		;pop handle to register for call
	INT	21H		;perform either DOS 3 read or write
	JC	DISK_BLK_ERR	;if error in operation, then jump
	CMP	AX,CX		;test completion - carry set if not complete
DISK_BLK_ERR:
cEnd

	ASSUME	DS:DGROUP	


	SUBTTL	clear buffer
	page
;***
;ClrRestBuf -- fill remainder of buffer with 0's.  Added with [21].
;
;Purpose:
;	Fill the remainder of buffer with 0's after a short read.
;Entry:
;	[AX]	= number of valid bytes in buffer
;	[CX]	= number of bytes to clear (# requested - # read)
;	[ES:DI] = *buffer
;Exit:
;	End of buffer filled with 0's
;Uses:
;	CX
;Preserves:
;	AX,BX,DX
;Exceptions:
;	none
;*******************************************************************************

cProc	ClrRestBuf,<NEAR>,<AX,CX,DI>

cBegin
	ADD	DI,AX		; [ES:DI] = address to start clear
	XOR	AX,AX		; fill with nulls
	SHR	CX,1		; make length word
	REP	STOSW		; store word
	JNC	ClrBufExit	; brif no odd byte -- exit
	STOSB			; store odd byte
ClrBufExit:
cEnd				; return to caller

	SUBTTL	random I/O supporting routine
	page
;***
; B$MUL32 - 16x32 bit multiply with error checking
;
;Purpose:
;
;Entry:
;	[DX:CX] = multiplicand
;	[AX]	= multiplier
;
;Exit:
;	[DX:CX] = [DX:CX] * [AX]
;
;Uses:
;	AX
;
;Preserves:
;	BX
;
;Exceptions:
;	B$ERR_BRN -- bad record number upon overflow
;
;******************************************************************************
cProc	B$MUL32,<NEAR,PUBLIC>,BX 
cBegin				
	xchg	ax,cx		; get multiplier into cx, low word into ax
	call	B$Mul32x16	; [DX|AX] = [DX|AX] * [CX]
	xchg	ax,cx		; [DX|CX] = result
	jc	ERCBRN		; brif overflow
cEnd				


;***
;Locate -- locate the positon in a file
;
;Purpose:
;	This routine checks whether a given record number is legal.  If it is
;	fine, translate it into the number of bytes.
;Entry:
;	(ES:)[SI]   = *FDB
;	[DX|CX] = record number if user specified
;	[AL]	= flag
;	the flag is defined as the follows:
;		RELFLG ==> record number specified
;
;Exit:
;	[DX|CX] = the location in bytes
;	FileDB.FD_BUFCNT = 0
;Uses:
;	None
;Preserves:
;	AX,BX
;Exceptions:
;	B$ERR_BRN -- bad record number
;*******************************************************************************
cProc	Locate,<NEAR>
cBegin
	TEST	AL,RELFLG		;record number specified?
	JZ	RelRecNum		; Brif not -- use next record # 

	OR	DX,DX			;test upper word of record
	JS	ERCBRN			;Brif negative, "bad record number"
	JNZ	RecNumOK		;Brif positive, record number is OK
	JCXZ	ERCBRN			;Brif low word = 0, "bad record number"
RecNumOK:				
	SUB	CX,1			;make it 0-relative
	SBB	DX,0
	TEST	FileDB.FD_MODE,MD_BIN+MD_RND ; random or binary?
	JZ	LocateExit		; brif not -- exit with [DX|CX] =
					; byte offset
	MOV	FileDB.FD_LOGREC,CX	;save the new referred record #
	MOV	FileDB.FD_HIGHLR,DX	

RelRecNum:
	MOV	CX,FileDB.FD_LOGREC	;[DX|CX] = current logical record
	MOV	DX,FileDB.FD_HIGHLR	
	TEST	FileDB.FD_MODE,MD_BIN	; (SPEED) binary mode?
	JNZ	LocateExit		; brif so -- exit w/o multiplying 
					; by VRECL, since it is 1

	PUSH	AX			; save register
	MOV	AX,FileDB.FD_VRECL	;multiplier
	CALL	B$MUL32			; [DX|CX] = [DX|CX] * [AX]
	POP	AX			; restore register
LocateExit:
	MOV	FileDB.FD_BUFCNT,0	;no read/unwritten bytes in buffer
cEnd					;exit to caller


ERCBRN: JMP	B$ERR_BRN	; bad record number

	SUBTTL	disk random I/O
	page
;***
;DISK_RANDIO -- low level routine to access a file for GET/PUT
;
;Purpose:
;	This routine reads from/writes to a file a record.
;Entry:
;	[AL]		= flags
;			  Bit 0: 1 if PUT, else GET
;			  BIT 1: 1 if explicit record number specified
;			  BIT 2: 1 if record variable specified
;	[BX]		= record length to be written
;	[CX|DX] 	= user specified record number if GET/PUT
;	(ES:)[SI]	= *FDB
;	[b$RECPTR]	= Pointer to the data to be written
;
;Exit:
;	[AX]		= number of bytes actual read/write
;	one buffer is filled/flushed
;Uses:
;	none
;Exceptions:
;	B$ERR_IOE -- device I/O error
;	B$ERR_FWP -- permission denied
;	B$ERR_ACD -- path/file access error
;	B$ERR_BRN -- bad record number (from Locate)
;*******************************************************************************

cProc	DISK_RANDIO,<NEAR>,<CX,DI> 

cBegin
	XCHG	DX,CX		
	CALL	Locate		;[DX|CX] = DWORD byte position of record

	TEST	FileDB.FD_FLAGS,FL_CHAR 
	JNZ	GetPutCharDev	;Brif it is a character device
	test	al,VarStrData	; processing data of var len string?
	jnz	GiveDosCall	; brif so -- don't do the seek.  File is
				; correctly positioned past count word.
	push	ax		; save flags
	CALL	B$SeekFromStart ;seek to set file location (preserves BX)
	pop	ax		; restore flags

GiveDosCall:			;issue the Dos call (AL = Flags)
	PUSH	AX		;save flags
	LES	DI,[b$RECPTR]	; address of buffer
	cCall	DosReadWrite	;issue the Dos call, on return if CY then
				; error happened, AX=error code, else
				; [AX] has the actual number of
				; read/write
	POP	DX		;get back flag in DX
	JB	JMP_AnalyzeErr1	; error return

	FDB_PTR ES			;freshen FDB seg
	TEST	FileDB.FD_MODE,MD_BIN	; binary mode?
	JZ	NotBin			; brif not -- don't adjust count
	ADD	FileDB.FD_LOGREC,AX	; add number actually read/written
	JMP	SHORT IsBin		; to record count
NotBin:					
	test	dl,VarStrLen		; length of variable length string?
	jnz	NoIncrement		; brif not -- don't increment rec #
	ADD	FileDB.FD_LOGREC,1	; increment record number
IsBin:					
	ADC	FileDB.FD_HIGHLR,0	
	JS	ERCBRN			; brif overflow -- bad record number
NoIncrement:				
	OR	FileDB.FD_FLAGS,FL_NEOF ; assume no EOF
	TEST	DL,PUTFLG		; is put ?
	JNZ	PutBuf			; Brif yes

	MOV	CX,BX			; requested count
	SUB	CX,AX			; CX = number we didn't get
	JCXZ	GetPutExit		; Brif got all we requested
	AND	FileDB.FD_FLAGS,NOT FL_NEOF ;clear bit to indicate EOF
	CALL	ClrRestBuf		; clear rest of buffer
	JMP	SHORT GetPutExit	;exit

GetPutCharDev:
	TEST	AL,PUTFLG		; test if PUT or GET
					;   (bug fix -- was: NOT PUTFLG)
	JZ	GiveDosCall		;if GET just do the dos call

	; For random char devices, LOF is just total # bytes 'PUT'
	ADD	FileDB.FD_FSIZ_LO,BX	; add amount to write to file size
	ADC	FileDB.FD_FSIZ_HI,0	; don't bother doing overflow check.
					; So what if size wraps to 0?
	JMP	SHORT GiveDosCall

PutBuf:				
	MOV	CX,BX		; CX = requested count, AX = # written
	CALL	B$CHK_WRITE	; check if all chars written

GetPutExit:
cEnd				;exit to the caller

JMP_AnalyzeErr1:		
	JMP	B$AnalyzeErr	; give appropriate error message


	SUBTTL	low level file I/O -- file access
	page
;***
;DosReadWrite -- issue the DOS call for file read/write
;
;Purpose:
;	Read/write a buffer via DOS call.
;Entry:
;	[AL]	= flag
;	[BX]	= Length of data to be read
;	[SI]	= *FDB
;	[ES:DI] = *buffer
;Exit:
;	b$CSRPOS = 0 (invalid) if console output.
;	if CY
;		[AX] = error code
;	else
;		[AX] = actual number of bytes read/written
;	ES:[SI] = *FDB (for FV_FARFDB only)
;Uses:
;	none
;Preserves: (optional)
;	BX,CX,DX
;Exceptions:
;	none
;*******************************************************************************

cProc	DosReadWrite,<NEAR>,<BX,CX,DX>

cBegin
	TEST	AL,PUTFLG	;is put/write ?

	MOV	CX,BX		; [CX] = buffer length
	MOV	BX,FileDB.FD_HANDLE ; file handle
	MOV	DX,DI		;buffer address
	JNZ	DosCallWrite	;Brif PUT/WRITE
	MOV	AH,C_READ	;read the record in GET
	SKIP	2		
DosCallWrite:
	MOV	AH,C_WRITE	;write the record in PUT
DosCallExit:			
	PUSH	DS		; save DS
	PUSH	ES		
	POP	DS		; [DS:DX] = pointer to data

	ASSUME	DS:NOTHING	


	INT	21H		;do the call
	POP	DS		; restore DS

	ASSUME	DS:DGROUP	


cEnd				;exit to caller

	PAGE
;***
;B$SEEKSTART - seek to beginning of current file.
;
;Purpose:
;	Added as part of revision [12].
;	Seeks to beginning of file pointed to by b$PTRFIL.
;	Used to back up file ptr when a Binary load has
;	been detected.
;Entry:
;	b$PTRFIL - points to current fdb.
;Exit:
;	file ptr repositioned to beginning of current file.
;Uses:
;	Per convention.
;Exceptions:
;	Bad file number (from SeekToStart)
;****

cProc	B$SEEKSTART,<FAR,PUBLIC>,<SI>
cBegin
	FDB_PTR ES,SI,b$PTRFIL	;get FDB pointer
	DbAssertRel	SI,NE,0,DK_TEXT,<Invalid FDB ptr in B$SEEKSTART> 
	CALL	SeekToStart	; seek to start of file & check for errors
cEnd
	PAGE
;***
;B$BUFI, B$BUFO - Binary/Ascii Load/Save support
;
;Purpose:
; Added as part of revision [12].
; B$BUFI reads a block of data from the current file. B$BUFO writes a block
; of data to the current file. Requests for zero length reads/writes will be
; ignored. QB3 must call OPEN code to open file, followed by a call to B$CHAN
; to set the channel number. QB3 must also ensure that no heap movement occurs
; while B$BUFI and B$BUFO are active. QB3 is responsible for closing file
; (B$CLOS also clears b$PTRFIL) even if error occurs.
;
; NOTE: This routine can take a far pointer to a movable item in a heap. This
; routine cannot directly or indirectly cause heap movement.
;
;Entry:
;	b$PTRFIL - contains current FDB ptr.
;	stack parms:
;	fpData - far pointer to data buffer.
;	cbData - count of bytes to read/write.
;Exit:
;	CX = 0 if CbBytes couldn't be read by B$BUFI
;Uses:
;	Per convention.
;Exceptions:
;	None.
;Note: Possible speed optimizations
;	DosReadWrite currently CLEARS buffer before input. (could eliminate)
;
;****

cProc	B$BUFI,<FAR,PUBLIC>
cBegin	<nogen>
	XOR	AL,AL		;[AL]=I/O flag
	SKIP	2		;skip next instruction
cEnd	<nogen>

cProc	B$BUFO,<FAR,PUBLIC>
cBegin	<nogen>
	MOV	AL,PUTFLG	;[AL]=I/O flag
cEnd	<nogen> 		;fall into BufIOCommon

cProc	BufIOCommon,<FAR>,<ES,DI,SI>
parmD	fpData			;ptr to IO buffer
parmW	cbData			;count of bytes to read/write
cBegin
	CBW			;[AX] = I/O flag
	MOV	CX,cbData	;[CX] = count to read/write
	JCXZ	BufIOExit	;brif no data to read/write
	FDB_PTR ES,SI,b$PTRFIL	;get FDB pointer
	LES	DI,fpData	;[ES:DI] = fpData
	MOV	BX,CX		;[BX] = count of data to read/write
DbAssertRel	SI,NE,0,DK_TEXT,<Invalid fdb ptr in B$BUFI/B$BUFO>
	PUSH	AX		;save I/O type
	PUSH	BX		;save requested byte count
	CALL	DosReadWrite	;do block input
	POP	BX		;recover requested count of bytes
	JC	JMP_AnalyzeErr2	; exit if error (PSW.C set)
	CMP	AX,BX		;did we read 'em or writ 'em all
	POP	CX		;recover I/O type 0 for input.
	JC	BufError	;issue error
BufIOExit:
	INC	CX		;return CX=0 eof on read
cEnd

BufError:
	JCXZ	BufIEof 	;EOF if couldn't read all chars
	JMP	B$ERR_DFL	;Disk full if output
BufIEof:
	DEC	CX		;make CX = FFFF so incremented to 0 for EOF
	JMP	SHORT BufIOExit ;return with CX=0 for eof on read

;***
; B$FLUSH - Flush the sequential output buffer.  Moved here with [27].
;
;Purpose:
;	Flush a buffer if it contains any data.
;	No write is done unless buffer contains data
;	If bit FL_TRUNC of FD_FLAGS is set (set at open time for OUTPUT files),
;	a 0-length write is done before the buffer is flushed in order to set
;	the file size.
;
;Entry:
;	(ES:)[SI]   = *FDB
;
;Exit:
;	One buffer is flushed
;	FileDB.FD_BUFCNT = 0
;
;Uses:
;	CX
;Preserves:
;	AX,BX,DX
;
;******************************************************************************
cProc	B$FLUSH,<NEAR,PUBLIC>
cBegin

	XOR	CX,CX		; CX = 0
	TEST	FileDB.FD_FLAGS,FL_TRUNC ; truncate file at this time?
	JZ	NoTrunc		; brif not -- don't truncate file
	AND	FileDB.FD_FLAGS,NOT FL_TRUNC ; reset truncate flag
	CALL	B$FlushCount	; write 0 bytes to set file size
NoTrunc:

	XCHG	CX,FileDB.FD_BUFCNT ; clear count in FDB and get count in CX
	JCXZ	FlushExit	; if nothing in buffer, just return
cEnd	nogen			; fall into B$FlushCount


;***
;B$FlushCount - Flush n bytes of the sequential output buffer.
;
;Purpose:
;	Write a specified number of chars from the sequential file buffer
;	without checking for a zero buffer count.
;
;Entry:
;	(ES:)[SI]   = *FDB
;	CX = number of chars to write
;
;Exit:
;	One buffer is flushed
;	FileDB.FD_BUFCNT IS NOT CHANGED!
;
;Uses:
;	None
;Preserves:
;	All
;
;******************************************************************************
cProc	B$FlushCount,<NEAR,PUBLIC> ; Rename and make public
cBegin

	PUSH	AX		; save registers
	PUSH	BX
	PUSH	DX
	LEA	DX,FileDB.FD_BUFFER ; DX = sequential access buffer address
	MOV	BX,FileDB.FD_HANDLE ; BX = file descriptor
	CALLOS	write		;write it
	JB	JMP_AnalyzeErr2	;go if error
	CALL	B$CHK_WRITE	; check to see that we got all we requested
	POP	DX		; restore registers
	POP	BX
	POP	AX
FlushExit:
cEnd


JMP_AnalyzeErr2:		
	JMP	B$AnalyzeErr	; give appropriate error message
				; file forced close and FDB deallocated
				; if closing flag set.

;*** 
;B$CLOSE -- close a file
;
;Purpose:
;
;Entry:
;	[ES:]si = *FDB
;	BX = handle
;
;Exit:
;	File closed.
;
;Uses:
;	None
;
;Preserves:
;	All
;
;Exceptions:
;	All those generated by B$AnalyzeErr.
;
;******************************************************************************

cProc	B$CLOSE,<NEAR,PUBLIC>,<AX>
cBegin

	CALLOS	close,JMP_AnalyzeErr2,bx ; make sure we don't try to close
				; this file again if we have error

cEnd

sEnd	;DK_TEXT
	END

⌨️ 快捷键说明

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