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

📄 ssfor.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 2 页
字号:
page	49,132
TITLE	ssfor	- scan support for For/Next
;***
;ssfor.asm
;
;	Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;	Scan For/Next.
;
;	For executors utilize a For block that is allocated by the scanner.
;	The allocation is from the frame.
;
;	For opcode variants are:
;	  (IdLd,exp,exp[,exp]) opStFor<Step|> (UNDEFINED,UNDEFINED)
;
;	For executor variants are:
;	  (IdRf,exp,exp[,exp]) exStFor<Step|><I2|I4|R4|R8|CY> (oFrame,oTxNext)
;
;	where:
;
;	oFrame	   is the offset to the For block, which contains step and limit
;	oTxNext    is the oTx of the oTx operand of the Next associated with
;		   this For.  The For executor uses this oTx to branch to the
;		   Next executor to do the limit test for the first iteration.
;
;	Next opcode variants are:
;	   ([IdLd|]) opStNext<Id|> (UNDEFINED,UNDEFINED)
;
;	where:
;	<Id|>	indicates whether the user labeled the Next.
;
;	The statement:
;	Next i,j,k
;	maps to several opStNextId opcodes.
;
;	The Next executor variants are:
;	   (IdRf) exStNext<Id|><Step|><I2|I4|R4|R8|CY>
;
;	The IdLd's of both For and Next are converted to IdRf.
;	The scanner supplies the IdRf in the case that the Next is a
;	opStNext.  However, this Id is not listed and is removed at descan.
;
;	Not all executor variants are unique.  For example, the R8 variant
;	of For supplies a Step of 1 if the user does not so specify.  There
;	need be no Step versions of R8 Next.
;
;Exceptions:
;	Errors detected during For/Next scanning are:
;	- Nesting errors (For without Next and Next without For).
;	- Variable type errors (SD or user data types, arrays, or
;	  array elements
;
;For to Next binding:
;			+------------------------+
;			|			 V
;	exStFor (oFrame,oTx) ... exStNext (oFrame,oTx)
;			    ^			   |
;			    +----------------------+
;
;
;****************************************************************************

	.xlist
	include 	version.inc
	IncludeOnce	context
	IncludeOnce	qbimsgs
	IncludeOnce	scanner
	IncludeOnce	ssint
	IncludeOnce	txtmgr
	IncludeOnce	variable
	.list

assumes ds, DATA
assumes es, NOTHING
assumes ss, DATA
assumes cs, SCAN

sBegin	SCAN
subttl	For
page
;***
;Ss_For - Scan For statement
;Purpose:
;
;   Scan For statement.  The following tasks are performed:
;	1. Make a For scan stack entry - each item is a word:
;	    For identifier flags
;		STYP_For
;		STYP_Step
;	    oTx of For statement
;	    oTx for start of EXIT For chain (initially UNDEFINED)
;	    oTx of exIdRf opcode
;	    oTyp of For index
;
;	2. Convert IdLd to IdRf.  Coerce step, limit, and initial value
;	   to the type of the index variable.
;
;	3. Map and emit the executor
;	   Executor calculation involves these factors:
;	    1. opcode to exe map For this opcode
;	       From mpOpExe
;	    2. Direct mode or main level code
;	       From grsCur
;	    3. Data type of index variable
;	       From Ld stack entry
;	    4. Whether Step is present.
;	       From RULE table index
;
;***************************************************************************
.erre	low STYP_Step	;The following code and PEROPCOD.TXT assume that the
			;STYP_Step bit is one of the bits in the low byte.
			;This flag is obtained from mpOpRule where it is set
			;as <low STYP_Step> and the mpOpRule byte is loaded into
			;the low byte below.
SsProc	For,Rude
;Calculate STYP_Step for this For
	push	bp			; Set up local frame pointer to ease
	mov	bp,sp			;	access to index variable oTyp
	shr	bx,1
	test	mpOpRule[bx],STYP_Step	; Step clause present?
	jz	NoStep			; Brif no step clause
	mov	ax,[bp+14]		; Get oTyp of index (Record = ET_RC)
	mov	cx,3			; Coerce three values
	jmp	short CoerceFor		

NoStep:					
	mov	ax,[bp+10]		; Get oTyp of index (Record = ET_RC)
	mov	cx,2			; Coerce two values
CoerceFor:				
	pop	bp			; Restore BP.  Discard frame pointer.
	.erre	ST_Typ_Mask EQ 0ffh	; Assure CBW is sufficient
	.erre	ET_MAX LT 80h		; Assure CBW is sufficient
	cbw				; Clear flags in scan stack
	call	SsCoerceN		

	xor	ch,ch
	mov	cl,mpOpRule[bx] 	;cx now has correct value for STYP_Step
	shl	bx,1			;Back to opcode * 2
	mov	dx,bx			; Save in dx
;Obtain the IdLd executor address, check type of For index.
	pop	ax			; oTyp of For index (Record=ET_RC)
	pop	bx			; oTx of For index
	push	ax
	call	MakeRef 		;Convert IdLd to IdRf
	pop	ax			;Get type back
	and	ax,ST_Typ_Mask		; Map to ET_type
	.erre	ET_RC EQ 0		; Assure JZ is sufficient
	jz	ForTypeBad		; For index is a record
	.erre	ST_Typ_Mask EQ 0ffh	; Assure we can use AL
	cmp	al,ET_MaxNum		; Numeric type?
	jbe	ForTypeOK		
ForTypeBad:				
	mov	al,ET_I2		; Leave a valid type
ForTypeOK:
	push	ax			;FRAME gets type
	push	bx			; FRAME gets IdRf executor oTx

;Begin mapping to executor
	dec	ax
	shl	ax,1			;AX = zero relative word offset
	mov	bx,dx			; opcode*2 back to bx
	mov	bx,mpOpExe[bx]		;Address of executor map
	add	bx,ax			;Address of executor for this For
	mov	ax,word ptr cs:[bx]	;Load ...
	STOSWTX 			;... and emit the executor
	MOVSWTX 			;Copy current For block offset

.errnz	UNDEFINED - 0FFFFH
	mov	dx,UNDEFINED		;Get an UNDEFINED to push as the
					; EXIT For link head
	push	dx			;FRAME gets initial EXIT For link
	push	di			;FRAME gets address of oTx for this For
	or	cx,STYP_For		;cx = scan frame identifier
	push	cx			;FRAME gets frame identifier
	MOVSWTX				;Skip over oTx operand
	jmp	[ScanRet]		; and back to the scan loop


subttl	ForBlockAlloc - allocate the For block
page

;***
;ForBlockAlloc - allocate the For block
;Purpose:
;	For/Next executors require a For block to store limit and Step.
;	This block is allocated when scanning For.
;
;	The block is allocated from the current frame (the same as
;	frame space for dynamic variables).
;
;	A For may be scanned several times during the course of user program
;	development.  For blocks may be active during user edition.  For
;	block allocation supports CONT by utilizing the currently allocated
;	block for the For if one exists.
;
;Input:
;	cx = STYP_Step
;	dx = data type of For
;
;Output:
;	ax = new For block offset
;Preserves:
;	bx,cx,dx
;***************************************************************************
ForBlockAlloc:
;Calculate bytes required for this For block
	mov	ax,dx
	call	CbTypOTypSCAN		; bytes for data type
	cmp	dx,ET_I2		;Only I2 can have no Step
	jnz	ForStepCom		;  as For supplies Step for other types
	test	cl,STYP_Step		;Is Step present?
	jz	ForNoStepCom		;No Step, so ax = For block size
ForStepCom:
	shl	ax,1			;Times 2 for Step
ForNoStepCom:
;ax = bytes for For block
	test	byte ptr [grs.GRS_oRsCur+1],80H	;Module or procedure level?
	jnz	ProcLevel
	add	ax,mrsCur.MRS_cbFrameVars	;Get current top of frame
	mov	mrsCur.MRS_cbFrameVars,ax	;Put back new top of frame
	jmp	short MakeOBP

ProcLevel:
;Allocate the For block from the frame of the current procedure.
	add	ax,prsCur.PRS_cbFrameVars	;Get current top of frame
	mov	prsCur.PRS_cbFrameVars,ax	;Put back new top of frame
MakeOBP:
	neg	ax				;oBP
	ret

subttl	For Opcode to Executor maps
page
public	mStForOpExe
mStForOpExe:
	DWEXT exStForI2
	DWEXT exStForI4
	DWEXT exStForR4
	DWEXT exStForR8

public	mStForStepOpExe
mStForStepOpExe:
	DWEXT exStForStepI2
	DWEXT exStForStepI4
	DWEXT exStForStepR4
	DWEXT exStForStepR8

subttl	Next
page
;***
;Ss_Next, Ss_NextId
;Purpose:
;	Scan For/Next.
;
;	Next opcode variants are:
;	   ([IdLd|]) opStNext<Id|> (UNDEFINED,UNDEFINED)
;
;	where:
;	<Id|>	indicates whether the user labeled the Next.
;
;	The statement:
;	Next i,j,k
;	maps to several opStNextId opcodes.
;
;	The Next executor variants are:
;	   (IdRf) exStNext<Id|><Step|><I2|I4|R4|R8|CY>
;
;	The scanner supplies the IdRf in the case that the Next is a
;	opStNext.  However, this Id is not listed and is removed at descan.
;	Bit 0 of the oBP field is set if the IdRf was not inserted (due
;	to out-of-memory or a previous error).
;
;	Not all executor variants are unique.  For example, the R8 variant
;	of For supplies a Step of 1 if the user does not so specify.  There
;	need be only a Step versions of R8 Next.
;
;	For blocks are allocated at Next scan time.  If the For already
;	has a valid oBP (i.e., not -1), then it is used.  Otherwise,
;	if the Next has a valid oBP, it is used.  If neither are valid,
;	then a new oBP is allocated and CantCont is set.  This method allows
;	either a For or Next (but not both) to be edited and still retain
;	their previous For block.
;
;	However, a previous For block can only be used if its type and size
;	have not changed.  This can only happen when the For is edited, not
;	the Next.  In order to tell, the oText field of the Next is set at
;	descan time to have the oTyp and the Step flag.  (Step only matters for
;	I2, where a step of 1 uses a separate executor instead of a word in
;	the For block.)
;
;For to Next binding:
;			+------------------------+
;			|			 V
;	exStFor (oFrame,oTx) ... exStNext (oFrame,oTx)
;			    ^			   |
;			    +----------------------+
;
;Scan time tasks include:
;	1. Detect nesting error (Next w/o For)
;	2. Change IdLd to IdRf, or insert IdRf if not an Id variant of Next.
;	3. Calculate and emit the executor
;	   Factors include:

⌨️ 快捷键说明

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