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

📄 ssproc.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
page	49,132
	TITLE	ssproc	- Scan support for procedures
;***
;ssproc	- Scan support for procedures
;
;	Copyright <C> 1986, Microsoft Corporation
;
;
;****************************************************************************

	.xlist
	include		version.inc
SSPROC_ASM = ON
	IncludeOnce	context
	IncludeOnce	exint		
	IncludeOnce	extort
	IncludeOnce	opid
	IncludeOnce	opmin
	IncludeOnce	opstmt
	IncludeOnce	optables
	IncludeOnce	names		
	IncludeOnce	pcode
	IncludeOnce	qbimsgs
	IncludeOnce	rtinterp
	IncludeOnce	ssint
	IncludeOnce	txtmgr
	IncludeOnce	variable
	.list


assumes DS, DATA
assumes es, NOTHING
assumes ss, DATA


	extrn	ABSOLUTE:far 		

sBegin	CODE

	extrn	exBranchRel:near	;This executor in exgoto.asm
	extrn	exBranch:near		;This executor in exgoto.asm
	extrn	exNoList1:near		; This executor in exproc.asm
	extrn	exParamCnt:near 	;This executor in exproc.asm
	extrn	exSave87:near		;This executor in exproc.asm
	extrn	exR8ToStack:near	; This executor in exproc.asm

	    extrn   exR4ToStack:near	; This executor in exproc.asm

extrn	exDelLocSD:near
extrn	exDeallocArray:near

extrn	exDelTmpSD:near

;This executor in exrefarg.asm
extrn	exPushSeg:far		;executor to coerce near reference to far ref.


sEnd	CODE


sBegin	DATA


	extrn	b$ULSymSeg:word 	;Zero iff no user library
	extrn	b$TRPTBL:word		;Start of event handler table
	extrn	b$TRPTBLEND:word	;End+1 of event handler table


pbAbsolute	db	'ABSOLUTE'	
CB_Absolute	EQU	$ - pbAbsolute	


SsLastExit	dw	0
SsProcPRS	dw	0
SsDeclSeg	dw	0	
FuncOtyp	db	0

sEnd	DATA


sBegin	SCAN
assumes cs, SCAN

NoParamsFlag=	80H	;No parentheses on declaration:  no type checking
ArrayFlag=	04H	;Current parameter is whole array
DefFnFlag=	40H	;Def Fn:  pass by value
CallSFlag=	20H	;CallS:  pass by far reference
ByValFlag=	ST_ByVal;BYVAL found on current parameter
SegFlag	=	ST_Seg	;SEG found on current parameter
ProcType=	03H	;From PRS_procType
CallFlag=	SegFlag	;Dual use flag - explicit call

TypeMatchFlag	=	FP_ENDPROC	;Set this bit if type mismatch
ResetBits	=	(ByValFlag + SegFlag + ArrayFlag)*100H + TypeMatchFlag
			;Reset for each parameter

.errnz	ByValFlag - HIGH PATR_byVal
.errnz	SegFlag - HIGH PATR_Seg
.errnz	ArrayFlag - HIGH PATR_array

;Verify the SsRefArg flags defined in SSINT.INC
.errnz	Lvalue - ProcType
.errnz	FarArg - (CallSFlag+SegFlag)
.errnz	FScb - ByValFlag

public	ByValMarker,SegMarker		;Put in rule byte

ByValMarker=	ByValFlag
SegMarker=	SegFlag


;executor map to store values in a temp.
tTmpType	label	word
	DWEXT	exStTmp2
	DWEXT	exStTmp4
	DWEXT	exStTmpR4
	DWEXT	exStTmpR8
	DWEXT	exStTmpSD


;*** Ss_LParen
;
; Make sure type of expression on stack is "expression", not
; variable or literal.

SsProc	LParen
	STOSWTX				;Emit no-op executor
	pop	ax			;Get expression type
	and	ax,((ST_ByVal OR ST_Seg) SHL 8) OR ST_Typ_Mask
	push	ax
	jmp	[ScanRet]


;*** Ss_ByVal_Seg
;
; Set flag that indicates Byval or Seg was seen
; Rule table byte has flag bit set

SsProc	ByVal_Seg
	STOSWTX				;Emit it
	shr	bx,1			;Back to byte index
	pop	ax			;Get oTyp and flags
	or	ah,mpOpRule[bx]		;Add ByVal or Seg flag
	push	ax			;Put it back
	jmp	[ScanRet]


;*** Ss_NoList0 - Current PC oText
;
; This opcode indicates location of current PC.  It was swapped in place
; of original opcode just before scanning.

SsProc	NoList0
	mov	[grs.GRS_otxCont],di	;Set new CONT otx
	dec	si
	dec	si			;Point back to opcode
	mov	ax,[SsErrOpcode]	;Get original opcode
	mov	PTRTX[si],ax		;Put it back so we can scan it now
	jmp	[ScanRet]


