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

📄 strfcn.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
cProc	B$FMID,<FAR,PUBLIC>	
parmW	psdSource		
parmW	iStart			
parmW	cbLen			
cBegin				

	MOV	BX,psdSource	
	MOV	CX,cbLen	
	OR	CX,CX		;test string length
	JL	ARGER2		;error if negative
	MOV	DX,iStart	
	DEC	DX		;Offset should start at zero, not 1
	XCHG	DX,CX		;Set up for future call
	JL	ARGER2		;Error if now negative
	JNZ	MID_10		
	CALL	LEFRIG		; Offset is zero, so treat just like LEFT$
	JMP	SHORT MID_90	
MID_10: 			
	MOV	AX,[BX] 	;Get length of string
	SUB	AX,CX		;Reduce length by the offset
	JNLE	MID_20		
	CALL	B$STDALCTMP	;Delete if temp string
	MOV	AX,OFFSET DGROUP:b$nuldes ; Null string descriptor
	JMP	SHORT MID_90	
MID_20: 			
	CMP	AX,DX		;Need smaller of request and amount remaining
	JGE	MIDLEN
	MOV	DX,AX		;Limited by length of string
MIDLEN:
	CALL	B$STALCTMPSUB	;Create temp string from descriptor
	XCHG	AX,BX		; [AX] has return value
MID_90:

cEnd				


;***
; LEFRIG - support routine
;
;Purpose:
; This subroutine is used for $LEF, $RIG, and some $MID.
;
;Entry:
; [BX]	 = Address of string descriptor
; [DX]	 = Length requested
; [CX]	 = Starting offset
;
;Exit:
; [AX]	 = new descriptor
;
;Uses:
; CX   - only for special RIGHT$ case
;
;Preserves: (optional)
;
;Exceptions:
;
;******************************************************************************
cProc	LEFRIG,NEAR
cBegin

	OR	DX,DX		;Test requested length
	JL	ARGERR		;If negative, give error
	JNZ	LEFRIG_10	;If zero, return null string
	CALL	B$STDALCTMP	;ensure we get rid of any temps
	MOV	AX,OFFSET DGROUP:b$nuldes 
	RET
LEFRIG_10:
	CMP	DX,[BX] 	;See if requested length is shorter than string
	JLE	MAKTMP		;  Yes - create temp string
	MOV	DX,[BX] 	;  No - use actual string length
	OR	CX,CX		;If offset is negative from RIGHT$
	JGE	MAKTMP		;  No - OK
	XOR	CX,CX		;  Yes - just make it zero
MAKTMP:
	CALL	B$STALCTMPSUB	;Create temp from string descriptor
	XCHG	AX,BX		; [AX] = new descriptor
cEnd				


	SUBTTL	B$SPAC - SPACE$ function
	PAGE
;***
;B$SPAC - SPACE$ function
;sd * pascal B$SPAC(I2 cbDesired)
;
;Function:
; Produce temporary string with a blank (' ') character repeated BX times.
;
;Inputs:
; cbDesired = Length of string desired
;
;Outputs:
; [AX]	= Address of result temp string descriptor
;
;Registers:
; Per convention
;
;******************************************************************************
cProc	B$SPAC,<FAR,PUBLIC>	
parmW	cbDesired		
cbegin

	MOV	DL," "		;Provide a space to be repeated
	MOV	BX,cbDesired	; [BX] = count
	CALL	STRING		; [AX] = pointer to sd

cEnd

;***
; STRING - Create a temp string of length n containing something.
;
;Purpose:
;	Creates a temp string of n characters, where character is specified.
;	If we are compiled with KANJI enabled, DL contains the first byte
;	of the character to go into the string.  DH contains the second byte
;	unless it is 0 in which case it is a single byte character.
;
;Entry:
; [DL]	= Character (DX for kanji)
; [BX]	= desired length
;
;Exit:
; [AX]	= pointer to temp sd
;
;Uses:
; Per convention
;
;******************************************************************************
cProc	STRING,NEAR,ES
cBegin
	MOV	AX,OFFSET DGROUP:b$nuldes ;[7]
	OR	BX,BX		;Check character count
	JZ	STRING_90	; Return null string if zero
	JL	ARGERR		;Error if negative


