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

📄 txtfind.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 4 页
字号:
	;********************************************************

	mov	si,[otxStart]		;ds:si = ptr to txt table of opcode
					;to start search with
	or	di,di			;is this a TxtSkip request?
	jne	NotSkipOp		;brif not

; We just want to skip one opcode in the text table.
;	ds:si - points to opcode to skip.

	lodsw		 		;ax = current opcode from text table
	test	[flags],TFC_FindExec
	je	SkipOpNotExec		;brif scanState == SS_EXECUTABLE

; map executor to opcode
	xchg	bx,ax			;bx = executor's adr
	mov	ax,es:[bx-2]		;ax = executor's opcode
SkipOpNotExec:
	and	ah,HIGH OPCODE_MASK	;upper bits sometimes used for operands
	mov	dx,ax
	mov	bx,dx			;bx = opcode
	mov	al,cs:[mpOpAtr_UNDONE + bx]    ; al = #bytes of operands
	and	ax,OPA_CntMask		;Isolate attribute count
.errnz	OPA_CntMask AND 0FF00H		;must use ax in next line if not
	cmp	al,OPA_CntMask		;Test for cnt field in operand
	jne	SkipNotVar		;brif variable length operand count

	lodsw				;ax = # bytes of operands
	inc	ax			;round up to odd count as follows:
	and	al,-2			; {0,1,2,3,4,...} => {1,3,3,5,5,...}
SkipNotVar:
	add	si,ax			;si points to next opcode
	push	ss
	pop	ds			;ds -> DGROUP
	DJMP	jmp SHORT FindExit

J1_FindOpExec:
	DJMP	jmp SHORT FindOpExec

; Search for first opcode in text table which matches an opcode specified
; in the search table.

NotSkipOp:
	test	[flags],TFC_FindExec
	jne	J1_FindOpExec		;brif scanState == SS_EXECUTABLE

	test	[flags],TFC_FindNext
	je	TestOp			;brif entry point was TxtFindOp[DS]
	lodsw		 		;ax = current opcode from text table

	and	ah,HIGH OPCODE_MASK	;upper bits sometimes used for operands
	mov	dx,ax

	;Register conventions for TxtFind loop
	;ds:si	- pts to current opcode in txt table
	;ss:di	- pts to base of search opcode bit array
	;dx	- current opcode

TryNext:
	mov	bx,dx			;bx = opcode
	mov	al,cs:[mpOpAtr_UNDONE + bx]    ; al = #bytes of operands
	and	ax,OPA_CntMask		;Isolate attribute count
.errnz	OPA_CntMask AND 0FF00H		;must use ax in next line if not
	cmp	al,OPA_CntMask		;Test for cnt field in operand
	je	VarLenOpcode		;brif variable length operand count
VarLenRet:
	add	si,ax			;si points to next opcode
TestOp:
	lodsw		 		;ax=opcode to search for (from txt tbl)
	and	ah,HIGH OPCODE_MASK	;upper bits sometimes used for operands

; test to see if opcode bit is set in search table

	mov	dx,ax			;dx = current opcode
	mov	bx,ax
	shr	bx,1			;divide opcode by 8 to get byte index
	shr	bx,1			;into bit-packed array for this opcode
	shr	bx,1			;bx=byte in bit packed array for opcode
	and	al,7			;al = bit number in array byte
	mov	cl,al
	mov	al,1
	shl	al,cl			;al = bit mask for opcode in array byte
	test	ss:[di+bx],al		;test opcode bit for match
	jz	TryNext 		;brif no match, try next opcode

; We have found the opcode.  We reenter here from FindOpExec.
;    si - pts two bytes past found opcode.

FoundOpcode:
	dec	si
	dec	si			;si points to found opcode

	push	ss
	pop	ds			;restore ds -> DGROUP
assumes ds,DGROUP
					;es still points to CODE
	mov	di,[pOpcodeList]	;es:di = ptr to original list of opcodes
	inc	di
	inc	di			;advance past size of table to first op
	mov	cx,-1
	xchg	ax,dx			;ax = opcode found
	repne	scasw			;search for found opcode in table
	not	cx			;cx = index+1 into table where opcode
					;was found
	dec	cx			;cx = index
	DbAssertRel cx,be,[cOpcodes],CP,<Error In TxtFindOp: Incorrect opTable>
	mov	[txtFindIndex],cl	;return index for matched opcode in
					; global static variable txtFindIndex
	mov	dl,cl			;return txtFindIndex in dl
FindExit:
	xchg	ax,si			;return offset in ax
	DbSegMoveOn			;OK to move segs again
cEnd	;TxtFindOpcode

