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

📄 prnval.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	TITLE	PRNVAL - Print values
	page	56,132
;***
; PRNVAL - Print values
;
;	Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;
;	This module contains B$P<term><type> and B$PEOS interfaces.
;
;	The PRINT, WRITE, and LPRINT statements have a large number of
;	runtime calls that can be generated, based on the list of
;	expressions given. There is a unique preamble call for each such
;	statement (except PRINT), to correctly set up flags, vectors, etc.
;	The actual printing call itself is one of 15 possibilities, based
;	on the argument type, and one of three possible ways of terminating
;	the print: ',', ';', or EOL. Each of these 15 calls is in the
;	form B$P<term><type> where <term> specifies the print termination
;	method, and <type> specifies the type of the argument.
;
;	<term>:
;		C == ',' (i.e., something like 'PRINT X,' was specified)
;		S == ';'
;		E == EOL (neither ',' nor ';' was specified)
;
;	<type>:
;		I2 == two byte integer
;		I4 == four byte integer
;		R4 == single precision real
;		R8 == double precision real
;		SD == string
;
;	Thus, for example, a call to B$PER4 would be used to print a s.p.
;	value and terminate with a EOL.
;
;	The list of expressions can be of any size; for each additional
;	expression, another one of the fifteen possible runtime calls is
;	generated. After the last such expression, a call to B$PEOS is
;	generated (if not terminated with EOL). If no expression is
;	specified, a NULL string is printed, so 'PRINT' would generate a
;	call to B$PESD with a null string as the parameter (print a string,
;	terminate with EOL).
;
;******************************************************************************
	INCLUDE switch.inc
	INCLUDE rmacros.inc

;Code segments:
	useSeg	DK_TEXT 	;disk I/O
	useSeg	MT_TEXT 	;floating point math.
	useSeg	NH_TEXT 	;near heap
	useSeg	ER_TEXT 	;error handling
	useSeg	CN_TEXT 	;concole I/O

;Data segments:
	useSeg	CONST		;constant definitions
	useSeg	_DATA		;initialized variables
	useSeg	_BSS		;uninitialized variables

	INCLUDE seg.inc
	INCLUDE baslibma.inc
	INCLUDE devdef.inc
	INCLUDE files.inc
	INCLUDE rtps.inc	; constants shared with QBI
	INCLUDE idmac.inc

	SUBTTL	local constant definitions
	page

	CLMWID	EQU	14	;column width

	COMA	EQU	0	;comma
	SEMI	EQU	1	;semicolumn
	EOL	EQU	2	;forced EOL

	TTY	EQU	0	;default for b$PTRFIL is TTY

	PRSTM	EQU	0	;print statement
	CHANL	EQU	1	;#
	USING	EQU	2	;using
	WRSTM	EQU	4	;write statement
	LPSTM	EQU	8	;lprint statement

	InpDefault	EQU	0FFH ;default for b$Finput


	SUBTTL	data definitions
	page

sBegin	CONST
	labelW	TTYVEC		;vector for PRINT
	staticW ,B$TTY_GPOS	;cursor position
	staticW ,B$TTY_GWID	;line width
	staticW ,B$$TCR		;force EOL
	staticW ,B$TTY_SOUT	;write one character
	staticW ,B$TYPSTR	;write a string with BX=*sd
	staticW ,B$TYPCNT	;write a string with CX=length
	staticW ,B$OUTCNT	;write a string char. by char.
	staticW ,TTY_PRTCHK	; check if EOL needs to be forced
sEnd

sBegin	_DATA
	externB b$PRFG		;print flag, may be combined from below
				;0: PRINT stmt
				;1: # (channel)
				;2: USING
				;4: WRITE stmt
				;8: LPRINT stmt
				;e.g. 3 means PRINT # USING

	labelW	<PUBLIC,b$VECS> ; print value vectors
	staticW VPOS,B$TTY_GPOS		;cursor position
	staticW VWID,B$TTY_GWID		;line width
	staticW VWCLF,B$$TCR		;force EOL
	staticW VWCH,B$TTY_SOUT		;write one character
	staticW VTYP,B$TYPSTR		;BX=*sd
	staticW VTYPCNT,B$TYPCNT 	;BX=*sd, CX=length
	staticW VOUTCNT,B$OUTCNT 	;SI=point to string, CX=length
	staticW VPRTCHK,TTY_PRTCHK	; check if EOL needs to be forced
