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

📄 strstack.asm

📁 random.zip 随机数产生器的汇编源代码 cmdsrc.zip 一个文本编辑器的汇编源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	call	near ptr stre_cmp ;Check if pattern is a prefix
	pop	cx
	jne	@strstk_bck_match_9 ;Not a prefix, go try next one
	xor	ax,ax
	mov	al,-1[si]	;AX<-length of matched string
	add	si,ax		;Point SI to trailer of matched string
; 	Successful match, return with CF clear.
;	Carry flag is guaranteed clear since no o'flow is possible in
;	the add si,ax instruction. Hence comment out the following clc.
;	clc
	jmp	short @strstk_bck_match_99
@strstk_bck_match_90:
	stc			;Error return

@strstk_bck_match_99:
	mov	[bx].cur,si	;Update current string pointer
	mov	sp,bp
	pop	bp
	@restore
	ret
strstk_bck_match endp




;+
; FUNCTION : strstk_fwd_find,strstk_bck_find
;
;	Searches towards the top/bottom of the stack, starting from the string
;	above/below the current string looking for a string that is the same
;	as the specified one. If the current string is at the top/bottom
;	the stack, the cur pointer remains unchanged.
;
; Parameters:
;	BX :=	address of buffer stack descriptor
;	AX :=	Address of string
;	CX :=	Length of string
; Returns:
;	CF  = 1 if no match or if at top/bottom of stack
;	    = 0 if success
;
; Registers AX,CX,DX destroyed.
;-
strstk_find proc near
strstk_fwd_find LABEL near
	push	di			;Save di
	push	si			;and si
	mov	di,offset CSEG:strstk_fwd_match
	jmp	short @strstk_find_8
strstk_bck_find LABEL near
	push	di			;Save di
	push	si			;and si
	mov	di,offset CSEG:strstk_bck_match
@strstk_find_8:
	mov	si,ax			;Save string address in SI
@strstk_find_10:
; Loop start
	mov	ax,si			;AX->string
	push	cx			;Save string length
	call	di 			;Look for prefix
	pop	cx			;Restore string length
	jc	@strstk_find_99		;Not found
	push	cx
	xor	cx,cx			;Don't want to copy, just need size
	call	near ptr strstk_copy	;AX<-length of current string
	pop	cx			;Restore passed length
	cmp	ax,cx			;Strings match ?
	jne	@strstk_find_10		;Lengths not same, keep looking
	clc				;Strings same
@strstk_find_99:
	pop	si
	pop	di
	ret
strstk_find endp



;+
; FUNCTION : strstk_makespace
;
;	Deletes enough strings from the bottom of the stack to make room
;	for a string of the length specified in AX. If the stack size is
;	smaller than the requested size, the stack is left unchanged and
;	an error indication returned. If there is already enough room in
;	the stack, the stack is left unchanged. In both cases the current
;	string ptr is updated to point to the top of the stack. Note that
;	any marks, if present, reduce the space that is available. 
;
;	The routine is not very efficient since it keeps calling strstk_kill
;	rather than deleting the required number in one shot. But it is
;	more compact.
; Parameters:
;	BX :=	pointer to buffer descriptor
;	AX :=	requested length
; Returns:
;	CF	= 1 if error (requested length to large for stack)
;		= 0 success
; 	Also changes current string pointer to point to top of stack.
; Registers AX,CX,DX destroyed.
;-
strstk_makespace proc near
	@save	si,di
	xchg	ax,si		;Save requested length in SI
	call	strstk_size	;AX := size of largest string that can
				; fit in an empty stack
	cmp	ax,si		;Smaller than requested length ?
	jb	@strstk_makespace_99 ;Yes, error exit
	call	strstk_setbot	;Set current string to bottommost

;Now keep iterating until enough strings have been deleted. Since we 
;have already checked that the stack is large enough, the loop below
;is guaranteed to terminate.

@strstk_makespace_10:
; Note that the strstk_space routine returns a 0 if there are less than
; the 2 bytes required for header/trailer. The carry flag must be
; checked to distinguish this from the situation where there is room
; for a null string (exactly 2 bytes available)
	call	near ptr strstk_space	;AX := available space
	jnc	@strstk_makespace_70	;Jump if > 2 bytes available
@strstk_makespace_65:
	call	strstk_kill		;If not delete one more
	jmp	short @strstk_makespace_10 ;And keep trying
@strstk_makespace_70:
	cmp	ax,si			;Enough space available ?
	jb	@strstk_makespace_65	;Yes, exit
@strstk_makespace_99:
	call	near ptr strstk_settop
	@restore
	ret
strstk_makespace endp


