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

📄 dvstmt.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;Exceptions:
;	illegal file number -- B$ERR_IFN
;	bad file mode -- B$ERR_BFM
;	bad record number -- B$ERR_BRN
;*******************************************************************************
cProc	B$PUT3,<PUBLIC,FAR>	
ParmW	Channel 		; I2 file number
ParmD	RecPtr			; far record pointer
ParmW	RecLen			; i2 record length
cBegin				
	MOV	AL,RecFlg+PutFlg; indicate this is PUT with record var
	JMP	SHORT RndIO3	; do it
cEnd	nogen			; exit via B$GET3

	SUBTTL	Relative random I/O interfaces -- B$GET4 & B$PUT4
	page
;***
;B$GET4 -- get the record with record number specified to record var
;void B$GET4(I2 Channel, I4 recnum, TYP far *recptr, I2 reclen)
;
;Purpose:
;	Get the record specified into user record
;
; 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:
;	Parameters in stack.
;	int		Channel
;	long int	RecNum
;	typ far 	*RecPtr
;	int		RecLen
;
;Exit:
;
;Note: while calling RndDsp,
;	[BX]	= file number (used by B$LHFDBLOC/B$LocateFDB)
;	[AL]	= GET + Relative flag (refer to RndDsp)
;	[CX|DX] = I4 specified record number
;	[SI]	= record length
;	[ES:DI] = Pointer to the users record
;
;Uses:
;	none
;
;Exceptions:
;	illegal file number -- B$ERR_IFN
;	bad file mode -- B$ERR_BFM
;	bad record number -- B$ERR_BRN
;*******************************************************************************
cProc	B$GET4,<PUBLIC,FAR>	
ParmW	Channel 		; I2 file number
ParmD	RecNum			; I4 record number
ParmD	RecPtr			; far record pointer
ParmW	RecLen			; I2 record length
cBegin

	MOV	AL,RelFlg+RecFlg; indicate GET with record number & var
RndIO4:
	MOV	CX,Seg_RecNum	; CX = RecNum high
	OR	CX,CX		; can't be negative number
	JS	ERCBRN		; Brif negative, give "bad record number"
	MOV	DX,Off_RecNum	; DX = RecNum low
	MOV	BX,CX		; another copy of RecNum high in BX
	OR	BX,DX		; can't be zero
	JZ	ERCBRN		; Brif zero, give "bad record number"
	MOV	BX,Channel	; BX has the channel number
	PUSH	SI		
	PUSH	DI		
	PUSH	ES		

	MOV	SI,RecLen	; [SI] = Record length
	LES	DI,RecPtr	; [ES:DI] = Record Pointer
	cCall	RndDsp		; do the work

	POP	ES		
	POP	DI		
	POP	SI		
cEnd				; exit to caller

;***
;B$PUT4 -- put a record with specified record number from record var
;void B$PUT4(I2 Channel, I4 RecNum, TYP far *recptr, I2 reclen)
;
;Purpose:
;	Put a record from record var with specified record number.
;
; 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:
;	Parmaters in stack.
;	int		Channel
;	long int	RecNum
;	typ far 	*RecPtr
;	int		RecLen
;
;Exit:
;
;Note: while calling RndDsp,
;	[BX]	= file number (used by B$LHFDBLOC/B$LocateFDB)
;	[AL]	= GET + Relative flag (refer to RndDsp)
;	[CX|DX] = I4 specified record number
;	[SI]	= record length
;	[ES:DI] = Pointer to the users record
;
;Uses:
;	none
;
;Exceptions:
;	illegal file number -- B$ERR_IFN
;	bad file mode -- B$ERR_BFM
;	bad record number -- B$ERR_BRN
;*******************************************************************************
cProc	B$PUT4,<PUBLIC,FAR>	
ParmW	Channel 		; I2 file number
ParmD	RecNum			; I4 record number
ParmD	RecPtr			; far record pointer
ParmW	RecLen			; I2 record length
cBegin				
	MOV	AL,RelFlg+PutFlg+RecFlg ; indicate PUT Rec Num & Rec Var
	JMP	SHORT RndIO4	; do it
cEnd	nogen			; exit via B$GET4

Locals	PROC	NEAR
	SUBTTL	B$FREF - Return next available file number
	PAGE
