📄 prtu.asm
字号:
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 + -