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

📄 ssrude.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 4 页
字号:
page	49,132
	TITLE	ssrude - Scan and Descan support routines for SS_RUDE mode
;***
;ssrude - Scan and descan support for SS_RUDE mode
;
;	Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;
;	Certain opcodes require work to scan from SS_RUDE to SS_PARSE and
;	back.  This module contains most of the dispatched entrypoints
;	for performing this work.
;
;	The connection between scan routines and descan routines is as
;	follows:
;	- Each scan routine is declared with macro SsVProc.  If there is
;	  work required to get to/from SS_RUDE then the optional parameter
;	  "rude" is specified on the SsVProc invocation.  Each scan dispatch
;	  so declared will have the address of the rude mode scan/descan
;	  routine stored in the scanner segment at the SsVProc entrypoint -
;	  SsVProcRude.
;	- The scan and descan main loop will vector through the above address
;	  when the mpOpAtr entry for the opcode indicates that work is required
;	  to get to or from SS_RUDE mode.
;	- The dispatched routine will determine whether the current operation
;	  is scan or descan by branching on PSW.Z.  PSW.Z set indicates
;	  descan from SS_PARSE to SS_RUDE.  PSW.Z clear indicates scan from
;	  SS_RUDE to SS_PARSE.
;
;	Rude scan/descan dispatches are entered with the following convention:
;	ax = oTyp from rule table (for opId's only)
;	cx = opcode
;	dx = pVariable table  (Descan to SS_RUDE only)
;	si = descan source
;	di = descan destination
;	es = text segment
;	PSW.Z set indicates SS_PARSE -> SS_RUDE
;
;       Special Cases:
;	-------------
;	CONSTants
;		When an opStConst statement is seen, we continue scanning
;		IdLd pcodes normally, except that we give an error if 
;		MakeVariable finds one of these that is not already created
;		as a CONSTant.  Each time we find an IdSt pcode, we call
;		ScanAndExec with the pcode expression we've just scanned
;		ScanAndExec calls MakeVariable to create the new CONSTant
;		variable, scans the expression to SS_EXECUTE, executes it
;		(thus storing the value of the expression in the CONSTant),
;		and then descans the expression back to SS_PARSE.
;
;
;*****************************************************************************

	.xlist
	include		version.inc
SSRUDE_ASM	= ON
	IncludeOnce	architec
	IncludeOnce	context
	IncludeOnce	names
	IncludeOnce	opcodes
;	IncludeOnce	opid
;	IncludeOnce	opmin
	IncludeOnce	optables
	IncludeOnce	parser
	IncludeOnce	pcode
	IncludeOnce	qbimsgs
	IncludeOnce	scanner
	IncludeOnce	ssint
	IncludeOnce	txtmgr
	IncludeOnce	ui
	IncludeOnce	variable
	.list

;Invoked after calling any function which could cause heap movement
; and thus, movement of the current text table being scanned.
; This macro preserves all registers except ES (including flags)
;
SsRefreshES MACRO
	GETSEGTXTCUR			; ES = current pcode segment,
					; all other registers preserved,
					; including flags
	ENDM


assumes ds, DATA
assumes es, NOTHING
assumes SS, DATA

sBegin	DATA
	globalW	oNamOfPrsCur,UNDEFINED	;Speed optimization for rude scan
					;  set up here, used by varmgr
	staticW	otxConstCur,0		;otx to start of current CONST expr
					;  if scanning a CONST stmt, else 0
	staticW	varFlags_Reset,0	;Normally 0, set to FVI_SHARED, 
					;  FVI_STATIC, FVI_COMMON, FVI_AUTO,
					;  or FVI_PUBLIC whenever one of those 
					;  bits must be temporarily reset
					;  in mkVar.flags by IdLd. 
					;  Always reset by HandleId.
	staticB fErrWithinOp,0		;set to 1 if an error occurred within
					;  the operand of a big opcode (like
					;  opStDeclare), so error can be
					;  reported at the operand.
	staticW spErrorRestore,0	;used for error recovery
sEnd	DATA

sBegin	SCAN
assumes cs,SCAN
page

;***
;SsRudeScan
;Purpose:
;	Move text between SS_PARSE and SS_RUDE.
;
;	This routine dispatches to the same entrypoint for moving
;	text in either direction.  The individual entrypoints must
;	examine PSW to determine which direction to take the current
;	opcode.
;
;	Rude mode register convention is:
;	ax	 = opcode
;	dx	 = mrsCur.MRS_bdVar_pb (if not SizeD)
;	es:si/di = source and destination pointers
;	PSW.Z	   set indicates descan from SS_PARSE to SS_RUDE
;		   reset indicates scan from SS_RUDE to SS_PARSE
;
;	Dispatching is performed for all opcodes.  Table space is
;	conserved by placing the rude dispatch as a prefix to the non-rude
;	scan dispatch entrypoint for the opcode.  Note that this restriction
;	limits the resolution of the rude scan dispatching to that of the
;	standard scan dispatching.  In other words, there are no two opcodes
;	with individual rude dispatches that have a common standard scan
;	dispatch.
;
;	A further space savings is that not all standard scan dispatches
;	have rude dispatch prefixes.  The scan entrypoint declaration macro
;	SsProc has a second parameter that determines whether the rude
;	dispatch is required.  The opcode atribute table mpOpAtr contains
;	a bit (OPA_fSsRude) that indicates to the rude scan loop whether
;	there is work to go to/from SS_RUDE for that opcode.  All opcodes
;	that do not have this bit set are dispatched to a common entrypoint
;	that skips operands to the next opcode.
;
;	The rude scans are wholly space invarient.  The rude scan is
;	a scan in place - it is not necessary for dispatch points to emit
;	text that is not modified (for instance, it is not necessary to
;	emit the opcode).
;
;	Descanning from SS_PARSE to SS_RUDE can cause no errors.
;
;	Scanning from SS_RUDE to SS_PARSE can cause errors.  When a dispatch
;	point finds an error it must:
;	- record the variable in a static variable.
;	- recover the opcode that it is processing to a consistent (RUDE or
;	  PARSE mode state (all operands must be in the same state).
;	- replace the first SS_RUDE mode opcode in the text table with an
;	  opEot.
;	- restart SsRudeScan to descan the pcode up to the opEot.
;	- replace the opEot with the saved opcode.
;	- return, reporting the error.
;
;NOTE:	This is not a recursive scheme; an alternate reentry point is
;	used to descan the pcode, and the opEot detects whether an error
;	has occurred or not. Aside from the above mechanism, this routine
;	is NOT reentrant.
;
;	Error control variables are:
;	SsErrOTx	- text offset of pcode which was replaced by opEot
;				descanner expects this to be UNDEFINED if no
;				error has occured.
;	SsErr		- error code to be returned by scanner.
;	SsErrOpcode	- opcode which was replaced by opEot
;
;Entry:
;	parmW	target scan state (must be SS_RUDE or SS_PARSE)
;Exit:
;	ax == 0  ----> Output registers are the same as for GetTXDInfo
;	ax != 0  ----> ax = error code
;                      [grs.GRS_otxCur] = text offset to error.  If low
;		       bit is set, error is within an operand (like opStSub,
;		       opStDeclare, etc.), so caller can position cursor
;		       exactly to the error token.
;
;************************************************************
cProc	SsRudeScan,<PUBLIC,FNEAR>,<si,di>	
	parmB	TargetState
cBegin

	mov	[spErrorRestore],sp	;in case an error occurs with 
					;  stack in an intermediate state
	sub	ax,ax
	mov	[fErrWithinOp],al
	dec	ax			;ax = UNDEFINED
	mov	[SsErrOTx],ax		;initialize in case we're descanning	
	cmp	[TargetState],SS_RUDE	;Indicate scan or descan
	jz	SsRudeDeScan		;brif descanning to SS_RUDE

	call	OtxDefType0Far		; set all 26 letter default
					;	types to initial default
SkipDT:
	cmp	[grs.GRS_fDirect],FALSE
	jz	Not_Direct		;brif not scanning direct mode buffer

	push	[grs.GRS_otxCONT]	; In direct mode,
	call	OtxDefTypeCurFar	; set all 26 letter defaults to
					; values at the current program counter.
					; If cant CONT (i.e. UNDEFINED), set
					; them to their value at EOT
Not_Direct:
	DbAssertRelB [TargetState],z,SS_PARSE,SCAN,<ssrude: invalid target state>
	cmp	[grs.GRS_oPrsCur],UNDEFINED
	jz	SsRudeScanErr		;brif not scanning a procedure table

	cmp	[grs.GRS_fDirect],FALSE
	jnz	SsRudeScanErr		;ignore prsCur stuff if in Direct Mode

	push	[prsCur.PRS_ogNam]	
	call	ONamOfOgNamFar		;must succeed (as prs already exists)
	DbAssertRel  ax,nz,0,SCAN,<SsRudeScan: [6] ONamOfOgNam returned an error>
	mov	[oNamOfPrsCur],ax	;speed optimization - used by varmgr

	call	MakePrsTVar		;make var hash table for prsCur
	or	ax,ax			;error return?
	jnz	SsRudeScanErr		;  brif not
	
	PUSHI	ax,ER_OM		;insufficient memory - - exit
	jmp	ErrExit

SsRudeDeScan:				;only get here if we're descanning
	DbAssertRelB [grs.GRS_fDirect],z,FALSE,SCAN,<ssrudedescan: fDirect TRUE>
	;don't want to reset otxCONT when dealing with the Direct Mode buffer,
	;  so we're counting on the fact that we never descan the D.M. buffer
	mov	[grs.GRS_otxCONT],UNDEFINED
					;ensure this is correctly set whenever
					;  we descan any text table
SsRudeScanErr:				;reentry point in case of scan error
	SsRefreshES			;es = cur pcode seg (heap movement)
	mov	dx,[mrsCur.MRS_bdVar.BD_pb] ;Address of variable table
	SetStartOtx	si		;Start scan from the top
	mov	di,si			;Destination = source

RudeLoop:
	LODSWTX 			;Pick up opcode
	mov	bx,ax
	and	bx,OPCODE_MASK		; ax is actual opcode, bx is
					; masked opcode
	DbAssertRel	bx,be,op_max,SCAN,<Rude Scan Loop: opcode out of range.>
	DbAssertRel	spErrorRestore,e,sp,SCAN,<Rude Scan Loop: Stack Use Err.>
	DbAssertRel	si,ae,di,SCAN,<Rude Scan Loop: Emit overran source.>
	DbAssertRel	es,z,EScheckRude,SCAN,<Rude Scan Loop: ES not preserved>
	mov	cl,mpOpAtr.[bx]		;load attribute byte
	test	cl,OPA_fSsRude		;Test for scan work for rude mode
	jnz	RudeScanWork		;Work required to get to SS_RUDE

Ssv_NOps:				;Skip opcode and operands
	and	cx,OPA_CntMask		;get the operand count from attribute
	.errnz	OPA_CntMask AND 0FF00H	;must use cx in next line if non-zero
	cmp	cl,OPA_CntMask		;check for cnt field in operand
	jz	Fetch_Cnt		;  brif there is a cnt field
Bump_TxtPtr:
	add	si,cx
	jmp	RudeLoop		;start over for next operand

Fetch_Cnt:
	LODSWTX				;load the cnt field
	mov	cx,ax
	inc	cx
	and	cl,0FEH			;round up to even byte count
	jmp	short Bump_TxtPtr

RudeScanWork:
	mov	di,si			;Bring destination in line with source
	mov	al,ah			; al contains oTyp for opId's,
					; but left shifted
	SHIFT	H,R,al,2		; shift al right two bits
	.errnz	OPCODE_MASK - 03FFH	; 03FF mask implies it's shifted
					; left two bits.
	cbw				;ax = oTyp for opId's
	mov	cx,bx			; cx = masked opcode
	shl	bx,1			;To word offset
	mov	bx,[bx].mpOpScanDisp	;Scan dispatch address
	DbPub DispSSR			;a handy public for debugging
	cmp	[TargetState],SS_RUDE	;Indicate scan or descan
DispSSR:
	jmp	word ptr cs:[bx].SsProcRude	;Dispatch to RUDE scanner

;***
;SsVProc Eot
;Purpose:
;	Rude scan/descan dispatch.
;
;Input:
;	Standard rude dispatch
;Output:
;************************************************************
SsVProc Eot
	jnz	SsRudeOkX		;if scanning and got to opEot, no errors

	mov	ax,UNDEFINED
	cmp	[grs.GRS_fDirect],FALSE
	jnz	Eot_Cont1

	mov	bx,dataOFFSET mrsCur
	cmp	[grs.GRS_oPrsCur],ax
	jz	Eot_Cont		;brif not scanning a procedure table

	mov	bx,dataOFFSET prsCur
	mov	[prsCur.PRS_oVarHash],ax
					;must ensure this gets reset here, in
					;  case we were called to descan a
					;  prs with an empty text table
Eot_Cont:
	.errnz	PRS_cbFrameVars - MRS_cbFrameVars
	mov	[bx.PRS_cbFrameVars],-FR_FirstVar	
					; reset to init. value. This value
					; is 2 to account for the fact that
					; b$curframe is always pushed on the
					; stack after bp, so we treat this
					; word as a frame var for ref'ing
					; the real frame vars off of bp
Eot_Cont1:
					;reset to default
	cmp	[SsErrOTx],ax		;did we just descan due to a scan err?
	jz	SsRudeOkX		;No error - exit.

	mov	di,[SsErrOTx]
	mov	ax,[SsErrOpcode]
	STOSWTX				;restore the saved opcode in text table
	push	[SsErr]			;in case ModuleRudeEdit changes this
ErrExit:
	cmp	[grs.GRS_fDirect],FALSE
	jnz	Eot_Err_Exit		;don't call ModuleRudeEdit if error
					;  in scanning Direct mode buffer - -
					;  no need to do so.
	call	ModuleRudeEditFar	;discard vartable, reset name table bits
	mov	[spErrorRestore],sp	;refresh (ModuleRudeEdit recursively
					; calls SsRudeScan which changes this)
Eot_Err_Exit:
	pop	ax			;retval
SsRudeErr:				;ax = error code, set carry and return
	jmp	short SsRudeX

SsRudeOkX:
	mov	al,[TargetState]
	cmp	[grs.GRS_fDirect],FALSE
	jnz	SsRudeX1		;brif just scanned direct mode buffer
	mov	[txdCur.TXD_scanState],al

	;in case we had a DEF FN without an END DEF (an error the execute
	;  scanner will catch), deactivate prsCur if the current text table
	;  is for mrsCur
	test	[txdCur.TXD_flags],FTX_mrs
	jz	SsRudeX1		;brif a prs is active

	call	PrsDeActivateFar	; in case we had a DEF FN w/o an END DEF
SsRudeX1:
	DbMessTimer	SCAN,<Leave SsRudeScan - >
	sub	ax,ax			; Indicate success
SsRudeX:
	mov	[oNamOfPrsCur],UNDEFINED ;reset to default value
cEnd

⌨️ 快捷键说明

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