SizeOfVecs	EQU	(($-b$VECS)/2)	;length of b$VECS table in words
	globalB b$FInput,InpDefault	;Where is input comming from
	globalW b$GetOneVal,<DK_TEXTOFFSET NoGetValAssert> ; vector
					;to routine which INPUT will
					;will use to get next data
	globalW b$pGetValDefault,<DK_TEXTOFFSET NoGetValAssert> 
					;if no input statement is
					;present, attempts to call
					;indirect through b$GetOneVal
					;will die by assertion in
					;non-release runtimes.
	globalW b$pFLUSH,Near_Ret,1	;conditional vector for B$FLUSH
	externB b$CRTWIDTH 	; screen width
sEnd

sBegin	_BSS
	globalW b$PUSG,,1	;print using routine
EVEN				; for safety
	externW b$TempSD	; static string descriptor

	globalW b$StkBottom,,1	; used to clean the stack after TTY inp

	externW b$?TYP		; [b$VTYP|b$TTYP] (defined in global.inc)
	externB b$VTYP		; value type (defined in global.inc)
	externB b$TTYP		; terminator type (defined in global.inc)

	externW b$PTRFIL	; print channel #
	externW b$pSTDALCTMP	; indirect B$STDALCTMP vector

	externB b$LPTFDB 	; FDB for line printer
	externB b$Buf1		
sEnd

	SUBTTL	code externals
	page


sBegin	DK_TEXT
	externNP	B$CNTRL		; needed during B$WRIT
sEnd

sBegin	MT_TEXT
	externNP	B$FOUTBX
sEnd

sBegin	CN_TEXT
	externNP	B$TTY_GPOS	;cursor position
	externNP	B$TTY_GWID	;line width
	externNP	B$$TCR		;force EOL
	externNP	B$TTY_SOUT	;write one character
	externNP	B$TYPSTR 	;write a string with BX=*sd
	externNP	B$TYPCNT 	;write a string with CX=length
	externNP	B$OUTCNT 	;write a string char. by char.
sEnd

	assumes CS,DK_TEXT
sBegin	DK_TEXT


	SUBTTL	print interfaces -- B$P<term><type>(<param>)
	page
;***
; B$P<term><type>(<param>) -- print an item for :
;	PRINT, PRINT #, PRINT USING, PRINT # USING,
;	WRITE, WRITE #,
;	LPRINT, LPRINT USING.
;
;Purpose:
;	These are interfaces to the compiler.  Each entry point sets up
;	(1) types of value & terminator, and
;	(2) a pointer to that item,
;	 and then fall through PRINT, which performs actual printing job.
;
;	<term>, <type> & <param> may vary as follows:
;	<term>:
;		C:	Comma used as terminator
;		S:	Semi used as terminator
;		E:	End of statement used as terminator
;	<type>:
;		I2:	Two byte integer
;		I4:	Four byte integer
;		SD:	String (string descriptor)
;	<param>:
;		A parameter of type <type> to be printed.
;
;
;Entry:
;	Parameter was pushed in stack.
;	<type>	Val = Number if <type> is numerical type
;		    = String descriptor if <type> is string
;
;Exit:
;	through B$PRINT
;Uses:
;	none
;Exceptions:
;
;*******************************************************************************

;========================
;	Print I2,	|
;========================

cProc	B$PCI2,<PUBLIC,FAR>

cBegin	nogen			;no stack frame generated
	MOV	AX,COMA SHL 8 + VT_I2 ;AX=[terminator type | value type]
	JMP	SHORT B$PRINT	;print this item
cEnd	nogen			;no code generated

;========================
;	Print I2;	|
;========================

cProc	B$PSI2,<PUBLIC,FAR>

cBegin	nogen			;no stack frame generated
	MOV	AX,SEMI SHL 8 + VT_I2 ;AX=[terminator type | value type]
	JMP	SHORT B$PRINT	;print the item
cEnd	nogen			;no code generated

;========================
;	Print I2	|
;========================

cProc	B$PEI2,<PUBLIC,FAR>

