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

📄 gwcom.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 4 页
字号:
CSWAIT:
	CALL	GetComUnitID	;[AL]=Com Unit ID(DI)
	MOV	AH,AL		;[AH]=Com Unit ID(DI)
	CALL	B$RECCOM 	;[AL]=input byte (if data is ready)
	PUSHF
	CALL	CKCMER		;check for Com Error
	POPF
	JNZ	CSGOT1		;wait if none ready to be read
	CALL	B$BREAK_CHK	;allow ^Break to break in
	JMP	SHORT CSWAIT
CSGOT1:
	PUSH	AX		;save registers...
	PUSH	DI
	CALL	GetComDCB	;get DCB in DI
	DEC	[DI].CD_CMEVT	;one less char in input queue
	POP	DI		;restore registers
	POP	AX
	CMP	AL,EOFCHR 	;check for CTL-Z
	JNE	CMNEOF		;branch if not
	TEST	[SI].FD_FLAGS,FL_BIN ; binary file?
	JNZ	CMNEOF		;CTL-Z is not EOF for Binary files
	STC			;CTL-z is EOF for ASCII files
	AND	[SI].FD_FLAGS,NOT FL_NEOF ;flag as eof
	JMP	SHORT CMSINX	;restore registers and exit
CMNEOF:
	CLC			;clear carry (no eof)
CMSINX:
	RET

;COM_SOUT - Sequential Output.
; Entry - SI points to File-Data-Block.
;	  [DI] = device offset (2=COMD, 4=SCRN, etc.)
;	  [AL] = byte to be output.
; Exit	- SI, DI can be changed.
;	  All other registers preserved
;	  This routine keeps track of column position,
;	  expands tabs, and forces a carriage return when line width
;	  is exceeded.


COM_SOUT:
	PUSH	AX
	CALL	GetComDCB	;DI points to COMx DCB
	POP	AX
	TEST	[DI].CD_CMFLG,CF_CMCOD ;did user explicity specifiy BIN/ASC?
	JZ	NOTBIN		;No
	TEST	[SI].FD_FLAGS,FL_BIN
	JNZ	CMROUT		;if binary, branch to Raw-Output routine
NOTBIN:
	PUSH	DX		;NOT binary
	MOV	DL,[SI].FD_WIDTH ;[DL]=device width (from FDB)
	MOV	DH,[DI].CD_CMPOS ;[DH]=current column (from DCB)
	CALL	XTABCR		;Expand tabs, force CR, do output, etc.
	MOV	[DI].CD_CMPOS,DH ;save new column position
	POP	DX
RET11:
	RET


;CLRCRF - Clear <CR> flag and output character
;CMROUT - Raw output routine
; Exit	- All registers preserved

CLRCRF:
	AND	[DI].CD_CMFLG,NOT CF_CMCRF ;clear CR flag

CMROUT: 			;output character/raw output routine
	MOV	AH,[DI].CD_DEVID ;[AH]=device ID
	CALL	B$SNDCOM 	;output [AL] to COM
	JMP	CKCMER		;check for successful transmit and rtn

;XTABCR     expand tabs,force <CR> if EOL
;entry->    [AL] = Char to be output
;	    [DX] = [current column,file width]
;	    [DI] = device offset
;exit ->    [DH] = new column
;	    all other regesters preserved


XTABCR:
	INC	DH		; send character and then check
				;if beyond width specified
	CMP	AL,ASCSP 	;Is it printable
	JB	OTHERS		;No  - start checking alternatives
	CALL	CLRCRF		;Yes - print it
	CMP	DH,DL		;Are we in range?
	JB	INRANG		;YES
	CMP	DL,0FFh 	;NO, but do we care?
	JE	INRANG		;We dont care so pretend were in range
	MOV	AL,ASCCR 	;	  and print a
	CALL	TRYCR		;     carriage return
	AND	[DI].CD_CMFLG,NOT CF_CMCRF ;clear CR flag
INRANG:
	RET
OTHERS:
	DEC	DH
TRYTAB:
	CMP	AL,ASCHT 	;is it a tab
	JNE	TRYCR		;no so try <CR>
	TEST	[DI].CD_CMFLG,CF_CMCOD ;test if IBM mode
	JZ	CMROUT		;if so, just output tab
	MOV	AL,ASCSP 	;expand to spaces
MORSPC:
	CALL	XTABCR
	TEST	DH,7		;Are we on a multiple of 8?
	JNZ	MORSPC		;Nope, try again
	MOV	AL,ASCHT 	;Restore AL
	RET			;and return