;***
; B$FREF - Return next available file number
; int pascal B$FREF(void)
;
;Purpose:
; Runtime entry point to return the next available file number. This is done
; by a pretty dumb repetative linear search of all FDBs, trying all file
; numbers starting at 1. Anything more intelligent is probably more effort
; than it's worth, since the call to FREEFILE will more often than not be
; followed by an OPEN call, which is probably I/O bound.
;
;Entry:
; None.
;
;Exit:
; [AX]	= Next available file number.
;
;Uses:
; Per convention.
;
;Exceptions:
; B$ERR_SSC, if the heap is screwed up.
;
;******************************************************************************
cProc	B$FREF,<FAR,PUBLIC,FORCEFRAME>,<SI> 
cBegin				

	XOR	AX,AX		; [AX] = potential "next" file number
FREF_5: 			; Loop to restart at beging of FDB chain
	XOR	SI,SI		; [SI] = Flag to get first FDB pointer
	INC	AX		; [AX] = next potential "next" filenumber
FREF_10:			; Loop for each FDB
	CALL	B$LHNXTFIL	; [SI] = pointer to next FDB
	JZ	FREF_90 	; Jump if no more FDB's (we're done)
	CALL	B$LHLOCFDB	; [BL] = filenumber associated with FDB
	CMP	AL,BL		; See if our "guess" is being used
	JNZ	FREF_10 	; loop to go check next FDB if not used
	JMP	FREF_5		; else loop to attempt a new guess
FREF_90:			; FDB chain end found, and guess not used

cEnd				

	SUBTTL	EOF interface -- B$FEOF
	page
;***
;B$FEOF -- function which detects the EOF for a file
;I2 B$FEOF(I2 Channel)
;
;Purpose:
;	Detect whether the EOF is reached.  This function is only significant
;	for  a input or communication file.
;
;	Note: EOF won't return true (-1) for a random file, even if you GET
;		a record beyond the file end.  However, that GET gets a null
;		record.
;
;Entry:
;	Parameter in stack.
;	int	Channel
;Exit:
;	[AX]	= -1	EOF is reached for a sequential input file, or
;			communication buffer is empty
;		= 0	EOF is not reached yet
;Uses:
;	none
;Exceptions:
;	illegal file number -- B$ERR_IFN
;*******************************************************************************

cProc	B$FEOF,<PUBLIC,FAR>
	ParmW	Channel 	;I2, file number
cBegin
	MOV	BX,Channel	;BX has file number

	OR	BX,BX		;special for standard input ?
	JZ	REDIR		;Brif yes
	MOV	AH,DV_EOF	;end of file function
	cCall	ComDsp		; do it, on return [AX] has the result

	JMP	SHORT EOFExit	;exit to caller
REDIR:
	TEST	b$IOFLAG,RED_INP ; is input file redirected ?
	JZ	ERCIFN		; Brif not, give "illegal file number"
	MOV	AX,C_IOCTL SHL 8 + InpSts ; get input status
	INT	21h		; is the end of a file ?
				;[AL] = 0FFH if not end of file
				;[AL] = 0    if end of file
	CBW			;result in AX
	NOT	AX		; and pervert
EOFExit:

cEnd				;clear stack and return

	SUBTTL	B$FATR - FILEATTR function
	PAGE
;***
; B$FATR - FILEATTR function
; I4 pascal B$FATR(I2 channel, I2 fieldid)
;
;Purpose:
; Returns specific information from an FDB, based on the fieldid value. This
; interface allows us to muck with the FDB, and still provide the same info
; to the user in a stable fasion.
;
;Entry:
; channel	= File number to be queried
; fieldid	= field number to be returned
;
;Exit:
; [DX:AX]	= requested information
;
;Uses:
; Per convention
;
;Exceptions:
; B$ERR_FC	= Bad field number
;
;******************************************************************************
cProc	B$FATR,<FAR,PUBLIC>,<SI> 
parmW	channel 		; file to futz with
parmW	fieldid 		; field desired
cBegin				

	MOV	BX,channel	; [BX] = File's channel #
	cCall	B$LHFDBLOC	; [SI] = FDB pointer (NZ if found)
	JNZ	FATR_3		; Jump if so
	JMP	B$ERR_IFN	; else bad file number

FATR_3: 			
	MOV	BX,fieldid	; [BX] = user requested field
	DEC	BX		; Make it zero-relative
	CMP	BX,FIELDID_MAX	; See if in range
	JB	FATR_5		; Jump if valid request
	JMP	B$ERR_FC	; Else illegal function call