cBegin	nogen			;no stack frame generated
	MOV	AX,EOL SHL 8 + VT_I2 ;AX=[terminator type | value type]
	JMP	SHORT B$PRINT	;print the item
cEnd	nogen			;no code generated

;========================
;	Print I4,	|
;========================
cProc	B$PCI4,<PUBLIC,FAR>

cBegin	nogen			;no stack frame generated
	MOV	AX,COMA SHL 8 + VT_I4 ;AX=[terminator type | value type]
	JMP	SHORT B$PRINT	;print the item
cEnd	nogen			;no code generated

;========================
;	Print I4;	|
;========================
cProc	B$PSI4,<PUBLIC,FAR>

cBegin	nogen			;no stack frame generated
	MOV	AX,SEMI SHL 8 + VT_I4 ;AX=[terminator type | value type]
	JMP	SHORT B$PRINT	;print the item
cEnd	nogen			;no code generated

;========================
;	Print I4	|
;========================
cProc	B$PEI4,<PUBLIC,FAR>

cBegin	nogen			;no stack frame generated
	MOV	AX,EOL SHL 8 + VT_I4 ;AX=[terminator type | value type]
	JMP	SHORT B$PRINT	;print the item
cEnd	nogen			;no code generated

;========================
;	Print a$,	|
;========================

cProc	B$PCSD,<PUBLIC,FAR>

cBegin	nogen			;no stack frame generated
	MOV	AX,COMA SHL 8 + VT_SD ;AX=[terminator type | value type]
	JMP	SHORT B$PRINT	;print the item
cEnd	nogen			;no code generated

;========================
;	Print a$;	|
;========================

cProc	B$PSSD,<PUBLIC,FAR>

cBegin	nogen			;no stack frame generated
	MOV	AX,SEMI SHL 8 + VT_SD ;AX=[terminator type | value type]
	JMP	SHORT B$PRINT	;print the item
cEnd	nogen			;no code generated

;========================
;	Print a$	|
;========================

cProc	B$PESD,<PUBLIC,FAR>

cBegin	nogen			;no stack frame generated
	MOV	AX,EOL SHL 8 + VT_SD ;AX=[terminator type | value type]
cEnd	nogen			;no code generated

	SUBTTL	actual routine to print an item
	page
;***
;B$PRINT - continue the print interfaces to print an item
;
;Purpose:
;	Print an item for PRINT/WRITE/LPRINT statement.
;
;	Printing an item is affected by:
;	(1) whether it's a 'print using'
;	(2) whether it prints a string (numbers need to be translated)
;	(3) whether it is a print stmt or is a write stmt.
;		In case of write stmt, the following are different:
;		(a) no leading blank for a positive number if '+' omitted
;		(b) no ending space for a number
;		(c) string delimited by '"'
;		(d) comma delimiting items
;
;	One major difference here is that numbers also use the string output
;	routine to print on a device.  The string output routine outputs one
;	string a time, if it fits the rest of the line, which is faster than
;	iteratively outputs one character a time.
;
;	Certainly, one piece of code, which serves such many functions, can't
;	be as clean as some simple routines do.  However, there still has its
;	logic as follows:
;
;	B$PRINT (TerminatorType_&_ValueType)
;	{
;	    if channel on, test the mode is not input
;		if error then give "bad file mode"
;	    get pointer of the item to be printed from stack
;	    set up types
;
;	    /* print the item */
;
;	    if the request was PRINT USING, then
;		call print using routine
;	    else	/* not a PRINT USING */
;		if the request was printing a number, then
;		    translate the number into digital string
;		    if the request was a WRITE statement, then
;			special process the leading & ending space
;		else	/* printing a string */
;		    if the request was a WRITE statement, then
;			special process the string delimitor
;		print the string
;
;	    /* process the terminator */
;
;	    if the terminator was a EOL, then force a carrage return
;	    if the terminator was a COMMA, then fill the rest of the column
;		with blanks
;	    if the terminator was a SEMI-COLUMN and the request was a WRITE
;		statement, then print a ','
;
;	    /* handle the exit process explicitly */
;
;	    play around with BP and SP
;
;	    /*	When exit the stack looks like :	*/
;	    /*			__________________	*/
;	    /*			|	SI	 |	*/
;	    /*			|----------------|	*/
;	    /*			|  DS (if ?WIN)  |	*/
;	    /*		  BP -->|----------------|	*/
;	    /*			|	BP	 |	*/
;	    /*			|----------------|	*/
;	    /*			|    Ret offset  |	*/
;	    /*			|----------------|	*/
;	    /*			|    Ret segment |	*/
;	    /*		 Val -->|----------------|	*/
;	    /*			|    Parameter	 |	*/
;	    /*	(variable len)	\................\ 	*/
;	    /*			\................\ 	*/
;	    /*	      old SP -->|----------------|	*/
;	    /*			|________________|	*/
;	    /*						*/
;	}
;Entry:
;	[AH] = [terminator type]
;	[AL] = [value type]
;	in stack,
;	Val = first word of item, where item is either I2,I4,R4,R8 or sd/psd
;Exit:
;	none
;Uses:
;	none
;Exceptions:
;	bad file mode
;	I/O error or Disk full error when flush the buffer if a EOL encountered
;*******************************************************************************

				;NOTE!: This routine has a manually
				;generated epilogue due to variable number
				;of parameters.  If you change the prologue,
				;here you must also change the epilogue
				;further down.

