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

📄 ssscan.asm

📁 Microsoft MS-DOS6.0 完整源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	TITLE	SSSCAN	-	Main Static Scanner Module
;***
;ssscan - Main static scanner module
;
;	Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;
;   This is the main static scanner module.  It contains all external
;   interfaces to the module.  These interfaces are:
;   ssscan	      - scans the current text table to executor mode.
;   SsDescan(toState) - descans current text table to the state specified
;			this state may be SS_PARSE or SS_RUDE.
;
;
;****************************************************************************

	.xlist
	include 	version.inc
SSSCAN_ASM	= ON
	IncludeOnce	context
	IncludeOnce	executor
	IncludeOnce	opmin
	IncludeOnce	opstmt
	IncludeOnce	optables
	IncludeOnce	pcode
	IncludeOnce	qbimsgs
	IncludeOnce	rtinterp
	IncludeOnce	ssint
	IncludeOnce	txtmgr
	IncludeOnce	variable
	.list

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

extrn	B$IFindEvHandler:far
extrn	exBolLab:far


	    extrn   DimImplicit:far	


sBegin	DATA

EmitErrOtx	dw	0

sEnd	DATA


sBegin	SCAN
assumes cs,SCAN

;*************************************************************************
;UpdateTxdBdl - Update the TXD or BDL for text table
;
; Purpose:
;
;   Update the txdCur (or the direct mode bdl) for this text table.
;
; Entry:
;
;   al = scanState
;   di = cbLogicalNew	    oTx of opEOT + 2
;
;   The structure txdCur identifies the current text table.
;   If grs.fDirect is TRUE, the direct mode text table (grs.bdlDirect)
;      is used instead.
;
; Preserves:
;
;   All
;
;*************************************************************************
UpdateTxdBdl:
	cmp	grs.GRS_fDirect,FALSE
	jne	DirectMode		;branch if in direct mode
	mov	txdCur.TXD_bdlText_cbLogical,di
	mov	txdCur.TXD_scanState,al
	ret

DirectMode:
	mov	[grs.GRS_bdlDirect_cbLogical],di
	ret

;***
; TxLnkInit
; Entry:
;	bx points to table to use for SsLinkCtl
; Exit:
;	ax = 0 (callers assume this)
; preserves: bx,dx (callers assume this)
;
;********************************************************
TxLnkInit PROC NEAR
	push	es
	push	di
	mov	SsLinkCtl,bx		;Save for scan dispatch routines
	push	ds
	pop	es
	mov	di,bx
	mov	cx,(size TXLNK)/2	;Count of bytes in structure
	xor	ax,ax			;Get a zero
	rep	stosw			;Initialize link controls to zero
	pop	di
	pop	es
	ret
TxLnkInit ENDP

;***
;ushort SsScan - Scan pcode from SS_PARSE to SS_EXECUTE
;
;Purpose:
;
;   In the case of an error, the pcode is left entirely
;   in the state in which the pcode was found.	An error
;   code is always returned.
;
;   This procedure causes memory allocations in the
;   interpreter and far heaps.
;
;   Certain scan routines push identified frames on the stack.
;   These frames must be uniquely identifiable, as other scan
;   routines must check to see if they exist.  At scan initialization,
;   an end-of-frame identifier is pushed on the stack, ensuring
;   that the bottom of the stack is not misinterpreted as some
;   particular scan stack entry.
;
;   NOTE: If grs.GRS_fDirect is TRUE on entry, txdCur should be
;	    ignored, and we should assume that the text table (whose
;	    segment is obtained via TxtSegCur) is in SS_RUDE, and
;	    must be scanned to SS_EXECUTE. Note also that the information
;	    in txdCur should be unchanged on return in this case.
;
;Algorithm:
;
;   Determine whether current text table is in SS_EXECUTE already
;      return if so
;   Grow the text table
;      If cbScanned = 0 then guess that cbScanned = 1.3 * cbText
;      Attempt to grow the text table by cbScanned
;	    error if NO growth possible
;      Move text up to end
;	    relink all links
;   Set up for main scan loop
;      install return address
;      set up es, si, di
;      push an end-of-stack frame identifier
;   Loop to completion
;   pop end-of-stack frame identifier
;   Return
;
;Entry:
;
;   grs.GRS_fDirect	 Current context information
;   rs	    mrsCur	 Current context information
;   ushort  oPrsCur	 Offset of current procedure.
;			    UNDEFINED = module
;   prs     prsCur	 Procedure context if
;			    oPrsCur != UNDEFINED
;
;Exit:
;
;   ax	    = 0 if no error occurred
;	      or
;	      error code
;   SsScan		 Standard BASIC error code
;   grs.context 	 Pcode address of the error
;			 or
;			 unmodified
;Exceptions:
;
;   None
;
;********************************************************
cProc	SsScan,<FAR,PUBLIC>,<si,di>

	localV	txLinks,<SIZE TXLNK>

