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

📄 prtu.asm

📁 Microsoft MS-DOS6.0 完整源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:

BGSTRF:
	;MOV	BP,CX		;SAVE THE "USING" STRING CHARACTER COUNT
				;can't use BP, but we exhaust all registers
				; we have to use another way to solve it
	MOV	DI,SI		;SAVE THE POINTER INTO THE "USING" STRING
	MOV	BX,2		;THE \\ STRING FIELD HAS 2 PLUS
				;NUMBER OF ENCLOSED SPACES WIDTH

;There does not have to be a test for KANJI characters in this loop, as
;We know that we are not in the middle of one, and no KANJI can start with
;either a CSTRNG or a SPACE

LPSTRF:
	LODSB			;GET THE NEXT CHARACTER
	CMP	AL,CSTRNG	;THE FIELD TERMINATOR?
	JZ	ISSTRF		;GO EVALUATE A STRING AND PRINT
	INC	BX		;INCREMENT THE FIELD WIDTH
	CMP	AL," "		;A FIELD EXTENDER?
	LOOPZ	LPSTRF		;KEEP SCANNING FOR THE FIELD TERMINATOR

;-------------------------------
; Since  string field wasn't found, the "using" string character count and the
; pointer into it's data must be restored and the "\" printed.
;
; The way to restore CX has to pay a little bit attention, since we can't
; use BP as tempopary saving register.	Note that the SI incremented by one
; and CX decrement by one in the LPSTRF loop, if we don't find the string
; field.  So that, when enter NOSTRF, the amount of SI's increment is equal
; to the amoutn of the CX's decrement.  We may then restore CX using this
; calculation.	How lucky we are !
;-------------------------------

NOSTRF:
	SUB	SI,DI		;calculate the bytes we have scaned, put in SI
	ADD	CX,SI		;restore the count in CX
	MOV	SI,DI		;RESTORE THE POINTER INTO "USING" STRING'S DATA
	;MOV	CX,BP		; can't use BP
	MOV	AL,CSTRNG	;RESTORE THE CHARACTER

;-------------------------------
; Here to print the character in [al] since it wasn't part of any field.
;-------------------------------

NEWUCH: cCall	PLSPRT		;IF A "+" CAME BEFORE THIS CHARACTER
				;MAKE SURE IT GETS PRINTED
	CALL	[VWCH]		;Print the char that wasn't part of a field
;-------------------------------
; Scan one value field from USING string, and set up print using flags.
; On entry:
;	[SI]	= Points to next byte in PRINT USING string
;	[CX]	= Count of characters left in PRINT USING string
;	[DH]	= Flag byte used by B$PUFOUT (stored in b$PUFLG - see above)
;	[BH]	= Number of digits to left of decimal point (numbers only)
;	[BL]	= Number of digits to right of decimal point (numbers only)
;	[BX]	= Length of string field (strings only)
;-------------------------------

PRCCHR: XOR	AL,AL		;SET [DH]=0 SO IF WE DISPATCH
	MOV	DH,AL		;DON'T PRINT "+" TWICE
PLSFIN: cCall	PLSPRT		;ALLOW FOR MULTIPLE PLUSES IN A ROW
	MOV	DH,AL		;SET "+" FLAG
	LODSB			;GET A NEW CHARACTER

	CMP	AL,"!"		;CHECK FOR A SINGLE CHARACTER
	MOV	BX,1		;Set string length to 1
	JZ	ISSTRF		;STRING FIELD
	CMP	AL,"#"		;CHECK FOR THE START OF A NUMERIC FIELD
	JZ	NUMNUM		;GO SCAN IT
	CMP	AL,VSTRNG	;See if variable string field
	JZ	VARSTR		;GO PRINT ENTIRE STRING
	DEC	CX		;ALL THE OTHER POSSIBILITIES
				;REQUIRE AT LEAST 2 CHARACTERS
	JZ	REUSIN		;IF THE VALUE LIST IS NOT EXHAUSTED
				;GO REUSE "USING" STRING
	CMP	AL,"+"		;A LEADING "+" ?
	MOV	AL,PLUS 	;SETUP [DH] WITH THE PLUS-FLAG ON IN
	JZ	PLSFIN		;CASE A NUMERIC FIELD STARTS
	MOV	AL,[SI-1]	;GET BACK THE CURRENT CHARACTER
	CMP	AL,"."		;NUMERIC FIELD WITH TRAILING DIGITS
	JZ	DOTNUM		;IF SO GO SCAN WITH [BH]=
				;NUMBER OF DIGITS BEFORE THE "."=0
	CMP	AL,"_"		;CHECK FOR LITERAL CHARACTER DECLARATION
	JZ	LITCHR
	CMP	AL,CSTRNG	;CHECK FOR A BIG STRING FIELD STARTER
	JZ	BGSTRF		;GO SEE IF IT REALLY IS A STRING FIELD
	CMP	AL,[SI] 	;SEE IF THE NEXT CHARACTER MATCHES THE
				;CURRENT ONE
	JNZ	NEWUCH		;IF NOT, CAN'T HAVE $$ OR ** SO ALL THE
				;POSSIBILITIES ARE EXHAUSTED
	CMP	AL,CURNCY	;IS IT $$ ?
	JZ	DOLRNM		;GO SET UP THE FLAG BIT
	CMP	AL,"*"		;IS IT ** ?
	JNZ	NEWUCH		;IF NOT, ITS NOT PART
				;OF A FIELD SINCE ALL THE POSSIBILITIES
				;HAVE BEEN TRIED
	OR	DH,STAR 	;Set "*" bit
	INC	SI
	CMP	CX,2		;SEE IF THE "USING" STRING IS LONG
				;ENOUGH FOR THE SPECIAL CASE OF
	JC	SPCNUM		; **$
	MOV	AL,[SI]
	CMP	AL,CURNCY	;IS THE NEXT CHARACTER $ ?
	JNZ	SPCNUM		;IF IT NOT THE SPECIAL CASE, DON'T
				;SET THE DOLLAR SIGN FLAG
	DEC	CX		;DECREMENT THE "USING" STRING CHARACTER COUNT
				;TO TAKE THE $ INTO CONSIDERATION
	INC	BH		;INCREMENT THE FIELD WIDTH FOR THE
				;FLOATING DOLLAR SIGN