NOTKAN: MOV	CX,BX		;Put count in count register
	MOV	AL,DL		;Character to copy
	MOV	AH,DL		;Repeat it by words for speed
	CALL	B$STALCTMP	;Allocate string
	INC	CX		;Round up to whole word if odd
ISKAN:	XCHG	DI,DX		;Get address of data in destination register
	SHR	CX,1		;Divide byte count by 2 for word move
	PUSH	DS		
	POP	ES		; [ES] = [DS]
	REP	STOSW
	MOV	DI,DX		;Restore DI
	XCHG	AX,BX		;[AX] has string desc
STRING_90:
cEnd

ARGERR: JMP	B$ERR_FC	  ;Clean stack and report illegal function call

	SUBTTL	B$STRI & B$STRS - STRIN& functions
	PAGE
;***
;B$STRI & B$STRS - STRING$ functions
;sd * pascal B$STRI(I2 cbdesired, I2 ascCode)
;sd * pascal B$STRS(I2 cbDesired, sd *psdChar)
;
;Function:
; Produce temporary string with a single character repeated BX times. B$STRI
; provides the character to be repeated, and B$STRS provides a string
; descriptor, the first character of which is to be repeated.
;
;Inputs:
; cbDesired = Length of string desired
; ascCode   = Character to repeat (B$STRI only)
; psdChar   = Descriptor of string with character to repeat (B$STRS only)
;
;Outputs:
; [AX]	= Address of result temp string descriptor
;
;Registers:
; Per convention
;
;******************************************************************************
cProc	B$STRI,<FAR,PUBLIC>	
parmW	cbDesired		
parmW	ascCode 		
cBegin

	MOV	DX,ascCode	
	JMP	SHORT STRI_10	
cEnd	nogen

cProc	B$STRS,<FAR,PUBLIC>	
parmW	cbDesired		
parmW	psdChar 		
cBegin

	MOV	BX,psdChar	; Put descriptor where we can address with it
	CMP	WORD PTR[BX],0	;Length of string must not be zero
	JZ	ARGERR
	PUSH	BX		
	MOV	BX,[BX+2]	;Get address of string data
	POP	AX		; [AX] = pointer to descriptor

	PUSH	[BX]		; Push first character in string
	XCHG	AX,BX		; [BX] = pointer to descriptor
	CALL	B$STDALCTMP	;Delete if temp string
	POP	DX		; [DX] = character
STRI_10:			
	MOV	BX,cbDesired	; [BX] = length to do it
	CALL	STRING		; [AX] = pointer to sd
cEnd

	SUBTTL	B$VARP - VARPTR$ function
	PAGE

;***
;B$VARP - VARPTR$ function
;sd * pascal B$VARP(U2 addr, I2 type)
;
;Function:
; Create a 3 byte string of following:
;	Byte 1		contains variable type, one of:
;		2 - Integer
;		3 - String
;		4 - Single
;		8 - Double
;	       14h- Long
;	Byte 2 & 3	contain the address of the variable
;
;Inputs:
; addr	= Address of Variable
; typ	= type of the variable
;
;Outputs:
; [AX]	= Address of String Descriptor
;
;Registers:
; Per convention
;******************************************************************************
cProc	B$VARP,<FAR,PUBLIC>	
parmW	addr			
parmW	typ			
cBegin				
	MOV	BX,3
	CALL	B$STALCTMP	;Get a 3 byte string
	XCHG	BX,DX		;[BX] has its address
	MOV	AX,typ		
	MOV	[BX],AL 	
	MOV	AX,addr 	
	MOV	[BX+1],AX	
	XCHG	AX,DX		; [AX]= String Descriptor

cEnd



	SUBTTL	B$LCAS/B$UCAS - convert string to lower/upper case
	PAGE
;***
; B$UCAS - Convert string to upper case
; B$LCAS - Convert string to lower case
;
;Purpose:
; String case conversion.
;
;Entry:
; psd	= Pointer to string descriptor to be converted
;
;Exit:
; [AX]	= Pointer to string descriptor of result
;
;Uses:
; Per convention
;
;******************************************************************************
cProc	B$UCAS,<FAR,PUBLIC>
cBegin
	MOV	AX,'za'
	JMP	SHORT	CASE_5	;go perform case conversion