FATR_5: 			
	ADD	BX,BX		; [BX] = word offset into table
	XOR	AX,AX		; Init I4 return value
	CWD			
	FDB_PTR ES,SI,SI	;(ES:)[SI] = * FDB
	ADD	SI,CS:[BX].FIELDOFF_TABLE ; FDB field by fun. (zero rel)
	JMP	CS:[BX].FIELDDISP_TABLE   ; Dispatches by fun. (zero rel)

FATR_TWO:			; Dispatch point for two byte fields
	LODS	WORD PTR FileDB ; Load FDB word
	JMP	SHORT FATR_90	

FATR_ONE:			; Dispatch point for one byte fields
	LODS	BYTE PTR FileDB ; Load FDB byte

FATR_90:			

cEnd				

ERCIFN: JMP	B$ERR_IFN	;illegal file number

	SUBTTL	general I/O supporting routines
	page
;***
;ComDsp -- common dispatch routine
;
;Purpose:
;	This common dispatch routine checks the legality of the channel
;	and then dispatch to the actual working routine.
;Entry:
;	[AH]		= fucntion number (minor #)
;	[BX]		= file number
;Exit:
;	depends on function
;Uses:
;	none
;Exceptions:
;	illegal file number -- B$ERR_IFN
;*******************************************************************************

cProc	ComDsp,<NEAR>,<SI>	;save SI

cBegin
	CALL	B$LHFDBLOC	;[SI] = file data block pointer
	JZ	ERCIFN		;Error - illegal file number
	CALL	B$PtrDispatch	; dispatch to the working routine
cEnd				;pop si and exit to caller

;***
;RndDsp -- dispatch for random I/O
;
;Purpose:
;	Check the legality of the file number and the file mode.  If both
;	OK, dispatch to the working routine.
;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]		= file number
;	[CX:DX] 	= record number if RelFlg is on. Note: use [CX|DX] here
;			  for the consistence with DOS function call
;	[ES:DI] 	= record variable address, if RecFlg is on
;	[SI]		= record variable length, if RecFlg is on
;
;
;Exit:
;	a record is in random buffer
;Uses:
;	none
;Exceptions:
;	illegal file number -- B$ERR_IFN
;	bad file mode -- B$ERR_BFM
;*******************************************************************************

cProc	VarStrLenDsp,<NEAR>,<SI,ES,DI>	
cBegin					
	jmp	VarStrLen_Entry 	
cEnd	<nogen> 			

cProc	RndDsp,<NEAR>,<SI,ES,DI> 
cBegin
	PUSH	SI		; preserve record length
	CALL	B$LHFDBLOC	;NZ & [SI]=*FDB if file number found
	POP	BX		; [BX] = length of record variable
	JZ	ERCIFN		;Brif not found, give "illegal file number"

	FDB_PTR ES,SI,SI	;(ES:)[SI] = *FDB
	TEST	FileDB.FD_MODE,MD_RND+MD_BIN ; random or binary?
	JNZ	RND_OR_BIN	
	JMP	ERCBFM		; brif not - bad file mode
RND_OR_BIN:
	TEST	AL,RecFlg	; See if record variable passed
	JNZ	RndDsp_5	; Jump if it was

	TEST	FileDB.FD_MODE,MD_BIN ; binary mode?
	JZ	NOT_BIN 	
	JMP	ERCRVR		; brif so -- record variable required
NOT_BIN:

	PUSH	DS		; Form...
	POP	ES		;   pointer in...
	LEA	DI,FileDB.FD_BUFFER ;[ES:DI] ptr to record (field buffer)
	MOV	BX,FileDB.FD_VRECL  ;[BX] = length of record (LEN= length)
	JMP	SHORT RndDsp_15 ; go finish dispatch

RndDsp_5:			; record variable was passed in
	OR	BX,BX		; 0-length read/write?
	JNZ	NotSD		; brif not -- not a string descriptor
				; A 0-length means that we have a string
				; descriptor and that we must dereference
				; ES:DI = string descriptor address


	TEST	FileDB.FD_MODE,MD_BIN ; binary mode?
	JNZ	NotVarLenStr	; brif so -- no special string handling