; We have a variable length opcode in SS_RUDE or SS_PARSE state.
; Pick up the byte count of the operands, and skip to the next opcode.
;
VarLenOpcode:
	lodsw				;ax = # bytes of operands
	inc	ax			;round up to odd count as follows:
	and	al,-2			; {0,1,2,3,4,...} => {1,3,3,5,5,...}
	jmp	SHORT VarLenRet


	;********************************************************
	;NOTE: DS register points to text table until end-of-loop
	;      ES points to CODE, where opcodes in execute state can be accessed
	;      SS still points to DGROUP, so local vars can be accessed
	;********************************************************
assumes	ds,NOTHING

; We are in SS_EXECUTE state.  Search the pcode for an opcode from
; the passed table.

FindOpExec:
	test	[flags],TFC_FindNext
	je	TestOpExec		;brif entry point was TxtFindOp[DS]
	lodsw		 		;ax = current opcode from text table
; map executor to opcode
	xchg	bx,ax			;bx = executor's adr
	mov	ax,es:[bx-2]		;ax = executor's opcode

	and	ah,HIGH OPCODE_MASK	;upper bits sometimes used for operands
	mov	dx,ax

	;Register conventions for FinOpExec loop
	;ds:si	- pts to current opcode in txt table
	;ss:di	- pts to base of search opcode bit array
	;es	- pts to CODE seg for execute state searches
	;dx	- current opcode

TryNextExec:
	mov	bx,dx			;bx = opcode
	mov	al,cs:[mpOpAtr_UNDONE + bx]    ; al = #bytes of operands
	and	ax,OPA_CntMask		;Isolate attribute count
.errnz	OPA_CntMask AND 0FF00H		;must use ax in next line if not
	cmp	al,OPA_CntMask		;Test for cnt field in operand
	je	VarLenOpcodeExec	;brif variable length operand count
VarLenExecRet:
	add	si,ax			;si points to next opcode
TestOpExec:
	lodsw		 		;ax=opcode to search for (from txt tbl)

; map executor to opcode
	mov	bx,ax			;bx = executor's adr
	mov	ax,es:[bx-2]		;ax = executor's opcode

	and	ah,HIGH OPCODE_MASK	;upper bits sometimes used for operands

; test to see if opcode bit is set in search table

	mov	dx,ax			;dx = current opcode
	mov	bx,ax
	shr	bx,1			;divide opcode by 8 to get byte index
	shr	bx,1			;into bit-packed array for this opcode
	shr	bx,1			;bx=byte in bit packed array for opcode
	and	al,7			;al = bit number in array byte
	mov	cl,al
	mov	al,1
	shl	al,cl			;al = bit mask for opcode in array byte
	test	ss:[di+bx],al		;test opcode bit for match
	jz	TryNextExec		;brif no match, try next opcode
	jmp	FoundOpcode

; We have a variable length opcode in SS_EXECUTE state.
; Pick up the byte count of the operands, and skip to the next opcode.
;
VarLenOpcodeExec:
	lodsw				;ax = # bytes of operands
	inc	ax			;round up to odd count as follows:
	and	al,-2			; {0,1,2,3,4,...} => {1,3,3,5,5,...}
	jmp	SHORT VarLenExecRet

assumes ds,DGROUP


;*************************************************************************
; TxtFindOpFar
; Purpose:
;	Same as TxtFindOp, only has a FAR interface
;
;*************************************************************************
cProc	TxtFindOpFar,<PUBLIC,FAR>
	parmW	otxStart
	parmW	pOpcodeList
cBegin
	cCall	TxtFindOp,<otxStart,pOpcodeList>
cEnd

;*************************************************************************
; TxtFindNextOpFar
; Purpose:
;	Same as TxtFindNextOp, only has a FAR interface
;
;*************************************************************************
cProc	TxtFindNextOpFar,<PUBLIC,FAR>
	parmW	otxStart
	parmW	pOpcodeList
cBegin
	cCall	TxtFindNextOp,<otxStart,pOpcodeList>
cEnd

;*************************************************************************
; TxtSkipOp
; Purpose:
;	Skip over 1 opcode.  Text table can be in any scan-state.
; Entry:
;	grs.fDirect, grs.oRsCur identify text table
;	ax = offset of opcode to be skipped
; Exit:
;	ax = offset beyond skipped opcode
;
;*************************************************************************
cProc	TxtSkipOp,<PUBLIC,NEAR>
cBegin
	push	ax
	PUSHI	ax,0
	cCall	TxtFindNextOp		;ax = result
cEnd