;*** Ss_NoList1 - Pcode reference to update
;
; This opcode identifies a spot in the pcode that is referenced by a static
; location in DS.  Its operand is the offset in DS where the oTx is stored.
; This location is updated to contain the current emit oTx if it is possible
; to continue.  Otherwise, this opcode is deleted.
;
; This opcode is used for return addresses on the stack, event table
; entries, and pcode references in the MRS.
;
; In the case of DefFn/Function return addresses, there will be a scan
; stack frame for the return value.  The oTx of this entry must be updated
; to point AFTER this return address opcode, so that any coercions, etc.,
; will be performed AFTER the DefFn/Function returns.
;
; The opNoList1 for error and event handlers is inserted after the opBol
; so that the text manager won't get confused.  A check is made for these
; handlers so they can be updated to the oTx of the saved opBos.  The opcode
; is deleted so that it won't be updated if a coercion takes place later on
; the line.

SsProc	NoList1
	    cmp     [grs.GRS_otxCONT],-1
	jz	EatNoList		;If can't continue, delete pcode
	STOSWTX
	LODSWTX				;Get operand, offset into stack
	STOSWTX
	xchg	bx,ax

	;See if we're dealing with an error or event handler

	test	byte ptr es:[si-3],HIGH (OPCODE_MASK+1)
	jnz	UpdateBOS		; Brif error/event handler

	;   The processing of a opNoList1 results in an exNoList1 being
	;emitted.  This is necessary in case text is inserted before the
	;current location.  opBos processing in ssbos.asm will scan the
	;statement for exNoList1s and update the return addresses with
	;the correct oTx.  The update is still performed here because
	;the Bos search and update will not occur unless there is an
	;insertion.

	mov	[bx],di			;Set oTx of return address to here
	or	[SsBosFlags],SSBOSF_PcUpdate	;Remember that update occured
	pop	ax
	or	ax,ax			;Scan stack entry present?
	jz	PushAx

	;Analyze stack entry to see if oTx needs updating

	pop	bx			;Get oTx
	lea	dx,[bx+4]		; Size of this opcode
	cmp	di,dx			;Did it point just in front of us?
	jnz	RestoreEntry
	mov	bx,di			;Use current emit oTx for entry
RestoreEntry:
	push	bx			;Restore oTx
PushAx:
	push	ax			;Restore oTyp
NoListRet:
	jmp	[ScanRet]

EatNoList:
	inc	si
	inc	si			;Skip over operand
	jmp	NoListRet

UpdateBOS:
	mov	ax,[SsOtxBos]
	mov	[bx],ax
	sub	di,4			;Eat opNoList1 for error/event handler
	jmp	NoListRet

subttl	StDeclare,StSub,StFunction,StDefFn - Scan procedure headers
page

;***
;Ss_StDeclare - Scan the DECLARE statement
;
;Make sure this is the same as the official declaration
;
;***********************************************************************

SsProc	StDeclare,rude
	STOSWTX
	test	[SsExecFlag],OPA_fExecute ;Already seen executable stmt?
	jz	@F
	mov	ax,MSG_COM		;DECLARE must precede executable stmts
	call	SsError
@@:
	mov	ax,PTRTX[si+2]		;Get oPRS
	push	di			;Save current position
	call	ReLinkScan		;Copy operands, adjust PRS if def.
	mov	es,cx			;Segment of PRS to es
	pop	ax
	push	si
	push	di			;Save source and emit oTx
	xchg	ax,di			;Get oTx of declare to di
	add	di,DCL_cParms		;Point to parameter count field
	xor	dh,dh			;Not a DefFn
	call	GetDecl			;Get declaration
	assumes ds,NOTHING

	;ds:si points to declaration of SUB/FUNCTION/DEF FN
	;ax = oRS of declaration

	xchg	ax,bx			;oRS to bx
	lodsw				;Get attributes
	mov	dx,ax			;Preserve length of alias
	xor	ax,es:[di-2]		;Compare attributes
	and	ax,DCLA_cdecl+DCLA_procType+DCLA_oTyp+DCLA_cbAlias
					;Make sure proc type, alias length,
					;CDECL, and fcn return type match
	jnz	DeclareDD
	lodsw				;Get count of parameters
	scasw				;Same as this declare?
	xchg	cx,ax			;Count to cx
	mov	ax,ER_AC
	jnz	DeclareX		;Argument count error?
	inc	cx
	jz	CompAlias		;No parameter list?
	dec	cx
	jz	CompAlias		;No arguments
CompareArgs:
	cmpsw				;Skip over oVar
	lodsw				;Get ParamAtr
