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

📄 fin.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	CMP	AL,'%'		;integer?
	JNE	FIN_30
	TEST	CL,l_s16inv	;check if valid 16-bit integer
	JNZ	FIN_TM		; no - type character error
	JMP	SHORT FIN_40

FIN_30:
	CMP	AL,'&'		;long?
	JNE	FIN_35
	TEST	CL,l_s32inv	;check if valid 32-bit integer
	JNZ	FIN_TM		;  no - type character error
	OR	CL,l_s16inv	;force it long
	JMP	SHORT FIN_40

FIN_TM: JMP	B$ERR_TM	;invalid type character

FIN_35:

	DEC	SI		;back up

FIN_40:
;
; Since we couldn not parse any number at all, we have to explicitly
; return a zero ($I8_INPUT will return garbage).  We can also just
; return without further tests, which will avoid an altmath bug where
; certain invalid flags are not being set if l_inv is set.
;
; This check could not be done earlier, as we need to do the same type
; character parsing as before this bug fix.
;
	TEST	CL,l_inv	; was the number invalid?
	JNZ	InValidNumber	; yes, zero out our number and return
;
; Now we attempt to store the result, based on the user-requested data type.
;
	XCHG	AX,BX		; [DX:AX] = possible long result
	MOV	BL,[B$VTYP]    
;
; If the result is a valid 16 bit int, and the user wants an int, just store
; the result (in AX) into the fac.
;
	TEST	CL,l_s16inv	;result a valid 16-bit integer?
	JNZ	FIN_45		;Jump if not
	CMP	BL,VT_I2	; User wants an I2?
	JZ	FIN_50		;brif so - same logic as when have I4
;
; If the result is a valid 32 bit int (or a fall through valid 16 bit int), and
; the user want's an I4, then just store the result (in BX:AX) into B$AC.
;
FIN_45:
	TEST	CL,l_s32inv	;result a valid 32 bit int?
	JNZ	FIN_55		;Jump if not
	CMP	BL,VT_I4	; caller wants an I4?
	JNZ	FIN_55		;brif not
	MOV	[WORD PTR B$AC+2],DX	 ; save high word
FIN_50:
	MOV	[WORD PTR B$AC],AX	 ; save low word
	jmp	SHORT FIN_EXIT		 ;done - exit
;
;If the result is a valid currency, and the user wants currency, just
;store the result (at $i8_input_cy) into B$DAC.
;
FIN_55: 			
;
; The number is not a valid int, thus only the R8 in B$DAC is valid. Determine
; what type the user wants, and coerce to that by loading up on the numeric
; stack, and storing as the desired type.
;
	TEST	CL,l_inf	; Waaaayyyyyy too big?
	JNZ	FIN_OV		; then go complain.
	XCHG	BX,DX		; [DL] = valtype
	CMP	DL,VT_R8	;Does the user perhaps want R8?
	JZ	FIN_EXIT	;In that case, we're done!

	FLD	B$DAC		; [ST0] = R8

	CMP	DL,VT_R4	;Does the user want an R4?
	JNZ	FIN_60		;Jump if not, probably wants an int

	FSTP	B$AC		; Save as R4

	JMP	SHORT FIN_EXIT
;
; Here we have an Integer result type, with only an R8 in B$AC. Convert to the
; appropriate type, with rounding, and make sure the result fits.
;
FIN_60:
	CMP	DL,VT_I2
	JZ	FIN_65		;Must be either I2 or I4 or CY at this point
	CMP	DL,VT_I4
	JNZ	FIN_OV		;Jump if error
FIN_65:
	PUSH	DX		;Save the user resuested type
	cCALL	B$ftolrnd	;Round nearest or even & Store it in DX:AX
	MOV	[WORD PTR B$AC],AX	; Store low word
	MOV	[WORD PTR B$AC+2],DX	; Store Hi-word
	MOV	BX,DX		;Get a copy of Hi-word
	CWD			;Needed to check for overflow in SINT
	CMP	DX,BX		;If they are equal, then all is well
	POP	DX		;[DL] = valtype
	JE	FIN_EXIT	;No complaint
	CMP	DL,VT_I4	;User wanted a long integer?
	JE	FIN_EXIT	;Brif so - no error

FIN_OV: JMP	B$ERR_OV	;Overflow error

InValidNumber:
	MOV	DI,OFFSET DGROUP:B$DAC	 
	XOR	AX,AX		; Get a Zero to store
	STOSW			; Store it as an R8 (will be 0 for all
	STOSW			;  possible lengths)
	STOSW			
	STOSW			

FIN_EXIT:
	CALL	B$GETCH 	; provide return value

FIN_Str_Exit:			 
	FWAIT			; Always wait for 87 to complete.
cEnd				



	SUBTTL	B$STRSCAN
	PAGE
;***
;B$STRSCAN
;
;Purpose:
;	This routine will scan a zero terminated string for the
;	presence of a string input by the user.  If the first
;	character of the string is a double quote ("), then the
;	string is composed of all characters from the double quote
;	to the next double quote not including the quotes.  Otherwise
;	the string is composed of all the characters from the first
;	character until the first comma.
;
;	If the double quote or comma does not appear before the terminating
;	zero, then the zero byte is used as a legal terminator. On return,
;	[ES:SI] will point to the byte following the string seperator.	The
;	seperator, which is returned in AL, is determined as follows:
;
;	1.) If the string was terminated by a zero byte, then the
;	    seperator is the zero byte
;	2.) If the string was not quoted, then the seperator is
;	    the comma that ended the string
;	3.) If the string was quoted, then the seperator is the
;	    first non-blank character following the second double quote.
;
;
;Parameters:
;	[ES:SI]       = Pointer to text string to analyze
;
;Returns:
;	[ES:DX]       = updated pointer to start of string
;	[ES:SI]       = updated pointer to char after string seperator.
;	[CX]	      = Length of string (number of bytes in string)
;	[AL]	      = Seperator byte
;****