;	Special code to handle puts/gets from/into variable-length strings.
;	For random files, the length of the string will be placed in the file
;	before the string data.

	push	ax		; save flags
	push	cx		; save optional record #
	push	dx		

	mov	bx,2		; length to read/write
	or	al,VarStrLen	; don't increment record # after next op.
	test	AL,PutFlg	; PUT statement?
	jnz	PutStrLen	; brif so -- output length

				; GET statement
	;(othewise, ES should be equal to ds/ss)

	push	bx		; save '2'
	push	di		; save SD offset
	push	ax		; space for length on stack
	mov	di,sp		; ES:DI = addr of length word
	call	VarStrLenDsp	; read length of string into ES:DI
	pop	ax		; AX = length to read (new str length)
	pop	di		; DI = SD offset
	pop	bx		; BX = 2 (total # to read)

	FDB_PTR  ES,si,si	 ; restore (ES:)[SI] = *FDB for ChkRandom
	add	bx,ax		
	call	ChkRandom	; do verification

	push	ax		; save length
	cCall	B$STDL,<DI>	; deallocate existing string
	pop	cx		; restore CX = length

	jcxz	RestoreState	; brif zero-length string -- don't do ALLOC

	mov	bx,cx		; BX = new string length
	call	B$STALC 	; alloc string with new length, BX=*str data
	mov	[di],cx 	; set SD string length
	mov	[di+2],bx	; set SD string address
	mov	[bx-2],di	; set back pointer
	jmp	short RestoreState 

PutStrLen:			; PUT statement, DS:[DI] = str len (from SD)
	push	bx		; save '2'
	add	bx,[di] 	; bx = 2+string length

	call	ChkRandom	; do verification
	pop	bx		; restore bx = 2
	call	VarStrLenDsp	; write length of string to file


RestoreState:			
	pop	dx		; restore optional record #
	pop	cx		
	pop	ax		; restore flags
	or	al,VarStrData	; don't seek before next get/put

NotVarLenStr:			


	MOV	BX,ES:[DI]	; BX = string length
	MOV	DI,ES:[DI+2]	; DS:DI = string address
	PUSH	DS		; ES:DI = string address
	POP	ES		
	OR	BX,BX		; null string?
	JZ	RndExit 	; brif so -- return without doing anything
	FDB_PTR ES		;restore FDG SEG in ES

NotSD:				
	TEST	FileDB.FD_MODE,MD_BIN ; binary mode?
	JNZ	RndDsp_15	; brif so -- skip checks for bad record
				; length and field statement
VarStrLen_Entry:
	call	ChkRandom

RndDsp_15:			
	MOV	[b$RECPTR],DI	
	MOV	[b$RECPTR+2],ES ; [b$RECPTR] = record pointer
	MOV	AH,DV_RANDIO	;AH=function number (minor #)
	CALL	B$PtrDispatch	; dispatch to the working routine
RndExit:			
cEnd				;pop si, exit to caller


;*** 
;ChkRandom -- verify stuff before RANDOM file I/O
;
;Purpose:
;	Added with revision [43] to save code.
;
;Entry:
;	BX = length to read/write (includes count word for variable-length
;		strings as record variables).
;Exit:
;	None
;Uses:
;	None
;Preserves:
;	All
;Exceptions:
;	Bad record length, Field statement active
;
;******************************************************************************
cProc	ChkRandom,<NEAR>
cBegin
	CMP	BX,FileDB.FD_VRECL	; record too long?
	JA	ERCBRL			; brif so -- Bad record length
	TEST	FileDB.FD_FLAGS,FL_FIELD ; FIELD stmt active for this FDB?
	JNZ	ERCFSA			; brif so -- FIELD statement active
cEnd

ERCBRL: JMP	B$ERR_BRL
ERCFSA: JMP	B$ERR_FSA

; FIELDOFF_TABLE
;
; Table of FDB fields offsets that FILEATTR will return. Each entry contains
; the location within the FDB of the field to be returned.
;
; FIELDDISP_TABLE
; table of routine offsets to execute to fetch a particular field.
;
labelW	FIELDOFF_TABLE		
	DW	FD_MODE 	; 1: File Mode
	DW	FD_HANDLE	; 2: DOS file handle

labelW	FIELDDISP_TABLE 	
	DW	FATR_ONE	; 1: File Mode: one byte
	DW	FATR_TWO	; 2: DOS file handle: two byte

FIELDID_MAX	=	2		; last entry in table

Locals	ENDP

ERCBFM: JMP	B$ERR_BFM	;bad file mode
ERCRVR: JMP	B$ERR_RVR	;record variable required

sEnd	;DV_TEXT

	END

⌨️ 快捷键说明

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