.errnz	LOW PATR_byVal			
	mov	dl,ah			; Save ByVal flag in dl
	xor	ax,PTRTX[di]		;Compare ParamAtr
	TestX	ax,PATR_Array+PATR_Seg+PATR_ByVal+PATR_oTyp ;Only these count
	jnz	DeclareTM
	mov	ax,PTRTX[di+2]		; Get declared oType

	; Make sure ByVal is only on numeric types

	xchg	cx,ax			; Declared oType to cx, loop cnt to ax
	test	dl,HIGH PATR_ByVal	; ByVal?
	jz	CompType		; Not ByVal - go compare oTyps
	jcxz	DeclareTM		; Don't allow As Any with ByVal
	cmp	cx,ET_MaxNum		;[2] Record or SD type?
	ja	DeclareTM		; Don't allow non-numeric with ByVal
CompType:				
	push	dx
	push	ax			;Save loop count
	push	bx
	push	ds
	lodsw				;Get official oType
	xchg	ax,dx			;oType to dx

	;NOTE: Zero flag still set here if not ByVal!

	push	ss
	pop	ds
assumes	ds,DATA
	jcxz	AsAny			;Always allow ANY to pass--ZF must be set
	mov	ax,[grs.GRS_oRsCur]
	cCall	CompareTyps,<ax,bx,cx,dx>	
	REFRESH_ES				
	or	ax,ax				
AsAny:
	pop	ds
assumes	ds,NOTHING
	pop	bx
	pop	cx
NextArg:
	pop	dx
	jnz	DeclareTM
	add	di,4
	loop	CompareArgs
CompAlias:
;Make sure aliases match
.errnz	DCLA_cbAlias - 07C00H
	mov	cl,dh			;cbAlias to cx
	and	cl,HIGH DCLA_cbAlias
	shr	cl,1
	shr	cl,1
rep	cmpsb				;Compare alias strings (ZF set if none)

DeclareDD:
	mov	ax,ER_DD		;Duplicate def. if aliases don't match
DeclareX:
;Zero flag set if no error, else error code in ax
	pop	di
	pop	si
	push	ss
	pop	ds
assumes	ds,DATA
	jz	NoDeclErr
	call	SsError
NoDeclErr:
	jmp	[ScanRet]

DeclareTM:
;To accurately position error cursor, figure out exact position in pcode
;of error.  di = emit oTx of error.
	mov	dx,di			;Error location to dx
	pop	di
	pop	si
	sub	dx,di			;Distance back to error
	inc	dx			;Set LSB
	add	si,dx			;Position of error in source
	mov	ax,MSG_ParmTM		;Parameter type mismatch
	push	ss
	pop	ds			;Restore ds
	call	SsError
	sub	si,dx			;Restore source oTx
	jmp	short NoDeclErr

;***
;SsReLinkDecl - adjust PRS to point to proc declaration after scan/descan
;
;Purpose:
;	If this is the official definition of the procedure, i.e. it is
;	referred to by PRS_oRsDef and PRS_otxDef, then adjust PRS_otxDef
;	to refer to new (emit side) location.  Set flag bit if this
;	is done.
;
;	Also copies all operands.
;
;Inputs:
;	ax = oPRS
;	bx = opcode * 2
;	si & di = oTx of cbEOS (source & emit, respectively)
;	dh = 0 if scanning, dh = -1 if descanning
;Outputs:
;	cx:bx = pPRS
;	si & di = oTx of next pcode
;Preserves:
;	dl
;***********************************************************************
	public	SsReLinkDecl,SsReLinkNoCopy
ReLinkScan:
	xor	dh,dh
SsReLinkDecl:
	PUSH_ES 			
	push	di			;Save oTx of declar. (emit side)
	push	si
	push	ax			;Save oPRS
	call	CopyOperands
	pop	ax
NoCopy:
	call	PPrsOPrsSCAN		;[22] oPRS in ax --> pPRS in es:bx
	pop	ax			;oTx+2 of declaration (source side)
	pop	cx
	xor	dh,BPTRRS[bx].PRS_flags ; Get flags, adjust for scan vs. descan
	test	dh,FP_DEFSCANNED	;Already scanned/descanned definition?
	jnz	ReLinked		;No work if already in correct state
	dec	ax
	dec	ax
	sub	ax,[SsCbTxExpand]	;Compute original oTx
	cmp	ax,PTRRS[bx].PRS_otxDef ; Is that where defined?
	jnz	ReLinked
	mov	ax,PTRRS[bx].PRS_oRsDef 
	cmp	ax,grs.GRS_oRsCur	;Defined in this RS?
	jnz	ReLinked
	xor	BPTRRS[bx].PRS_flags,FP_DEFSCANNED ; Change scan state
	dec	cx
	dec	cx
	mov	PTRRS[bx].PRS_otxDef,cx ; Adjust oTx to emit location
ReLinked:
	mov	cx,es			;Save segment of PRS
	POP_ES				
	ret