;+
; FUNCTION : strstk_copy
;
;	Returns a copy of the current stack entry. Stack is unchanged.
;	If the stack is empty, a 0 length string is returned.
;	If the user buffer is not large enough, as many characters as
;	possible are copied into it. AX reflects the length of the actual
;	string and not just the copied part and the carry flag is set.
;	Thus this routine can also be used to find the length of the current
;	string by passing it a zero length buffer.
;
; Parameters:
;	BX	:= pointer to buffer descriptor
;	AX	:= starting address of location into which the string
;			is to be copied
;	CX	:= size of buffer
;
; Returns:
;	AX	= length of current string (ACTUAL LENGTH, NOT COPIED LENGTH)
;	CF	= 0 if the user buffer is large enough
;		= 1 if user buffer too small
;		  As many chars as possible are returned in the use buffer.
; Register CX destroyed.
;-
strstk_copy proc near
	@save	si,di
	mov	di,ax		;Destination buffer
	mov	si,[bx].cur	;SI := trailer of current string
	mov	al,[si]
	xor	ah,ah		;AX:=length of current string
	sub	si,ax		;SI->first byte of string
	cmp	cx,ax		;User buffer large enough ?
	jb	@strstk_copy_5	;No, error return
				;Note empty stack case automatically handled.
	mov	cx,ax		;CX<-length of string to copy
@strstk_copy_5:
	pushf			;Save carry flags
;	CX == number of bytes to copy
	rep	movsb
	popf			;Restore CF
	@restore
;	Return AX = length of actual string
	ret
strstk_copy endp



;+
; FUNCTION : strstk_size
;
;	Returns the maximum size string that can fit in the buffer if all
;	strings are deleted (but not markers).
;
; Parameters:
;	BX	:= buffer descriptor address
;
; Returns:
;	AX	:= Max string size for buffer if all strings are deleted
;
; All registers (except AX)  are preserved.
;-
strstk_size proc near
	mov	ax,[bx].topmark		;Address beyond last available
					; for strings
	sub	ax,[bx].low_end		;bottom of buffer (sentinel header)
	sub	ax,4			;Need 2 for header trailer + 2 for
					; sentinel
	jnb	@strstk_size_99		;
	xor	ax,ax			;No space !
@strstk_size_99:
	ret
strstk_size endp





;+
; FUNCTION : strstk_prefix
;
;	Compares the passed string to check if it is a prefix of the
;	current string in the stack.
;
; Parameters:
;	BX	:= buffer descriptor address
;	AX	:= address of string
;	CX	:= length of string
;
; Returns:
;	ZF	= 1 if string is prefix
;		  0 if not
;
; Register(s) destroyed:
;-
strstk_prefix	proc near
	@save	si,di
	xchg	di,ax			;DI->string
	mov	si,[bx].cur		;SI->trailer byte of stack element
	xor	ah,ah			;Clear high byte
	mov	al,[si]			;AX<-length of string
	cmp	ax,cx			;Passed string longer ?
	jb	@strstk_prefix_90	;No, return `not prefix'
	sub	si,ax			;SI->start of string
	call	near ptr stre_cmp
;	ZF is set if match occurs, 0 otherwise
	jmp	short @strstk_prefix_99
@strstk_prefix_90:
	inc	al			;Set ZF=0 (no match)
@strstk_prefix_99:
	@restore
	ret
strstk_prefix endp




;+
; FUNCTION : strstk_compare
;
;	Compares the passed string against the current string in the stack.
;
; Parameters:
;	BX	:= buffer descriptor address
;	AX	:= address of string
;	CX	:= length of string
;
; Returns:
;	ZF	= 1 if strings equal
;		  0 if not equal.
;
; Register(s) destroyed:
;-
strstk_compare	proc near
	@save	si,di
	xchg	di,ax			;DI->string
	mov	si,[bx].cur		;SI->trailer byte of stack element
	xor	ah,ah			;Clear high byte
	mov	al,[si]			;AX<-length of string
	cmp	ax,cx			;Same length?
	jne	@strstk_compare_99	;No, return `not equal'
	jcxz	@strstk_compare_99	;Equal (zero length), ZF
;					 already set
	sub	si,ax			;SI->start of string
	call	near ptr stre_cmp	;Case-insensitive compare
;	ZF is set if match occurs, 0 otherwise
@strstk_compare_99:
	@restore
	ret
strstk_compare endp



	IF	WANT_MARKERS
;+
; FUNCTION : strstk_update_markers
;
;	This routine is called to update the markers that point to various
;	strings in the stack. This is necessary when strings are deleted
;	causing the string positions to change.
;
; Parameters:
;	BX	:= address of stack descriptor
;	AX	:= The address of the old (deleted) current string
;	CX	:= Number of bytes by which the strings were displaced.
;
; Returns:
;	Nothing.
; Registers AX is destroyed.
;-
strstk_update_marks proc near
	@save	si,di
	xchg	ax,si		;Store old current address in SI
	mov	di,[bx].topmark	;DI will iterate through the marks
@strstk_update_marks_20:
	cmp	di,[bx].high_end
	jnc	@strstk_update_marks_99 ;All done
	mov	ax,[di]		;Old address of marked string
	cmp	si,ax		;Compare with address of deleted string
	jne	@strstk_update_marks_40	;
	mov	ax,[bx].cur	;Mark pointed to deleted string so
	jmp	short @strstk_update_marks_50	;point it to new current
