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

📄 excontxt.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 2 页
字号:
page	49,132
	TITLE	EXCONTXT - context-related executors
;***
;excontxt.asm - context-related executors
;
;	Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;
;
;Special Information regarding [re]initialization:
;     - This module contains the fundamental entry point to which
;	1-time initialization branches.
;     - When UserInterface() is called, this represents a major transfer
;	of control; the User Interface takes over. It saves away the
;	keyboard interrupt handler that the runtime installed at
;	1-time initialization, and restores it prior to returning here.
;	Within the User Interface (UI), ES is no longer preserved, and
;	one may not assume that SI or DI represent anything in particular.
;     - Some executors in this module will behave differently in our
;	full shell version than in the "Runtime Module" version, i.e.,
;	the version which can just binary load QBI programs and run them.
;	Executors which terminate execution are at the head of this list
;	rather than returning to the shell, in the Runtime Module version,
;	these will cause QBI to terminate and exit to DOS.
;     - Note that anyone that changes grs.fDirect sets up a 'critical
;	section' situation: if a runtime error occurs after grs.fDirect
;	has been changed, and grs.oTxCur is not pointing to some exBol/Bos
;	opcode in the text table owned by txdCur, runtime error handling
;	will go out to lunch.
;     - The way we allow for RUN <filename> and CHAIN to load a file and
;	get it scanned is to have them call LoadFile, then put an actual
;	executor address in the direct mode buffer, set a bit in debugFlags,
;	and just dispatch. We know that the following BOS/BOL/EOT will cause
;	UserInterface() to regain control; UserInterface() will see the
;	debugFlags bit set, and cause the direct mode buffer to be executed.
;
;****************************************************************************

	.xlist
	include 	version.inc
EXCONTXT_ASM = ON
	IncludeOnce	architec
	IncludeOnce	conint
	IncludeOnce	context
	IncludeOnce	executor
	IncludeOnce	exint
	IncludeOnce	extort
	IncludeOnce	opcontrl
	IncludeOnce	opmin
	IncludeOnce	opstmt
	IncludeOnce	qbimsgs
	IncludeOnce	rtinterp
	IncludeOnce	rtps
	IncludeOnce	rttemp
	IncludeOnce	scanner
	IncludeOnce	txtmgr
	IncludeOnce	ui
	IncludeOnce	variable
	.list

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

sBegin	DATA
	externW b$cCSubs	;count of compiled BASIC frames on stack
	externB b$inonerr	;used to check for No RESUME error @ implied END
	externW	b$errnum
	externW b$ErrInfo	;extended error codes (UI <--> Runtime)
	externB fInitialized	;non-zero if we've completed initialization of
				;  quick basic
	externB b$CtrlFlags	;byte of runtime-specific flag bits
	staticW oTxRunSave,0	;!#@$ static location to save oTxCur before
				;RunFile or CHAIN.

sEnd	DATA

	EXTRN	B$IEND:FAR
	EXTRN	B$IEndSt:FAR
	EXTRN	B$SCLR:FAR
	EXTRN	B$ClearRange:FAR
	EXTRN	B$STACKINIT:FAR
	EXTRN	RtError_INI:FAR

	EXTRN	fEditorActive:FAR 

sBegin	CODE
assumes cs, CODE

	EXTRN	DoFBosResetStk:near
	extrn	I4ToU2:near

;***
;exStop, exStEnd, exStSystem - STOP, END, & SYSTEM Statement Executors
;
;	Note that, for STOP, UserInterface will save the CONTinue context
;	we don't have to do that here.
;
;	Note that for compiled BASIC STOP and END/SYSTEM, the runtime
;	will do a jump to B$IStop or exStEnd.
;
;	Note that SI, DI, & ES may not be correctly set on entry to B$IStop.
;
;***************************************************************************
	PUBLIC	B$IStop		;runtime call-back if ctrl-Break is
