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

📄 uidebug.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 3 页
字号:
	TITLE	uidebug.asm - User interface to debugger.
;*** 
;uidebug.asm
;
;	Copyright <C> 1985-1988, Microsoft Corporation
;
;Purpose:
;	Debugging support.
;
;
;*******************************************************************************

	.xlist
	include		version.inc
	UIDEBUG_ASM = ON

	;Include twin interface headers
	include 	cw/version.inc
	include 	cw/windows.inc
	include 	cw/edityp.inc

	;Next, include QBI's headers
	includeOnce	architec
	includeOnce	context
	includeOnce	executor
	includeOnce	heap
	includeOnce	lister
	includeOnce	opmin
	includeOnce	opstmt
	includeOnce	parser
	includeOnce	qbimsgs
	includeOnce	scanner
	includeOnce	txtmgr
	includeOnce	ui
	includeOnce	uiint
	includeOnce	util
	includeOnce	uimenu			
	.list

;---------------------------------------------------------------------------
;
; The following demonstrates how the user interface code interacts with
; the executor code to handle watchpoints and watch expressions.
; We start the discussion in UserInterface with the following program loaded:
;   A=1
;   A=2
; The pcode for this program is:
;   opBol
;   opLit1
;   opIdSt(A)
;   opBol
;   opLit2
;   opIdSt(A)
;   opEndProg
; 
; - User presses single step key, causing UserInterface to exit
; - opBol executes, sees DEBUG_TRACE bit set in debugFlags, enters UserInterface
; - User selects Watchpoint... menu, CmdWatchAdd(WT_Watch) prompts the user
;   for an expression, parses it to pcode, and inserts it at the end of the
;   text table.
; - User selects Watch... menu, CmdWatchAdd(WT_WatchPoint) prompts the user
;   for an expression, parses it to pcode, and inserts it at the end of the
;   text table.
; - We now have with a WATCHPOINT of "A=1" and a WATCH EXPRESSION of "A" and
;   the pcode looks like:
;   opBol
;   opLit1
;   opIdSt(A)
;   opBol
;   opLit2
;   opIdSt(A)
;   opEndProg
;   opIdLd(A)
;   opLit1
;   opEQ
;   opWatchStop
;   opIdLd(A)
;   opWatchExp
;   opEot
; 
; - User presses single step key.  When UserInterface exits, it sees active
;   Watch expressions, and sets DEBUG_WATCH in debugFlags.
; - opLit1 and opIdSt(A) execute
; - opBol executes, sees bits set in debugFlags, enters UserInterface
; - UserInterface immediately dispatches to DebugWatch.  DebugWatch sees
;   iWatch (static counter variable) is UNDEFINED (meaning we weren't executing
;   Watch pcode), saves current pc in otxWatchSave, sets the
;   current pc to the 1st watch expression's pcode, sets iWatch to 0,
;   returns to UserInterface with flags telling it to dispatch.
; - opIdLd(A), opLit1, and opEQ execute.
; - opWatchStop executes, sees a TRUE (non-zero) argument on the stack, sets
;   DEBUG_BREAK in debugFlags.  opWatchStop then falls into opBol which sees
;   debugFlags non-zero and enters UserInterface.
; - UserInterface immediately dispatches to DebugWatch.  DebugWatch sees
;   iWatch is 0, bumps it to 1, sets the current pc to the 2nd watch
;   expression's pcode, returns to UserInterface with flags telling it to dispatch.
; - opIdLd(A) executes.
; - opWatch executes, saves value at [pWatchVal], opWatch then falls into
;   opBol which sees debugFlags non-zero and enters UserInterface.
; - UserInterface immediately dispatches to DebugWatch.  DebugWatch sees
;   iWatch is 1, restores the current pc to otxWatchSave,
;   returns to UserInterface.
; - UserInterface then sees DEBUG_BREAK is set, and would have stopped program
;   execution even if we weren't tracing.  UserInterface then interacts with
;   the user until the user gives another command.
; - User presses single step key.  When UserInterface exits, it sees active
;   Watch expressions, and sets DEBUG_WATCH in debugFlags.
; - opLit2 and opIdSt(A) execute
; - opEndProg executes, causing us to once again enter UserInterface
;
;---------------------------------------------------------------------------


assumes	DS,DATA
assumes	ES,NOTHING
assumes	SS,DATA

	EXTRN	B$BEEP:FAR
	EXTRN	B$IFOUT:FAR
	EXTRN	B$Pause:FAR

sBegin	DATA

	EXTRN	b$ErrNum:word		;error code for last runtime error
	EXTRN	b$CurFrame:word	;current frame ptr (for PTRACE)
	EXTRN	b$MainFrame:word	;base frame ptr

	EXTRN	fRecord:byte		;set TRUE is /RCD switch seen
	EXTRN	fPlayBack:word		;TRUE if we're playing back.
					; an event playback file.
	EXTRN	axMac:byte

	externB HelpFlags		;	uiint.inc/h