TRYCR:
	CMP	AL,ASCCR 	;is it a <CR>?
	JNE	TRYLF		;No  - see if its a line feed
	CALL	CMROUT		;Yes - put it out
	XOR	DH,DH		;      and update pos.
	TEST	[DI].CD_CMFLG,CF_CMCLF ;  add an <LF>?
	JZ	SETCRF		;      no
	MOV	AL,ASCLF	;	   yes, so put one out
	CALL	CMROUT
	MOV	AL,ASCCR	;	   restore AL
SETCRF:
	OR	[DI].CD_CMFLG,CF_CMCRF ;set CR flag
	RET

TRYLF:
	CMP	AL, ASCLF	;Is it an <LF>
	JNE	TRYBS		;No - try a <BS>
	TEST	[DI].CD_CMFLG,CF_CMCRF ;look to see this follows CR
	JZ	CMROUT		;not preceded by a <CR>
	AND	[DI].CD_CMFLG,NOT CF_CMCRF ;pred by CR - ignore LF, clear flag
	TEST	[DI].CD_CMFLG,CF_CMCOD ;test if IBM mode
	JZ	CMROUT		;if so, no LF suppression
	RET			;   and return

TRYBS:
	CMP	AL,ASCBS 	;is it a <BS>
	JNE	CLRCRF		;no - write it out
	DEC	DH		;back up pos
	JNC	CLRCRF		;send it out unless pos backed up past 0
	INC	DH
	JMP	CLRCRF


;COM_GPOS - return current file position.
; Entry - SI points to File-Data-Block.
;	  [DI] = device offset (2=COMD, 4=SCRN, etc.)
; Exit	- [AH] = current file column. (0-relative)
;	  All other registers preserved

COM_GPOS:
	PUSH	AX		;save contents of AL
	CALL	GetComDCB	;DI points to Device Control Block
	POP	AX		;restore contents of AL
	MOV	AH,[DI].CD_CMPOS
	RET

;COM_GWID - get device width
; Entry - SI points to File-Data-Block.
;	  [DI] = device offset (2=COMD, 4=SCRN, etc.)
; Exit	- [AH] = device width as set by xxxSWD

COM_GWID:
	MOV	AH,[SI].FD_WIDTH ;get current width
	RET

;COM_SCW - set device comma width	****Apparently not used by Bascom****
; Entry - [BX] = new device comma width
;	  SI points to File-Data-Block.
;	  [DI] = device offset (2=COMD, 4=SCRN, etc.)
; Exit	- SI, DI can be changed.
;	  All other registers preserved
;
;COM_SCW:
;	 RET

;COM_GCW - get device comma width	****Apparantly not used by Bascom****
; Entry - SI points to File-Data-Block.
;	  [DI] = device offset (2=COMD, 4=SCRN, etc.)
; Exit	- [BX] = device comma width as set by xxxSCW
;	  All other registers preserved
;
;COM_GCW:
;	RET

;**	com_blkin - block input
;**	com_blkout  - block output			--DMA support for BLOAD
;	NOT IMPLEMENTED