ScanXj: jmp	ScanX

cBegin	SsScan

	DbMessTimer	SCAN,<Enter SsScan - >

;Assume not direct mode
	mov	cx,txdCur.TXD_bdlText_cbLogical ;Bytes of text
	cmp	grs.GRS_fDirect,FALSE		;Direct mode?
	jz	GetTXDInfoX			;Program mode
	xor	cx,cx
GetTXDInfoX:
;Grow the text, ensuring a gap between emit and source
	shr	cx,1
	shr	cx,1
	shr	cx,1			;Gap should equal 1/8 source size.
	GETSEGTXTCUR			;es = the text segment
	xor	ax,ax
	mov	SsCbTxExpand,ax 	;Initialize bytes of text expansion
	mov	[ScannerFlags],ax
	SetStartOtx	si		;oTxSrc
	mov	di,si			;oTxEmit
	DbChkTxdCur			;perform sanity check on txdCur
	call	SsMakeGap		;Ensure enough gap to scan (cx=gap)
	mov	ax,ER_OM		;Indicate out of memory
	jc	ScanXj			;Out of memory - can't scan
	lea	bx,txLinks		;Address of link controls
	call	TxLnkInit		;init txLinks structure to 0
					;ax = 0
					;preserves: bx,ax,dx, uses: cx,es
	mov	dx,txdCur.TXD_otxLabLink;Label link head pointer
	mov	[bx].TXLNK_LabDefNext,dx;offset of next label definition
					;LabDefLast left at zero

	cmp	grs.GRS_fDirect,FALSE	;Direct mode?
	jnz	InitLinks		;If direct mode, don't worry about CONT
	or	[txdCur].TXD_otxLabLink,1 ;Set LSB to indicate unbound

	    mov     bx,dataOFFSET prsCur.PRS_cbFrameTemp    ;Assume PRS
	    test    byte ptr [grs.GRS_oRsCur+1],80H	    ;MRS?
	    jnz     @F					    ;No
	    and     [mrsCur].MRS_flags,not FM_OptionBase1   ;Set option base 0
	    mov     bx,dataOFFSET mrsCur.MRS_cbFrameTemp
	    mov     [mrsCur.MRS_data_otxFirst],UNDEFINED    ;Init head of DATA list
@@:
	    xchg    ax,[bx]		;Zero cbFrameTemp if not direct mode
	push	ax			;Save old cbFrameTemp
	mov	bx,[grs.GRS_otxCONT]	;Get CONT otx
	inc	bx
	jz	InitLinks		;Can't continue, don't swap pcode
	mov	cx,[grs.GRS_oRsCONT]	;Get CONT oRS
	call	GetOtxRS		;Make sure oRS in cx isn't for DefFn
	cmp	cx,[grs.GRS_oRsCur]	;Is it the one we're scanning?
	jnz	InitLinks
	mov	ax,opNoList0
	xchg	ax,PTRTX[bx-1+si-StartOtx] ; Replace CONT pcode with special
	mov	[SsErrOpcode],ax	;Save original pcode

InitLinks:
	xor	ax,ax			;AX = 0

	mov	f_Static,TRUE		;Set $STATIC in effect flag

	;Initialize oTypCur and oValCur fields in COMMON to zero

	    mov     bx,[grs.GRS_bdtComBlk.BD_pb]
	mov	cx,ax
ZeroCom:
	cmp	cx,[grs.GRS_bdtComBlk.BD_cbLogical] ;Within size of block?
	jae	@F
	mov	[bx].COM_oTypCur,ax	;Zero oTypCur
	mov	[bx].COM_oValCur,ax
	add	bx,size COM
	add	cx,size COM
	jmp	ZeroCom

@@:

	mov	ssStackSave,sp		;Preserve the sp from start of scan loop
.errnz	STYP_StackEnd			;Stack base indicator used to determine
	push	ax			; end of control structures on stack