cEnd	nogen

cProc	B$LCAS,<FAR,PUBLIC>
cBegin
	MOV	AX,'ZA'
cEnd	nogen			

cProc	CASE_5,FAR,<DI,SI,ES>	
parmW	psd			
cBegin				

	MOV	BX,psd		;get string descriptor
	MOV	DX,[BX] 	;(DX) = length of string to convert
	OR	DX,DX		;is this a null string ?
	JZ	uca_ret 	;yes, just return it
	XOR	CX,CX
	CALL	B$STALCTMPSUB	;no, copy string to temporary
	PUSH	BX
	XCHG	CX,DX		;(CX) = length of string to convert
	MOV	SI,[BX+2]	;(SI) = ptr to string data
	MOV	DI,SI		;ditto for DI
	XCHG	AX,BX		;(BX) = chars to check
	PUSH	DS		; set ES=DS
	POP	ES
uca_loop:
	LODSB			;fetch next char from string
	CMP	AL,BL
	JB	uca_cont	;ignore if not wrong case
	CMP	AL,BH
	JA	uca_cont	;ignore if not wrong case
	XOR	AL,20H		;flip upper case bit
uca_cont:
	STOSB			;put character back
	LOOP	uca_loop	;repeat until entire string is checked
uca_abort:
	POP	BX		;restore descriptor address
uca_ret:
	XCHG	AX,BX		;return sd in AX

cEnd

	SUBTTL	$TRL/$TRM/$TRR - Trim blanks off string
	PAGE
;***
; B$TRIM, B$LTRM, B$RTRM - Trim family
;
;Purpose:
; Trim leading, trailing or both blanks from a string.
;
;Entry:
; psd	= Pointer to string descriptor to be converted
;
;Exit:
; [AX]	= Pointer to string descriptor of result
;
;Uses:
; Per convention
;
;******************************************************************************
TR_LEFT= 1
TR_RIGHT= 2

; cProc	B$TRIM,<PUBLIC,FAR>
; cBegin
; 	MOV	AH,TR_LEFT+TR_RIGHT
; 	SKIP	2		; fall into TRIM
; cEnd	nogen

cProc	B$LTRM,<PUBLIC,FAR>
cBegin				
	MOV	AH,TR_LEFT
	SKIP	2		; fall into TRIM
cEnd	nogen

cProc	B$RTRM,<PUBLIC,FAR>
cBegin				
	MOV	AH,TR_RIGHT
cEnd	nogen			; fall into TRIM

cProc	TRIM,FAR,<DI,ES>	
parmW	psd			
cBegin				

;When scanning for a blank character, we know that we will never take
;any part of a KANJI character as a space, as this value is illegal in
;a KANJI.

	PUSH	DS		; set es=ds
	POP	ES		
	MOV	BX,psd		;Get source SD
	MOV	CX,[BX] 	; get string length
	JCXZ	trim_ret	;   null string - return
	MOV	DI,[BX+2]	; (DI) = address of string contents
	MOV	AL,' '		; AL = blank - trim char
	TEST	AH,TR_LEFT	; trim left blanks?
	JZ	trim_right	;   no - trim right
trim_left:			
	REPE	SCASB		; scan blanks off front
	JZ	trim_done	;   all blanks

	INC	CX		; backup one character
	DEC	DI

trim_right:
	MOV	DX,DI		; (DX) = 1st nonblank address
	SUB	DX,[BX+2]	; (DX) = offset of 1st nonblank
	TEST	AH,TR_RIGHT	; trim right blanks?
	JZ	trim_done	;   no - done
	ADD	DI,CX
	DEC	DI		; (DI) = last char in string
re_trim_right:
	STD			; direction is down
	REPE	SCASB		; scan blanks off back
	CLD			; direction is up
	JZ	trim_done	;   all blanks
	INC	CX		; backup one character

trim_done:
	XCHG	CX,DX		; CX=offset , DX=length , BX=sdesc
	CALL	B$STALCTMPSUB	; copy into temp string

trim_ret:
	XCHG	AX,BX		;Return sd in AX
cEnd

sEnd	ST_TEXT

	END

⌨️ 快捷键说明

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