B$IStop:				;  seen, or compiled Basic STOP stmt
	mov	al,[grs.GRS_fDirect]	
	or	al,al			; in direct mode window?
	jnz	SkipCursorStuff 	; yes, skip cursor positioning
	push	ax			; save direct mode flag because
					;	OtxBosOfOtx hoses fDirect

	call	EnStaticStructs		;bring txdCur up to date
	push	[grs.GRS_otxCur]	;parm to OtxBosOfOtx
	call	OtxBosOfOtx		;ax = oTx of BOS/BOL of current stmt
					;we do this so we don't try to continue
					;execution in the middle of a statement
	xchg	ax, bx			; bx = otx of pcode to skip.
	call	TxtSkipOpFar		;ax = oTx of pcode following BOS/BOL.
					;  we do this so txtmgr can tell for
					;  sure which line to put the cursor on
	xchg	ax,si
	pop	ax
	mov	[grs.GRS_fDirect],al	;in case OtxBosOfOtx changed fDirect
	call	DisStaticStructs
SkipCursorStuff:			
	and	[BosFlags],NOT FBOSSTOP
	mov	bp,[b$curframe]
	SkipExHeader
MakeExe exStStop,opStStop
	or	[debugFlags],DEBUG_STOP ;indicate program stopped
	cmp	[fNonQBI_Active],FALSE	;was QBI code active when we stopped?
	jz	StopGrsContext		;brif so

	;We were stopped in QuickLib code. We cannot CONTinue, but we
	;do want to be able to allow the user to print variables, and stack 
	;trace from the most recent QBI frame back.
	or	[debugFlags],DEBUG_CANT_CONT
	call	ResetSP_BP_Far		; reset SP & BP based as appropriate
					;  depending on whether QBI code
					;  was active or not.
	mov	sp,ax			;set SP based on retval
	jmp	SHORT StopGrsContext

MakeExe exStSystem,opStSystem
	test	[cmdSwitches],CMD_SW_RUN ;/Z filename given on command line?
	jnz	Exit_Basic		 ;  brif so - - always exit

	cmp	[grs.GRS_fDirect],FALSE ;in Direct Mode?
	jz	exStEnd 		;  brif not - - act just like END stmt

Exit_Basic:
	or	[debugFlags],DEBUG_END	; indicate end-of-program, to ensure
					;  error not trappable in case of
					;  I/O error
	cCall	NotSaved		;notify user, get his response.
					; if CANCEL, ax=MSG_GoDirect
					; if user said NO, ax=FFFF
					; if I/O error, ax = error code
					; if files saved ok, ax=0
	jg	J2_RtErrorCODE		;brif runtime error while
					; saving files, or CANCEL
	call B$IEND			;tell runtime to terminate - - never
					;  returns
MakeExe exStEnd,opStEnd
	or	[debugFlags],DEBUG_CANT_CONT
					;make sure UserInterface() doesn't
					; let us continue execution
	mov	[grs.GRS_otxCur],si	; in case of error in closing files
	or	[debugFlags],DEBUG_END	; indicate end-of-program, to ensure
					;  errors aren't trappable
	call	B$IEndSt		;close all user files
	SkipExHeader			;fall through except for closing files,
					;  exEndProg is an implied END executor
;***
;exEot, exEndProg - End of Program Executor
;Purpose:
;	exEndProg is the main interpreter loop control.  It calls the
;	front end to obtain work.  It then executes the current text
;	table.	All text tables contain an exEndProg after the user's pcode.
;	The loop is completed by execution of the exEndProg at the end of some
;	text table.
;
;***************************************************************************
MakeExe exEot,opEot
	SkipExHeader
MakeExe exEndProg,opEndProg
	cmp	[b$inonerr],FALSE
	jz	EndProg1		;brif not in an error trap

	cmp	[grs.GRS_fDirect],FALSE
	jnz	EndProg1		;brif EOT in Direct Mode buffer

	mov	al,ER_NR		;No RESUME error
J2_RtErrorCODE:
	call	RtErrorCODE		;runtime error - doesn't return