ScanToExeStart:
	xor	ax,ax
	mov	[SsCbFrameTemp],ax	;Count of temps in next statement
	mov	[SsErr],ax		;Error code
	mov	[SsExec],ax		;No executable code yet
	dec	ax
	mov	[SsErrOTx],ax		;Set error location to FFFF
	mov	[grs.GRS_oTxCur],ax	
	mov	[EmitErrOtx],ax
	mov	[SsDelayCnt],ax
	mov	[SsOTxPatchBos],ax	

	;Top of scan loop when pcode has HeapMove flag set

	public	SetScanRet
SetScanRet:
	mov	[SsOtxHeapMove],di
	mov	ScanRet,SCANOFFSET ScanToExeLoop  ;Set return address for
						;  dispatched opcode scanners

	;Main scan loop for SS_PARSE to SS_EXECUTE

	public	ScanToExeLoop
ScanToExeLoop:
	LODSWTX
	and	ax,OPCODE_MASK


	mov	bx,ax
	mov	al,mpOpAtr[bx]
	or	[SsExecFlag],al
	test	al,OPA_fHeapMove	;Cause heap movement?
	jnz	SetHeapMove
GetExe:
	shl	bx,1
	mov	ax,mpOpExe[bx]		;Get nominal executor
	mov	dx,ax			; Some routines want it in DX
DbPub   DispSS
DispSS:
	jmp	mpOpScanDisp[bx]	;Dispatch to scan routine for opcode

SetHeapMove:
	mov	[ScanRet],SCANOFFSET SetScanRet
	jmp	GetExe

Public	ScanExit
ScanExit:
	pop	ax			;Remove stack base indicator
	call	SsFrameType		;Make sure nothing's on the stack
	mov	sp,[SsStackSave]
	mov	al,SS_EXECUTE		;Scan state of text table
	cCall	UpdateTxdBdl		;Update the TXD or BDL for this table
;See if temp space grew.  If there are frames for this procedure on the stack,
;then temps can't grow.  An exception is if the only frame is the one on the
;top of the stack, where the gosub return addresses can be moved down to make
;more room.  Although direct mode allocates temp space off the current proc,
;it doesn't matter if it grows then because the procedure itself doesn't
;need (or use) the space.
	cmp	grs.GRS_fDirect,FALSE	;Direct mode?
	jnz	CouldCont		;Could always continue if direct mode
;Check for CantCont because temps grew
	pop	ax			;Original cbFrameTemp
	test	[SsFlags],SSF_CantCont	;Already detect CantCont situation?
	jnz	SetCantCont
	test	byte ptr [grs.GRS_oRsCur+1],80H	;MRS?
	    mov     bx,dataOFFSET mrsCur.MRS_cbFrameTemp
	    jz	    TempsGrow		;Brif MRS
	    mov     bx,dataOFFSET prsCur.PRS_cbFrameTemp
TempsGrow:
	    cmp     ax,[bx]		;Did it grow?
	jae	CouldCont		;Didn't grow--still can continue
;Grew FrameTemps
	mov	bx,dataOffset b$CurFrame
	cCall	ActiveORs_Frame,<bx>	; See if frame on stack
	or	ax,ax			
	jz	CouldCont		; Didn't find one
SetCantCont:
	call	CantCont
CouldCont:
;Compute max size of blank COMMON type and value tables
	mov	bx,[grs.GRS_bdtComBlk.BD_pb];pBlankCommon
	mov	ax,[bx].COM_oTypCur	;Size of type table
	cmp	ax,[oTypComMax]		;Grow?
	jbe	MaxComSize
	mov	[oTypComMax],ax		;Set new max
	mov	ax,[bx].COM_oValCur
	mov	[oValComMax],ax		;Set new max for value table
MaxComSize:
	DbChkTxdCur			;perform sanity check on txdCur
	DbMessTimer	SCAN,<Leave SsScan - >
	mov	ax,[SsErr]		;Return error code in ax
	or	ax,ax
	jz	ScanX
	cmp	[grs.GRS_fDirect],FALSE ;don't descan direct mode buffer
	jne	ScanX			;branch if in direct mode
	push	ax			;Descan sets it own error--save ours
	call	far ptr SsDescanErr	;Back to parse state if error
	pop	ax
ScanX:
cEnd	SsScan

;CheckSLoop - exe loop nonRELEASE checking code