DOLRNM:
	OR	DH,DOLLAR	;SET BIT FOR FLOATING DOLLAR SIGN FLAG
	INC	SI		;POINT BEYOND THE SPECIAL CHARACTERS
SPCNUM: INC	BH		;SINCE TWO CHARACTERS SPECIFY
				;THE FIELD SIZE, INITIALIZE [BH]=1
NUMNUM: INC	BH		;INCREMENT THE NUMBER OF DIGITS BEFORE
				;THE DECIMAL POINT
	MOV	BL,0		;SET THE NUMBER OF DIGITS AFTER
				;THE DECIMAL POINT = 0
	DEC	CX		;SEE IF THERE ARE MORE CHARACTERS
	JZ	NOTSCI		;IF NOT, WE ARE DONE SCANNING THIS
				;NUMERIC FIELD
	LODSB			;GET THE NEW CHARACTER
	CMP	AL,"."		;DO WE HAVE TRAILING DIGITS?
	JZ	AFTDOT		;IF SO, USE SPECIAL SCAN LOOP
	CMP	AL,"#"		;MORE LEADING DIGITS ?
	JZ	NUMNUM		;INCREMENT THE COUNT AND KEEP SCANNING
	CMP	AL,","		;DOES HE WANT A COMMA
				;EVERY THREE DIGITS?
	JNZ	FINNUM		;NO MORE LEADING DIGITS, CHECK FOR ^^^
	OR	DH,COMMA	;TURN ON THE COMMA BIT
	JMP	NUMNUM		;GO SCAN SOME MORE

;-------------------------------
; Here when a "." is seen in the "using" string.  It starts a numeric field
; if and only if it is followed by a "#".  Once again, we do not have to
; test for KANJI characters because "#" and "^" can not be a legal first
; character for a double byte character.
;-------------------------------

DOTNUM:
	MOV	AL,[SI] 	;GET THE CHARACTER THAT FOLLOWS
	CMP	AL,"#"		;IS THIS A NUMERIC FIELD?
	MOV	AL,"."		;IF NOT, GO BACK AND PRINT "."
	JZ	DOTNU1		;[RDK]
	JMP	NEWUCH		;[RDK]cannot reach by short jump
DOTNU1: 			;[RDK]
	MOV	BL,1		;INITIALIZE THE NUMBER OF
				;DIGITS AFTER THE DECIMAL POINT
	INC	SI
AFTDOT: INC	BL		;INCREMENT THE NUMBER OF DIGITS
				;AFTER THE DECIMAL POINT
	DEC	CX		;SEE IF THE "USING" STRING HAS MORE
	JZ	NOTSCI		;CHARACTERS, AND IF NOT, STOP SCANNING
	LODSB			;GET THE NEXT CHARACTER
	CMP	AL,"#"		;MORE DIGITS AFTER THE DECIMAL POINT?
	JZ	AFTDOT		;IF SO, INCREMENT THE COUNT AND KEEP
				;SCANNING

;-------------------------------
; Check for the "^^^^" that indicates scientific notation.
;-------------------------------

FINNUM:
	DEC	SI		;Point back to current character
	CMP	WORD PTR [SI],"^^" ;Two "^"s in a row?
	JNZ	NOTSCI
	CMP	WORD PTR [SI+2],"^^" ;Four "^"s in a row?
	JNZ	NOTSCI
	CMP	CX,4		;WERE THERE ENOUGH CHARACTERS FOR "^^^^"?
	JC	PUSCAX
	SUB	CX,4
	ADD	SI,4
	INC	DH		;TURN ON THE SCIENTIFIC NOTATION FLAG

	JCXZ	NOTSCI		; jump if no more using to look at
	CMP	BYTE PTR [SI],"^" ; check for 5th "^"
	JNZ	NOTSCI		; no need to play games
	INC	SI		; eat the character
	DEC	CX		
	MOV	[b$PUFLG+1],BIGSCI ; Indicate 3 digit scientific