@strstk_update_marks_40:
	jg	@strstk_update_marks_50	;If mark pointed BELOW, no change
	sub	ax,cx		;Else subtract the displacement
@strstk_update_marks_50:
	stosw			;Store new value back, increment DI to point
	jmp	short @strstk_update_marks_20 ; to next mark and loop

@strstk_update_marks_99:
	@restore
	ret
strstk_update_marks endp



;+
; FUNCTION : strstk_mark_cur
;
;	Changes the topmost mark to point to the current string. If no marks
;	exist, one is created.
;
; Parameters:
;	BX	:= address of descriptor.
;
; Returns:
;	CF = 1 if error (no room), else 0.
; Register AX is destroyed.
;-
strstk_mark_cur proc near
	call	strstk_kill_mark
	call	strstk_push_mark
	ret
strstk_mark_cur endp


;+
; FUNCTION : strstk_kill_mark
;
;	Deletes the topmost mark on the stack.
;
; Parameters:
;	BX	:= address of buffer descriptor
;
; Returns:
;	CF = 1 if stack was empty, else 0.
; Register AX is destroyed.
;-
strstk_kill_mark proc near
	mov	ax,[bx].high_end	;Highest location of buffer
	cmp	ax,[bx].topmark	;Marker stack empty ?
	jb	@strstk_kill_mark_99 ;Yes
	dec	[bx].topmark	;Remove topmost mark by updating
	dec	[bx].topmark	; top of stack ptr
@strstk_kill_mark_99:
	ret
strstk_kill_mark endp


;+
; FUNCTION : strstk_push_mark
;
;	Pushes a marker to the current string onto the marker stack.
;
; Parameters:
;	BX	:= address of descriptor
;
; Returns:
;	CF = 1 if error (no room), else 0.
; Register AX is destroyed.
;-
strstk_push_mark proc near
	@save	di
	mov	di,[bx].topmark	;Point to topmost mark
	dec	di
	dec	di		;Next location to push mark
	cmp	di,[bx].top	;Enough room ?
	jle	@strstk_push_mark_90 ;Sorry, return error
	mov	[bx].topmark,di	;New stack top
	mov	ax,[bx].cur	;Address of current string
	stosw			;Store in top marker
	;Carry is clear
	jmp	short @strstk_push_mark_99
@strstk_push_mark_90:
	stc			;Set error
@strstk_push_mark_99:
	@restore
strstk_push_mark endp


;+
; FUNCTION : strstk_pop_mark
;
;	Pops the topmost mark off the stack and set the current ptr
;	to point to its associated string.
;
; Parameters:
;	BX	:= address of buffer descriptor
;
; Returns:
;	CF = 1 if no marks, else 0.
; Register AX is destroyed.
;-
strstk_pop_mark proc near
	call	strstk_goto_mark
	call	strstk_kill_mark
	ret
strstk_pop_mark endp



;+
; FUNCTION : strstk_goto_mark
;
;	Sets the current string pointer to the string associated with the
;	topmost marker on the marker stack.
;
; Parameters:
;	BX	:= address of buffer descriptor
;
; Returns:
;	CF = 1 if no markers, else 0.
; Register AX is destroyed.
;-
strstk_goto_mark proc near
	mov	ax,[bx].high_end
	cmp	ax,[bx].topmark
	jb	@strstk_goto_mark_99	;No marks
	mov	ax,[bx].topmark
	mov	[bx].cur,ax		;Update current string ptr
@strstk_goto_mark_99:
	ret
strstk_goto_mark endp


;+
; FUNCTION : strstk_purge_marks
;
;	Deletes all marks that point to the sentinel string. The marker
;	stack is compacted.
;
; Parameters:
;	BX	:= address of buffer descriptor
;
; Returns:
;	Nothing.
; Register(s)  AX,CX are destroyed.
;-
strstk_purge_marks proc near
	@save	si,di
	mov	cx,[bx].low_end
	inc	cx		;CX = sentinel string trailer
	mov	di,[bx].high_end
	inc	di
	mov	si,di
@strstk_purge_marks_10:		;SI = last marker location examined
				;DI = last marker location stored
	cmp	si,[bx].topmark	;Checked all markers ?
	je	@strstk_purge_marks_99 ;Yes, exit
	dec	si
	dec	si		;Next location to check
	mov	ax,[si]		;Marker value
	cmp	ax,cx		;Points to sentinel ?
	jg	@strstk_purge_marks_10 ;No, go check next
	dec	di
	dec	di		;DI = next location to store
	mov	[di],ax		;Store marker
	jmp	short @strstk_purge_marks_10
@strstk_purge_marks_99:
	mov	[bx].topmark,di	;Store new top of marker stack
	@restore
	ret
strstk_purge_marks endp

	ENDIF				;WANT_MARKERS

CSEG	ENDS

	END

⌨️ 快捷键说明

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