subttl	SsDescan
page
;***
;SsDescan
;
;Purpose:
;
;   Descan is dispatched as:
;	    [[mpOpScanDisp+(([executor-2])*2)]-2]
;
;   That is, the descan address is in memory as the word before
;   each scan routine.	This is memory conservative, as there are
;   relatively few scan routines compared to opcodes or executors.
;
;   Individual descan routines must determine descan requirements
;   based on ssTarget and the current pcode state.  This is efficient
;   in that there are few descan routines that are state sensitive.
;
;   When descanning from executor state all pcodes that can be inserted
;   by SsScan only are removed.  In other words scan routines do not have
;   to check to see if coercion tokens (for example) have already been
;   inserted.  This is efficient in that it is usually as hard to check
;   to see if the work is required as it is to simply do the work.
;
;   Descan routines are dispatched with:
;   ax = opcode
;   si = descan source
;   di = descan destination
;
;*******************************************************************************
public	SsDescan
cProc	SsDescanErr,<FAR>,<es,si,di>
	localW	oTxtLast		;Offset of last pcode word
	localV	txLinks,<SIZE TXLNK>	;Link list control
SsDescan:
	mov	[SsErrOTx],-1		;Set error location to FFFF
cBegin	SsDescanErr
	DbMessTimer	SCAN,<Enter SsDeScan - >
	DbChkTxdCur			;perform sanity check on txdCur
	DbAssertRelB grs.GRS_fDirect,e,0,SCAN,<descan called for direct mode buffer>
	DbAssertRelB txdCur.TXD_scanState,e,SS_EXECUTE,SCAN,<descan called when not in EXECUTE state>


;Load text segment to es:
	GETSEGTXTCUR			;es = seg adr of cur text table
	SetStartOtx	di		;Start at the beginning of text
					; and debind labels to oTxt
	call	SsLabelRefDebind	;First descan label references
	mov	ax,UNDEFINED
	mov	txdCur.TXD_otxLabLink,ax;Update txd head pointer
	lea	bx,txLinks		;Address of link control struc
	call	TxLnkInit		;init txLinks structure to 0
					;ax = 0
					;preserves: bx,ax,dx, uses: cx,es
	mov	[SsErr],ax
	mov	ax,txdCur.TXD_bdlText_cbLogical
	dec	ax
	dec	ax
	mov	oTxtLast,ax		;Save offset of last pcode word
	SetStartOtx	si		;Descan from the start
	mov	di,si			;Destination = source
	mov	[SsCbTxExpand],si
	mov	[ScanRet],SCANOFFSET ContDescanLoop ;Descan routines
						;return through ScanRet
SortOTx:
	mov	dx,[EmitErrOtx]		;Start sort with error location
	mov	[SsReturnBp],dataOFFSET EmitErrOtx
	call	FCanCont		; ZF set if user can't continue
	jz	SetNextOtxJ		;Don't search others if can't cont.
	push	si
	push	di
	mov	si,[pGosubLast] 	;Head of gosub list
	mov	di,[b$CurFrame]	;Start of bp return addr chain
	mov	cx,[grs.GRS_oRsCONT]	;cx = current pc's oRs
	mov	bx,dataOFFSET grs.GRS_oTxCONT
FixORs:
	call	GetOtxRS		;Make sure oRS in cx isn't for DefFn
CompOTx:
	test	byte ptr [bx],1 	;Special one we should ignore?
	jnz	NextOTx 		;Brif return to direct mode
	call	CheckUpdate
NextOTx:
	;Scan GOSUB return address list for returns in oPRS = cx

	or	si,si
	jz	CheckFrame		;No more gosub returns
	cmp	si,di			;Still within current module/procedure
	ja	CheckFrame
	lea	bx,[si].FR_otxRet
	mov	si,[si]
	jmp	CompOTx

CheckFrame:
	cmp	di,[b$MainFrame]	;End of list?
	jz	SetNext
	lea	bx,[di].FR_otxRet
	mov	cx,[di].FR_oRsRet	;oRS of return address
	mov	di,[di].FR_basBpLink	
	jmp	FixORs

SetNextOtxJ:
	jmp	short SetNextOtx

SetOtxCont:
	mov	ax,di
	inc	ax			;Set LSB of otx to remember it's set
	mov	[grs.GRS_otxCont],ax	;Set new CONT otx
	jmp	SortOtx

SetErrorLoc:
	mov	ax,di
	dec	ax

⌨️ 快捷键说明

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