cProc	B$STRSCAN,<NEAR,PUBLIC>
cBegin

assumes DS,NOTHING		
assumes ES,NOTHING		
	PUSH	DS		
	PUSH	ES		; CAUTION: We switch DS to point to string
	POP	DS		; CAUTION: data references won't work.

	CALL	B$GETCH
	MOV	AH,AL		;In case first char is "
	CMP	AL,'"'		;Is it?
	JZ	COUNTSTR
	MOV	AH,","		;Terminate with comma if not quoted
	DEC	SI		;Scan first char again
COUNTSTR:
	MOV	DX,SI		;Save starting address of string data
	XOR	CX,CX		;Character count
RDSTR:
	LODSB			;get byte from DS:SI and increment SI
	CMP	AL,AH		;End of string?
	JZ	NEGCNT
	OR	AL,AL		;End of line?
	LOOPNZ	RDSTR		;Count char and loop if not EOL
	INC	CX		;Don't count the EOL character
	CMP	AH,','		;Quoted string?
	JE	NEGCNT		;  No
	DEC	SI		;  Yes - point back to 00 terminator
NEGCNT:
	NEG	CX		;Make character count positive
	CMP	AH,','		;Unquoted string?
	JNZ	GETRTN
;Not a quoted string. Trim off trailing blanks.
	DEC	SI		;Point back at termination character
	MOV	DI,SI
	DEC	DI		;Point to last char of string
	MOV	AL," "
	CMP	AL,AL		;Set zero flag in case CX=0
	STD			;Set direction DOWN
	REPE	SCASB		;Scan of blanks backward
	CLD			;Restore direction
	JZ	GETRTN		;If null string, leave zero in CX
	INC	CX		;Last char scanned not blank - count it
GETRTN:
	CALL	B$GETCH 	;Get Delimiter for return
	POP	DS		;Restore Data Segment
cEnd


page

;***
; B$GETCH, B$GETCH_NS - get next byte from buffer
;
;Purpose:
;	These routines will get the next byte from a zero terminated
;	string of characters.  B$GETCH will skip blank spaces, tabs, and
;	linefeeds, B$GETCH_NS will not.  If the character is a letter, it
;	will be converted to upper case.  If FV_DBCS and FK_FULLMAP
;	then any two byte characters will first be converted to their
;	one byte format if at all possible otherwise any double double
;	byte character will be returned one character at a time.
;
;	If FV_DBCS, then b$SISAVE will be set to the offset (from DS)
;	of the character that is being returned.  This is used by other
;	code to back up a single character.  It is possible for this routine
;	to return only the first half of a Double Byte Character.  This
;	will cause no problems, as it will always be invalid for the purpose
;	that it is used (this will desynchronize the character order
;	but everyone who gets a double byte character from here will die
;	with an error at one point or another).
;
;	NOTE: DS may not point to DGROUP!
;
;Entry:
;	DS:SI - points to a zero terminated string
;
;Exit:
;	AL - next legal character in the string
;	DS:SI - points to next character
;
;Uses:
;	SI is used as the index into a string.
;
;Preserves:
;	AH, BX, CX, DX
;
;Exceptions:
;	None.
;****

cProc	B$GETCH_NS,<PUBLIC,NEAR>
cBegin
	LODSB			;get byte from DATA statement segment
	JMP	SHORT UPPER	;continue on with processing in B$GETCH
cEnd	<nogen>

cProc	B$GETCH,<PUBLIC,NEAR>
cBegin

GET_ANOTHER:			
	LODSB			;get byte from DATA statement segment

	CMP	AL," "		;Ignore spaces
	JZ	GET_ANOTHER	
	CMP	AL,9		;Ignore tabs
	JZ	GET_ANOTHER	
	CMP	AL,10		;Ignore linefeeds
	JZ	GET_ANOTHER	
UPPER:
	CALL	B$UPCASE	;Convert to upper case
cEnd



assumes DS,DGROUP		
assumes ES,DGROUP		


sEnd	MT_TEXT

	SUBTTL	FAR_I8_INPUT - Far Interface to $i8_input
	PAGE
;***
;FAR_I8_INPUT - far interface to $i8_input
;
;Purpose:
; This interface routine is required because we can't be sure that the B$FIN
; portion of MT_TEXT will be within 64k of $i8_input in _TEXT, and $i8_input
; must be called NEAR
;
;Entry:
; [AX] = FORTRAN scale factor
; [BX] = Radix desired (1..36), integer only to be returned.
; [CX] = Maximum character count for scanning input stream.
; [DX] = FORTRAN decimal point format factor
; [DI] = DS offset of space for 8 byte result
; [SI] = points to first digit in number to input
; [BX] = radix desired, integer only to be returned (0 is default)
; [ES] = DS
;
;Exit:
; [SI] = DS offset of first byte after decoded string value
; [DI] = DS offset of 8-byte result
; [AX] = low order part of integer value (32-bit integer)
; [BX] = high order part of integer value (32-bit integer)
; [CX] = Return flags - - - defined elsewhere
;
; Outputs:
;
;****
sBegin	_TEXT			; $i8_input must be called NEAR from here
	ASSUMES CS,_TEXT

externNP $i8_input	       


FAR_I8_INPUT PROC    FAR
	CALL	$i8_input      ;mathpack call
	RET
FAR_I8_INPUT	ENDP

sEnd	_TEXT

	END

⌨️ 快捷键说明

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