cProc	B$PRINT,<PUBLIC,FAR>,<SI> ;common routine, has to be declared
				; as FAR for setting up stack frame correctly.
				; SI saved
	ParmW	Val		;dummy parameter, which points to the first
				; byte of the actual parameter regardless how
				; many bytes it is;  this also forces to set
				; up the stack frame
cBegin				;stack frame is set up and SI is saved
	MOV	[b$?TYP],AX	;set up b$VTYP & b$TTYP
	LEA	BX,Val		;get the address of parameter

	CMP	AL,VT_SD	; is this a string parm?
	JNZ	ChkString	; brif not - BX has the pointer to the value
	MOV	BX,[BX] 	; if SD, BX has the value, not pointer
ChkString:

	TEST	[b$PRFG],USING	;is print using on ?
	JNZ	PRTUSG		;Brif yes
	CMP	AL,VT_SD	;printing a string ?
	JZ	PRTSTR		;Brif yes

;[2] At this moment, [BX]=*I2,*I4,*R4 or *R8. 
;	Currently B$FOUTBX changes all registers except BP.  This has to be
;	changed later on.

	CALL	B$FOUTBX	; Hopefully, the return from B$FOUTBX
				;  are BX containing the address of the
				;	string and AX is the length
	MOV	SI,BX		; SI=*Number
	TEST	[b$PRFG],WRSTM	;is write statement on ?
	JNZ	WRTVAL		;Brif is write stmt
	ADD	BX,AX		;bx points to the terminate byte (00)
	INC	AX		;increment the length of the digital string
	MOV	BYTE PTR [BX]," " ;Number always followed by " "
				;Note:	the static buffer for translating a
				;	number must at least one byte longer
				;	than the maximum possible length.
	cCall	MAKESD		;[BX]=*sd on return
PRTIT1: 			;at this entry, check whether a EOL is needed
	PUSH	BX		;save psd
	cCall	[VPRTCHK]	; CY if room is not enough (possibly a EOL
				; was already forced), needs AX=len of string
	POP	BX		;get back psd
PRTIT2: 			;at this entry, no check for EOL (write)
	PUSH	BX		; save psd
	CALL	[VTYP]		;print the string, needs [BX]=psd
	POP	BX		; get back psd
	CALL	[b$pSTDALCTMP]	; deallocate the temp if it is
PRTEND:
	MOV	AL,[b$TTYP]	; get delimiter type
	CBW			; extend to use word ops
	DEC	AX		; test for EOL delimiter
	JG	PRTCLF		; Brif end with LF-CR
	TEST	[b$PRFG],WRSTM	;is write stmt on ?
	JZ	PRTEND2 	; Brif not
	MOV	AL,","		; here if comma or semi and write stmt
	CALL	[VWCH]		;write the character
	JMP	SHORT PRINTX	;exit to caller

WRTVAL: 			;write stmt take off the leading " "
	CMP	BYTE PTR [BX]," " ;is first a blank ?
	JNZ	WTMKSD		;Brif not, go make sd & print it

⌨️ 快捷键说明

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