;Points to space allocated by CallsMenuInit, released by CallsMenuTerm
;
pbCallsRelease DW 0

;iWatch is used by several functions involved in drawing the content
; of the watch window.  It indicates which line in the window is currently
; being drawn (0 to n)
;
DbPub	iWatch
iWatch	DW	UNDEFINED

; iInstWatch is used to keep track of where an Instant Watch entry is
; in the tWatch table.  The value of iInstWatch is only significant if
; the value of cInstWatch is non-zero.
DbPub	iInstWatch			
iInstWatch DW	0			

;fRefreshWatch is set TRUE whenever a WATCH entry is added or removed.
;It causes us to refresh the WATCH window.
;
PUBLIC	fRefreshWatch
fRefreshWatch	DB	0

;pWatchVal points to valtyp/value structure to be filled in by Watch executors
PUBLIC		pWatchVal
pWatchVal	DW	0

;1 entry per watch expression - number of bytes in expression's title
tCbWatchTitle	DB (WATCH_MAX+1) DUP (?) ; "+1" is for Instant Watch

otxWatchSave	DW 0	;copy of grs.otxCur while WATCH pcode executes
errnumSave	DW 0	; copy of b$errnum while WATCH pcode executes
bpWatchSave	DW 0	;copy of bp for start of current WATCH expression
fDirectSave	DB 0	;copy of grs.fDirect while WATCH pcode executes

;Trace modes
;
TRACE_OFF	EQU 0
TRACE_HISTORY	EQU 1	;Debug/History menu item is ON
TRACE_ANIMATE	EQU 2	;Debug/Trace menu item is ON
TRACE_STEP	EQU 3	;F8 was pressed last time in UserInterface
TRACE_PSTEP	EQU 4	;F10 was pressed last time in UserInterface
TRACE_WATCHSTEP	EQU 5	;Used by watch to force watch code to execute.

traceMode	DB TRACE_OFF

pStepFrame	DW 0
nonStickyBpRs	DW 0
nonStickyBpLn	DW UNDEFINED

CHIST	EQU 20	;we will remember last 20 statements executed
CBHIST	EQU 4	;number of bytes in 1 history entry
bdHist	DB size BD DUP (0)

oHistNext	DW 0
oHistShow	DW 0
histFlags	DB 0
	FH_Full		equ	01H
	FH_NotEmpty	equ	02H

szRun	DB	"RUN",0

sEnd	DATA

sBegin	CODE

;Table of opcodes(1) which descanner inserts where it finds return
; addresses on the stack:
;
tOpNoList LABEL WORD
	opTabStart	NOLIST
	opTabEntry	NOLIST,opNoList1
	opTabEntry	NOLIST,opEot
sEnd	CODE

sBegin	UI
assumes	cs,UI


;**************************************************************************
; DoRunOrCont(ax:fFromStart)
; Purpose:
;	Setup so program will continue execution.
;	If can't continue then start at begining.
;
; Entry:
;	ax = fFromStart - if TRUE start program from the beginning.
; Exit:
;	fGotCmd is set TRUE (which terminates GetCmd)
;
;**************************************************************************
DoCont	PROC NEAR
	sub	ax,ax
DoCont	ENDP
	;fall into DoRunOrCont
cProc	DoRunOrCont,<NEAR>
cBegin
	or	ax,ax
	jne	FromStart
	call	fCanContUI
	jne	NotFromStart		;brif can continue

; FNextStmtDoesIO uses grs.otxCONT to determine if the next statement to
; execute will do output.  ContContext is called just before FNextStmtDoesIO.
; if grs.otxCONT is UNDEFINED, ContContext will
; set grs.otxCONT to the begining of the main module.
;
FromStart:
	call	CantCont		;sets [grs.GRS_otxCONT] to UNDEFINED
	PUSHI	ax,<dataOFFSET szRUN>
	call	DoCmd
NotFromStart:
	mov	[fGotCmd],sp
cEnd

;**************************************************************************
; SetTronTroff
; Purpose:
;	Set [traceMode] and set DEBUG_TRACE bit in [debugFlags] if not TRACE_OFF
;	Called by TRON and TROFF opcode executors after they set [fTraceOn]
; Entry:
;	[fTraceOn] = non-zero if TRON is active
;	[fHistOn] = non-zero if HISTORY is active
;
;**************************************************************************
PUBLIC	SetTronTroff
SetTronTroff PROC FAR
	.errnz	TRACE_ANIMATE - 2
	mov	ax,TRACE_ANIMATE
	cmp	[fTraceOn],ah
	jne	NoTrace			;brif TRON (Trace ON) is not active
	dec	ax			;al = TRACE_HISTORY
	.errnz TRACE_HISTORY - 1
	cmp	[fHistOn],ah
	jne	NoTrace			;brif History ON is not active
	dec	ax			;al = TRACE_OFF
	.errnz TRACE_OFF
NoTrace:
	call	SetTraceMode
	ret				;can't fall into SetTraceMode, far->near
SetTronTroff ENDP