;*************************************************************************
; TxtSkipOpFar
; Purpose:
;	Same as TxtSkipOp, only has a FAR interface, and otx is in BX
;
;*************************************************************************
cProc	TxtSkipOpFar,<PUBLIC,FAR>
cBegin
	xchg	ax, bx			; ax = input value
	cCall	TxtSkipOp		;ax = result
cEnd

;*************************************************************************
; TxtChkValidOpsExec
; Purpose:
;	Verify that expected opcodes exist in an oTx range. The text
;	table is assumed to be in SS_EXECUTE state.  Ensures that only
;	white space and remarks come between a SELECT CASE and the
;	first CASE, END SELECT clause.
; Entry:
;	parm1: ushort oTxFirst - oTx of first opcode of interest.
;	parm2: ushort oTxLast  - oTx of last opcode of interest.
; Exit:
;	ax = oTx of first opcode not found in list, or oTxLast if all opcodes
;	     valid.
;	dx == 0 if all opcodes valid.
; Preserves:
;	si, di
;*************************************************************************
cProc	TxtChkValidOpsExec,<PUBLIC,FAR>,<si>	
parmW	oTxFirst
parmW	oTxLast
cBegin
	DbChk	Otx,otxFirst		
	DbChk	Otx,otxLast		
	mov	ax,oTxFirst		;start at first opcode of interest

TxtChkValidLoop:
	push	ax			;stack oTxCur for Second TxtFind call

	push	ax
	PUSHI	ax,<codeOFFSET tOpSelect> ;get valid op table addr
	call	TxtFindNextOpExec	;ax = oTx of next opcode in list
	pop	bx			;recover oTxCur

	cmp	dl,SEL_opValidMax	;is op within valid range?
	ja	TxtChkValidX		;ax = oTx of bad guy, psw.z clear

	xchg	ax,si			;remember found opcode

	push	bx			;oTxCur
	PUSHI	ax,0			;find next op (oTxCur already stacked)
	cCall	TxtFindNextOpExec	;ax = oTx of next opcode
	cmp	ax,si			;next opcode should have been in list
	jnz	TxtChkValidX		;brif not - offender in AX, psw.z clear

	cmp	ax,oTxLast		;more to search?
	jb	TxtChkValidLoop 	;brif so.

	cmp	ax,ax			;all hunky dory - set psw.z

TxtChkValidX:
	mov	dx,sp			
	jnz	@F			; brif not all opcodes valid

	sub	dx,dx			
@@:					
cEnd

;*************************************************************************
; LOCAL FindBol
; Purpose:
;	Search the current text table from its start for a certain
;	beginning of line opcode, given the following 2 stopping conditions:
;	1 - stop after cx beginning of lines have been seen,
;	2 - stop after going beyond a certain text offset
; NOTE: This routine is crucial for PageUp speed.  Thus some code has been
;	duplicated from TxtFindOpcode to help Page Up performance.
; Entry:
;	ax = txt offset to stop at
;	cx = line # to stop at
; Exit:
;	grs.fDirect is reset to FALSE
;	ax = text offset to beginning of line opcode
;	dx = text offset to beginning of line opcode for previous line
;	cx = initial cx - # lines skipped
;	[fLnNotIncl] = zero if given line was an INCLUDEd line
;
; For example, if pcode contained:
;	[0]opBol,[2]opStop,[4]opBol,[6]opStop,[8]opEndProg,[0A]opEot
; The following inputs would produce the following results:
;	  ax   cx  =>	ax   cx   dx
;	0000 FFFF  => 0004 FFFF 0000
;	0001 FFFF  => 0004 FFFF 0000
;	0002 FFFF  => 0004 FFFF 0000
;	0003 FFFF  => 0004 FFFF 0000
;	0004 FFFF  => 0008 FFFE 0004
;	0005 FFFF  => 0008 FFFE 0004
;	0006 FFFF  => 0008 FFFE 0004
;	0007 FFFF  => 0008 FFFE 0004
;	0008 FFFF  => 0008 FFFE 0004
;	FFFF 0000  => 0000 0000 0000
;	FFFF 0001  => 0004 0000 0000
;	FFFF 0002  => 0008 0000 0004
;	FFFF 0003  => 0008 0000 0004
;
;*************************************************************************

StartFromTop:
	xor	ax,ax			
	mov	[lnFindLast],ax		;set lnFindLast to line # zero

;We must search for the first Bol since the scanner can insert opNoList's
;before the first line.
	push	cx			;save skip line count
	push	ax			
	PUSHI	ax,<CODEOFFSET tOpBol>	;pass ptr to start-of-line table
	call	TxtFindOp		;ax = offset to 1st opBos/opBol/opEot
	pop	cx			;restore cx = skip line count
	mov 	dx,ax			;dx = offset of 0th line

⌨️ 快捷键说明

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