;	Entry	[bx] =	offset of destination
;		[cx] =	maximum number of bytes to read
;		[dx] =	DS of destination
;		[di] =	device number
;		[si] -> FDB of file to be loaded
;	exit	?      (This routine is provided to allow the user
;			to trash himself beyond all recognition!
;	Exit	[bx] =	1 past last byte read
;		CF	set if EOF encountered
;	Uses	AX
com_blkin equ	B$ERR_FC
com_blkout equ	B$ERR_FC

;***
; GetComDCB - get pointer to COM Device Control Block
;
; Purpose:
;	To compute the offset the device control block (DCB) of
;	the communications device ID given.  The number of the
;	device is also given (0-relative).
; Entry:
;	DI = -2 * device ID (positive value)
; Exit:
;	DI = offset to the device control block
;	AX = 0 for COM1, 1 for COM2, ...
; Modifies:
;	None.
; Exceptions:
;	None.
;*****************************************************************************

GetComDCB:
	CALL	GetComUnitId	;[AX]=unit id (0..n)

	MOV	DI,OFFSET DGROUP:B$CM1DCB ;assume COM1: first
	OR	AX,AX		;test if really first device
	JZ	GetComDCBDone	;if so, then jump
	ADD	DI,SIZE COMDCB	;add to get start of DCB for COM2:
GetComDCBDone:
	RET

;***
; GetComUnitID - get communications unit ID
;
; Purpose:
;	To get the zero-relative unit identification number from
;	the device ID.
; Entry:
;	DI = -2 * device ID (positive number)
; Exit:
;	AX = 0 for COM1:, 1 for COM2:,...
; Modifies:
;	None.
; Exceptions:
;	None.
;***************************************************************************

GetComUnitID:
	MOV	AX,DI
	ADD	AX,2*DN_COM1
	SHR	AX,1		;[AX]=0, 1. for COM1, COM2, ...
ERRRET:
	RET

; Check for COM I/O error and output COM Error Message if error occured.
; Entry - [AH] = non-zero if error occured

CKCMER:
	OR	AH,AH
	JZ	ERRRET		;branch if no COM I/O error detected
	MOV	BL,AH
	XOR	BH,BH		;[BX]=error code 1..n
	MOV	DI,OFFSET DGROUP:CMERRT ;DI has dipatch table for error routines
	CMP	BL,5
	JBE	ERROK
	XOR	BX,BX		;use default error
ERROK:
	SHL	BX,1		;convert error to word offset
	JMP	[DI+BX] 	;Handle error

;***
;B$CommSave - Save communications state
;
;Purpose:
;	This routine will be called whenever a process is going to
;	be shelled.   The communications ports, if opened, are
;	disabled, but their DCB's and opened status are kept for
;	subsequent reopening in B$CommRestore.  Note that
;	interrupt handlers will not have to be terminated.
;
;	This is a DOS only routine.
;
;Entry:
;	None.
;
;Exit:
;	None.
;
;Uses:
;	Per Convention
;
;Preserves:
;	AX, BX, CX, DX
;
;Exceptions:
;	None.
;********************************************************************

cProc	B$CommSave,<PUBLIC,NEAR>,<AX,BX,CX,DX,SI,DI> 
cBegin				

DbAssertRelB	<[b$COFlag]>,E,0,DV_TEXT,<b$COFlag non-zero in B$CommSave> ;
	MOV	CX,b$ComPort	;get value of I/O port for COM1
	MOV	COMSAV,CX	;put into save area
	JCXZ	NoActCOM1	;if no active COM1, then jump

	MOV	DI,OFFSET DGROUP:b$COM_DCB ;get offset to COM1 DCB
; CX must be non-zero so DTR and RTS are unaffected (DOS 3 only)
	MOV	AH,0		; AH = 0 indicates COM1
	CALL	B$TRMCOM	;[3]terminate COM1 device
	CALL	B$ComDealloc	;and dellocate the COM1 buffer
NoActCOM1:			

	MOV	CX,b$ComPort+2	;get value of I/O port for COM2
	MOV	COMSAV+2,CX	;put into save area
	JCXZ	NoActCOM2	;if no active COM2, then jump

	MOV	DI,OFFSET DGROUP:b$COM_DCB+SIZE COMDCB ;offset to COM2 DCB
; CX must be non-zero so DTR and RTS are unaffected (DOS 3 only)
	MOV	AH,1		; AH = 1 indicates COM2
	CALL	B$TRMCOM	;[3]terminate COM2 device
	CALL	B$ComDealloc	;and dellocate the COM2 buffer
NoActCOM2:			
cEnd				

;***
;B$CommRestore - Restore communications state
;
;Purpose:
;	This routine will be called when a shelled process returns.
;	The communications ports disabled in B$CommSave are
;	reopened with their preSHELL values.  Note that interrupt
;	handlers will not have to be restarted.
;
;	This is a DOS only routine.
;
;Entry:
;	None.
;
;Exit:
;	None.
;
;Uses:
;	Per Convention
;
;Preserves:
;	AX, BX, CX, DX
;
;Exceptions:
;	None.
;********************************************************************

cProc	B$CommRestore,<PUBLIC,NEAR>,<AX,BX,CX,DX,SI,DI> 
cBegin				

DbAssertRelB	<[b$COFlag]>,E,0,DV_TEXT,<b$COFlag non-zero in B$CommRestore> ;
	MOV	CX,COMSAV	;get saved I/O port for COM1
	JCXZ	NoRestCOM1	;if none, the skip over restore

	MOV	DI,OFFSET DGROUP:b$COM_DCB ;get offset to COM1 DCB
	CALL	B$ComAlloc	;allocate the COM1 buffer
	MOV	BX,DI		;move DCB address to BX
	CALL	B$INICOM	;[3]initialize COM1 device
NoRestCOM1:			

	MOV	CX,COMSAV+2	;get saved I/O port for COM2
	JCXZ	NoRestCOM2	;if none, then skip over restore

	MOV	DI,OFFSET DGROUP:b$COM_DCB+SIZE COMDCB ;offset to COM2 DCB
	CALL	B$ComAlloc	;allocate the COM2 buffer
	MOV	BX,DI		;move DCB address to BX
	CALL	B$INICOM	;[3]initialize COM2 device
NoRestCOM2:			

cEnd				

sEnd	DV_TEXT 		

	END

⌨️ 快捷键说明

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