NOTSCI:
	INC	BH		;INCLUDE LEADING "+" IN NUMBER OF DIGITS
	TEST	DH,PLUS 	;DON'T CHECK FOR A TRAILING SIGN
	JNZ	ENDNUM		;ALL DONE WITH THE FIELD IF SO
				;IF THERE IS A LEADING PLUS
	DEC	BH		;NO LEADING PLUS SO DON'T INCREMENT THE
				;NUMBER OF DIGITS BEFORE THE DECIMAL POINT
	JCXZ	ENDNUM		;SEE IF THERE ARE MORE CHARACTERS
	LODSB			;GET THE CURRENT CHARACTER
	CMP	AL,"-"		;TRAIL MINUS?
	JZ	SGNTRL		;SET THE TRAILING SIGN FLAG
	CMP	AL,"+"		;A TRAILING PLUS?
	JNZ	ENDNUM		;IF NOT, WE ARE DONE SCANNING
	OR	DH,PLUS 	;TURN ON THE POSITIVE="+" FLAG
SGNTRL:
	OR	DH,SIGN 	;TURN ON THE TRAILING SIGN FLAG
	DEC	CX		;DECREMENT THE "USING" STRING CHARACTER
				;COUNT TO ACCOUNT FOR THE TRAILING SIGN
ENDNUM:
	MOV	PUSC,CX 	;Save scan count
	MOV	b$DIGCNT,BX
	ADD	BH,BL		;Digit count must not exceed 24
	CMP	BH,25
	JNC	ARGERR		;IF SO, "ILLEGAL FUNCTION CALL"
	OR	DH,PUSING	;TURN ON THE "USING" BIT
	MOV	BYTE PTR [b$PUFLG],DH	
PUSCAX:
	RET			;GET OUT

ARGERR: JMP	B$ERR_FC

	SUBTTL	check/print "+"
	page
;***
;PLSPRT -- decide whether a "+" should be printed or not
;
;Purpose:
;	If the "+" flag in [DH] is set, and a character which is decided
;	not part of a numeric field is found, a "+" is printed.
;
;	When a "+" is detected in the "using" string, if a numeric field
;	follows, a bit in [DH] should be set, otherwise a "+" should be
;	printed.  Since deciding whether a numeric field follows is very
;	difficult, the bit is always set in [DH].  At the point a character
;	which is decided not part of a numeric field is found, this routine
;	is called to see if the bit in [DH] is set.  If it is, then a plus
;	is printed.
;Entry:
;	[DH]	= print using flag (refer the definition of b$PUFLG)
;Exit:
;	none
;Uses:
;	none
;Preserves:
;	[AX]	= current character
;Exceptions:
;	none
;*******************************************************************************

cProc	PLSPRT,<NEAR>

cBegin
	OR	DH,DH		;check the plus bit in DH
	JZ	RT
	PUSH	AX		;save current character
	MOV	AL,"+"		;print "+"
	CALL	[VWCH]		;do it
	POP	AX		;get back character
RT:
cEnd				;exit to caller
sEnd	;ST_TEXT

; Moved B$PUSG here from PR0A.ASM to increase /O modularity
; Revision applies to entire routine B$PUSG.
	assumes CS,DK_TEXT	
sBegin	DK_TEXT			

	SUBTTL	interface for USING preamble
	page
;***
;B$USNG -- USING preamble [7]
;void B$USNG(sd *psdPUexp)
;
;Purpose:
;	This is the preamble for USING clause found in PRINT/LPRINT stmt.
;	It ORs the flag, b$PRFG, with USING (=2) to indicate an USING
;	clause is on going.  It also set up the b$PUSG with the actual
;	working routine, B$PREN.  The using expression is copied into
;	b$PUDS for further use.
;Entry:
;	Parameter is in stack:
;	sd	*psdPUexp
;Exit:
;	[b$PRFG] OR USING (=2)
;	[b$PUFLG] = NOPEND (set to no type pending)
;	[b$PUDS] = string of the print using
;	[b$PUSG] = address of actual working routine (B$PREN)
;Uses:
;	none
;Exceptions:
;	none
;*******************************************************************************

cProc	B$USNG,<PUBLIC,FAR>		
ParmSD	sdPUexp 			; sd of using expression
cBegin
	MOV	AX,OFFSET DGROUP:b$PUDS 
	cCall	B$SASS,<sdPUexp,AX>	;copy "using" string
	OR	[b$PRFG],USING 		;set up USING flag
	MOV	[b$PUSG],OFFSET B$PREN
					;set up the entry address for USING
	MOV	[b$PUFLG],NOPEND 	;set to no type pending
cEnd					;exit to caller

sEnd	;DK_TEXT			
	END

⌨️ 快捷键说明

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