;**************************************************************************
; SetTraceMode
; Purpose:
;	Set [traceMode] and set DEBUG_TRACE bit in [debugFlags] if not TRACE_OFF
; Entry:
;	al = new trace mode (TRACE_STEP etc.)
;
;**************************************************************************
SetTraceMode PROC NEAR
	mov	[traceMode],al
	or	al,al
	je	GotTroff
	.errnz TRACE_OFF
	or	[debugFlags],DEBUG_TRACE
GotTroff:
	ret
SetTraceMode ENDP

;**************************************************************************
; CmdGo(fFromStart)
; Purpose:
;	Continue or start program execution taking into account trace state.
;	This procedure is called in response to the menu items `Run/Run' and
;	`Run/Continue'
;
; Entry:
;	fTraceOn - non-zero if TRON is active
;	fFromStart - TRUE if we want to RUN else we want to CONT.
;
;**************************************************************************
cProc	CmdGo,<PUBLIC,NEAR>
	parmW	fFromStart
cBegin
	call	SetTronTroff		;setup based on [fTraceOn]
	mov	ax,[fFromStart]
	call	DoRunOrCont		;execute a RUN or CONT command
cEnd

;**************************************************************************
; CmdSetNextStmt()
; Purpose:
;	Reset instruction pointer to statement at cursor.
;
;**************************************************************************
cProc	CmdSetNextStmt,<PUBLIC,NEAR>,<si,di>
cBegin
	call	TxtDescan		;descan to SS_PARSE
	call	GetEditLine		;ax = current edit line (from EditMgr)
	push	ax
	call	OtxOfLn 		;ax = text offset to start of line
	xchg	ax, bx			; bx = otx of pcode to skip.
	call	TxtSkipOpFar		;ax = otx beyond the opBol[xx] opcode
					;We always enter direct mode after
					;execution of the opBol
	xchg	si,ax			;si = otx
	mov	di,[grs.GRS_oRsCur]	;di = oRs of current text table
	test	[txdCur.TXD_flags],FTX_mrs
	je	NotInDefFn		;brif we're in a sub/function window
	push	si			;pass otx
	call	OPrsOfOtx		;ax = otx of DEF FN
	inc	ax			;test for UNDEFINED
	je	NotInDefFn		;brif we're in main-level code
	dec	ax			;ax = oPrs for DEF FN
	or	ah,80h			;ax = oRs of DEF FN
	xchg	di,ax			;di = oRs of DEF FN
NotInDefFn:
	call	NeedContContext		;grs.oRsCur=grs.oRsCONT or grs.oMrsMain
					;if no main module, uierr is set
	je	NxtStmtExit		;brif no main module
	cmp	di,[grs.GRS_oRsCur]
	je	BranchOk		;brif branching within text table
BadBranch:
	PUSHI	ax,MSG_BadNextStmt	;"Cannot cross module/procedure boundary"
	call	SetUiErr
	jmp	SHORT NxtStmtExit

BranchOk:
	mov	[grs.GRS_otxCONT],si
	call	DrawDebugScr		;so new current stmt will be hilighted
NxtStmtExit:
cEnd

;**************************************************************************
; CmdRestart()
; Purpose:
;	Restart program. Like a Step but always starts at begining of program.
;
;**************************************************************************
cProc	CmdRestart,<PUBLIC,NEAR>
cBegin
	mov	al,TRACE_STEP
	call	SetTraceMode
	mov	ax,sp			;ax = TRUE (non-zero)
	call	DoRunOrCont
cEnd

;**************************************************************************
; PStepReset
; Purpose:
;	Called whenever executor resets stack pointer.  This guarentees
;	that DebugTrace will stop the next time it is called (even for F10).
;
;**************************************************************************
cProc	PStepReset,<PUBLIC,FAR>
cBegin
	mov	[pStepFrame],0
cEnd

;**************************************************************************
; CmdStep(fPStep)
; Purpose:
;	Setup to execute the next program statement.
;	This routine is called in response to the Step and PStep
;	accelerator keys.
;
; Entry:
;	fPStep - if TRUE count procedure calls as one statement (F10).
;
; Exit:
;	PStepFrame, debugFlags, traceMode, fGotCmd are all updated
;
;**************************************************************************
cProc	CmdStep,<PUBLIC,NEAR>
	parmW	fPStep
cBegin
	call	ContContext		;activate program counter's context
	call	SkipStop		;skip past opBreakPoint or opStStop

	mov	ax,[grs.GRS_otxCONT]
	inc	ax			;test for UNDEFINED
	je	UseBp			;if Can't continue, stop at next entry
	mov	ax,[b$CurFrame] 	;get current frame
	mov	cx,[pGosubLast] 	;get gosub stack value
	jcxz	UseBp			;zero, use current frame as frame

	cmp	cx,ax			
	ja	UseBp			; brif no gosubs for this frame

	xchg	ax,cx			;else use top of stack
UseBp:
	mov	[pStepFrame],ax 	;and move it in

⌨️ 快捷键说明

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