SsReLinkNoCopy:
;Same as SsReLinkDecl except does not copy operands
;si & di unchanged
	PUSH_ES 			
	push	di
	push	si
	jmp	NoCopy

subttl	StData,StDefType,StType,StEndType,StDefFn,StEndDef
page
;***
;StData,StDefType,StType,StEndType,StDefFn,StEndDef
;
;	These scan routines manage linked lists across the
;	source/emit boundary.
;
;Algorithm:
;	TXLNK is a data structure with a tail pointer for each list.
;	When another item to be linked is encountered, we simply
;	find the previous one with TXLNK and point it to the new one.
;	TXLNK is updated to point to our new one, too.  TXLNK = 0
;	means there is no previous element.
;
;	These routines are generally used for both scan and descan.
;	The exception is StDefFn/StEndDef, which is descan only.  During
;	scan to execute state a stack entry is used to link Def to End.
;	End is not linked in execute state.
;
;	Reasons why these guys are linked in Parse state:
;
;	DEF FN/END DEF - Used to keep track of what is within the definition.
;
;	DATA - NOT linked by parser in Parse state.
;
;	DEFtyp - Used to figure out what type something is, given a pcode
;		location.
;
;	TYPE/END TYPE - Used to keep track of what is within the type definition
;
;
;	Reasons why these guys are linked in Execute state:
;
;	DEF FN/END DEF - Need to know what is within a definition, to 
;		prevent GOTO, etc. to/from DefFn during scan.
;
;	DATA - to find the rest of the data.
;
;	DEFtyp - Used to assign types to direct mode things, using DEFtyp
;		status of the current PC or the last statement.
;
;	TYPE/END TYPE - Used to jump over the type definition.  End is linked
;		to next Type, but not needed.


SsDProc	StDefFn
	STOSWTX
	mov	dh,-1			;Set Descan direction
LinkDefFn:
	mov	ax,PTRTX[si+4]		;Get oPRS
	call	SsReLinkNoCopy		;Adjust PRS_otxDef
	jmp	short LinkDef

SsDProc	EndSingleDef
SsDProc	StEndDef
	STOSWTX
LinkEndDef:
	mov	PTRTX[si],2		;Set filler to cbEOS
LinkDef:
	mov	bx,TXLNK_DefFn
	mov	dx,dataOFFSET mrsCur.MRS_otxDefFnLink
	cmp	PTRTX[si+2],-1		;End of list?
	jz	VarLenLink		;If so, don't change it
	inc	PTRTX[si+2]		;Set LSB of link to indicate end
	jmp	short VarLenLink

ssProc	StData,,Local
SsD_StData:
	mov	bx,TXLNK_Data		;Link field for DATA link list
	mov	dx,dataOFFSET mrsCur.MRS_data_otxFirst
	STOSWTX 			;Emit executor
	mov	PTRTX[si+2],UNDEFINED	;In case this is last, mark end
VarLenLink:
	LODSWTX 			;Load cbEos
	mov	cx,ax
	inc	cx
	shr	cx,1			;Words to EOS including link field
	jmp	short EmitAndAdjLinks	; Emit cbEos and link


SsProc	StDefType,rude,Local
SsD_StDefType:
	mov	cx,3			;Link field plus 1 Dword operand
	mov	bx,TXLNK_DefType
	mov	dx,dataOFFSET txdCur.TXD_otxDefTypeLink
	jmp	short EmitAndAdjLinks	;Emit executor and link


SsProc	StType,rude,Local
	or	[SsFlags],SSF_InType	;Remember we're in TYPE declarationt
	test	byte ptr [grs.GRS_oRsCur+1],80H	;In procedure?
	jz	SsD_StType		;Better not be
	push	ax			;Save executor
	mov	ax,MSG_InvProc		;Illegal in procedure
	call	SsError
	pop	ax
SsD_StType:
	mov	cx,2			;Link field plus 1 word operand
	jmp	short FixType

SsProc	StEndType,rude,Local
	and	[SsFlags],not SSF_InType;No longer within TYPE declaration
SsD_StEndType:
	mov	cx,1			;Link field w/no additional operands
FixType:
	mov	bx,TXLNK_Type
	mov	dx,dataOFFSET txdCur.TXD_otxTypeLink

EmitAndAdjLinks:

	;AX = Word to be emitted
	;BX = offset into LinkCtl
	;CX = remaining cw of operands to copy
	;DX = pointer to head of list

	STOSWTX
	add	bx,[ssLinkCtl]		;Get pointer to link control struc
	mov	ax,di
	xchg	ax,[bx] 		;Get last item, set new "last"
	or	ax,ax			;First item?
	jz	SetHead
	xchg	bx,ax			;Pointer to previous item in bx
	mov	PTRTX[bx],di		;Fix up pointer to current value
CopyOps:

⌨️ 快捷键说明

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