EndProg1:
	;if something like NEW happened as the last statement, the stack won't
	;  have been cleared yet (and who knows, we might have something
	;  meaningful on the stack when we hit our next BOS/BOL after
	;  UserInterface(?)
	test	[BosFlags],FBOSRESETSTK
	jz	Ep_Cont

	call	DoFBosResetStk		;reset the stack
Ep_Cont:
	or	[debugFlags],DEBUG_END	;indicate end-of-program
	mov	si,UNDEFINED		;Save context (end of program)
	;fall into StopGrsContext
PUBLIC	StopGrsContext
StopGrsContext:
	mov	[grs.GRS_otxCur],si	;Save text pointer
	mov	[b$curframe],bp	;required by RT error handling code

	DbChk	BpChain			;ensure the bp chain is walkable
	DbAssertRel  sp,a,b$pendchk,CODE,<StopGrsContext: SP below b$pendchk>
					;ensure sufficient stack space for U.I.
	cmp	[b$errnum],ER_OM
	jz	Enter_UI		;brif might already be short on space
	call	GrabSpace		;ensure there's enough free space to
					;  at LEAST do a CLEAR ...
	or	ax,ax
	jnz	Enter_UI		;brif allocations successful
OM_Err:
	mov	al,ER_OM		;don't enter UI if we can't even
	jmp	J2_RtErrorCODE		;  get enough space to do a CLEAR - -
Enter_UI:
	call	ReleaseSpace		;release special space allocated by
					;  GrabSpace
	call	EnStaticStructs 	;activate static prsCur, mrsCur, txdCur

	test	[debugFlags],DEBUG_ERROR OR DEBUG_STOP OR DEBUG_END
	jz	Enter_UI_1		;brif not going back into UI to stay
					;  a while ...
	call	FreeAllUnrefdPrs	;Remove any prs's that arn't ref'd
					;  anywhere AND that don't have text
					;  tables.  This is needed in case
					;  the user called a prs in a QuickLib
					;  from direct mode, and this was the
					;  only reference to the prs.
Enter_UI_1:
	mov	bx,dataOFFSET prsCur
	test	byte ptr [grs.GRS_oRsCur+1],080H
	jnz	PrsIsActive

	mov	bx,dataOFFSET mrsCur
PrsIsActive:
	.errnz	MRS_cbFrameTemp - PRS_cbFrameTemp
	mov	ax,[bx.MRS_cbFrameVars]
	push	ax			;save in case more vars added to frame
	add	ax,[bx.MRS_cbFrameTemp]
	push	ax			;save in case frame size grows
	DbMessTimer	CODE,<Enter UserInterface() - >
	cCall	UserInterface		;Call direct mode for more work
	DbMessTimer	CODE,<Leave UserInterface() - >
	cmp	[grs.GRS_fDirect],FALSE
	jnz	No_Stk_Reinit		;  brif Direct mode

	mov	bx,sp			;reset empty words in stack for FRE(-2).
	sub	bx,4			;so cbFrameVars and cbFrame on stack 
					;  arn't hosed ...
	call	B$STACKINIT		;Must do this here as UserInterface
					;  is called one last time AFTER RunInit
No_Stk_Reinit:
	pop	si			;previous frame size for oRsCur
	pop	di			;previous cbFrameVars for oRsCur
					;(popping this here, as B$STACKINIT 
					;  trashes di ... pfthhhhhhhhhhp!)
	xor	bx,bx
	mov	[fNonQBI_Active],bx	;ensure this flag is reset
	cmp	[grs.GRS_otxCONT],UNDEFINED
	jnz	GetpRsCur		;brif can CONT

	;we must set SP based on BP so direct mode statments have the 
	;required amount of temp and var space on the frame. Prior to
	;doing this, however, we must release any owners on the stack - - -
	;we can't wait for the first BOS/BOL to occur, because resetting
	;sp means that we could overwrite an owner ...
	cmp	[grs.GRS_fDirect],FALSE	;executing in the direct mode buffer?
	jz	GoStartGrsContext    ; brif not - - - can't be any owners
					;  that we could hose here, and parms
					;  from Direct Mode CALL must not be
					;  released (example: call foo("bar")
					;  from direct mode)
	push	[b$pend]		;lomem of range to clear
	push	[b$mainframe]		;himem of range to clear
	call	B$ClearRange		;release any owners in given range
GoStartGrsContext:			; got relative jump out of range
	jmp	short StartGrsContext	

GetpRsCur:
	mov	bx,dataOFFSET prsCur
	test	byte ptr [grs.GRS_oRsCur+1],080H
	jnz	PrsIsActive1

	mov	bx,dataOFFSET mrsCur
PrsIsActive1:
	push	ds			;for later rep mov's and/or sto's
	pop	es
	cmp	[pGosubLast],0		;active pGosubLast chain?
	jz	Check_FrameVar_Size	;  brif not
	cmp	bp,[pGosubLast] 	; is the chain in this proc?
	jb	Check_FrameVar_Size	; no, then it's sure not active!

	.errnz	MRS_cbFrameVars - PRS_cbFrameVars
	.errnz	MRS_cbFrameTemp - PRS_cbFrameTemp
	mov	ax,[bx.MRS_cbFrameVars]
	add	ax,[bx.MRS_cbFrameTemp]
	mov	dx,ax
	sub	dx,si
	jbe	Check_FrameVar_Size	;brif sufficient frame space exists

	;Frame size has been increased; must move all gosub frames down to
	;account for the difference
	;Do this in two steps:
	;	(1) update pGosubLast chain to account for movement
	;	(2) move all gosub frames down.
	;Note that there can be an event gosub frame here, but if so, it
	;	has to be the active mrs frame - - - we can treat this the
	;	same way.
	push	di
	mov	di,[pGosubLast]
Update_Gosub_Ptrs:			;loop for step (1)
	mov	cx,[di]			;fetch ptr to next frame
	jcxz	Move_Gosub_Frames	;brif no more gosub frames
	sub	[di],dx			;update current frame ptr by amount
					;  we're moving frames down by
	mov	di,cx			;go on to next frame
	jmp	short Update_Gosub_Ptrs

Move_Gosub_Frames:			;now step (2), move frames down
	mov	cx,bp
	sub	cx,si			;cx points just past the end (himem)
					;  of range to be moved down
	xchg	ax,dx			;ax = amt to move gosub frames down by
	mov	si,[pGosubLast]		;start of range to move
	mov	di,si
	sub	di,ax
	mov	[pGosubLast],di
	sub	cx,si			;cx = number of bytes to move down
	pop	dx			;must pop this BEFORE we alter sp
	sub	sp,ax			;so interrupts won't overwrite gosub
					;  frames
	rep	movsb
	mov	di,dx			;di = old cbFrameVars
Check_FrameVar_Size:
	.errnz	MRS_cbFrameVars - PRS_cbFrameVars
	mov	dx,di			;dx = old cbFrameVars
	mov	cx,[bx.MRS_cbFrameVars]
	sub	cx,dx                   ;if cx > 0 then new vars have been added
	DbAssertFlags  ae,CODE,<excontxt: cbFrameVars got smaller!>
	jbe	Vars_Okay		;brif none have been added

	;cx = number of bytes worth of new frame vars added to current frame
	mov	al,0
	mov	di,bp
	sub	di,[bx.MRS_cbFrameVars]	;di points to start of new frame vars,
	cmp	sp,di
	jb	Got_SP			;brif sp was moved down when gosub
					;  frames were
	mov	sp,di			;so interrupts won't overwrite this
					;  after the stosb
Got_SP:
	rep	stosb			;initialize new frame vars

Vars_Okay:
	;fall into StartGrsContext
public	StartGrsContext
StartGrsContext:
	call	DisStaticStructs	;ensure static structs deactivated
	call	SetSP			;set SP based on BP	
	ja	StartGrs_Cont		;brif SP is in valid stack range

	mov	[b$ErrInfo],OMErr_STK	;out of stack space error
	jmp	OM_Err
StartGrs_Cont:
	mov	sp,ax		
	mov	si,[grs.GRS_otxCur]	;Load the continuation address
	xor	ax,ax
	mov	[grs.GRS_flagsDir],al	;reset flags which get reset every
					; time we begin executing pcode,
					; or when a runtime error occurs.
public	Start
Start:
	call	GetEsDi
Disp2:
	mov	[b$curframe],bp	;in case b$curframe got changed by
					;  the U.I. and not restored
	DbChk	BpChain			;ensure the bp chain is walkable

	DispMac 			; and begin execution

;***
;exStRunMain - Start program execution of the main module text
;Purpose:
;	Perform the RUN statement (no arguments) - begin program execution.
;
;Input:
;Output:
;Modifies:
;***************************************************************************
MakeExe exStRunMain,opStRunMain
	xor	di,di			;Set context to beginning of text tabl
					;  (put this in di in case of runtime
					;   error)
	mov	ax,[grs.GRS_oMrsMain]
	DbAssertRel ax,ne,UNDEFINED,CODE,<exStRunMain: grs.oMrsMain UNDEFINED>
Run_Otx:
	cCall	RsActivateCODE		;activate the main module
	cmp	[grs.GRS_fDirect],FALSE
	jz	RunMain1		;brif from pcode - - - must reinit stack

	or	[b$CtrlFlags],NoSTACKINIT
					;speed optimization for the case where

⌨️ 快捷键说明

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