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

📄 uidebug.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 3 页
字号:
	mov	al,RSN_fIndent
	push	ax			;pass GetRsName flags
	mov	al,20d
	push	ax			;cbMax = 20
	call	GetRsName		;fill bufStdMsg with name
					;ax = cbName
	mov	bx,dataOFFSET bufStdMsg ;bx points to buffer being filled
	add	bx,ax			;ax points beyond end of context's name
	mov	BYTE PTR [bx],' '
	inc	bx			;bx points to dst for expression's name
	mov	dx,CB_bufStdMsg - 3	;dx = max chars in context + expression
	DbAssertRel CB_bufStdMsg,ae,40d,UI,<WatchName: msg buffer too small>
	sub	dx,ax			;dx = max chars left for expression
	mov	[bdBuf.BD_cbLogical],dx ;pass cbMax to ListLine
	mov	[bdBuf.BD_pb],bx	;pass ptr to buffer to ListLine
	push	bx			;save ptr to expression's name
	lea	bx,bdBuf
	push	si			;pass otx to ListLine
	push	bx
	call	ListLine		;ax = #bytes listed
	pop	bx			;bx points to szExpression
	add	bx,ax			;bx points to 0-byte terminator
	mov	ax,dataOFFSET bufStdMsg + 40d
	cmp	bx,ax
	jb	LengthOk		;brif length of context+name < 40
	xchg	bx,ax			;truncate length of name to 40
					; 20 for context, 20 for expression
LengthOk:
	mov	WORD PTR [bx]," :"	;store ": " at end of expression
	inc	bx
	inc	bx			;return ax = new cbMsg
	mov	BYTE PTR [bx],0		;store 0-byte terminator
	mov	ax,dataOFFSET bufStdMsg ;ax points to start of name
	xchg	ax,bx			;bx points to start of name (ret value)
					;ax points to end of name
	sub	ax,bx			;ax = length of name (return value)
cEnd

;**************************************************************************
; WatchNameId(idWatch)
; Purpose:
;	Fill bufStdMsg with the title of a watch expression.
;	The text table containing the watch expression is also activated.
; Entry:
;	idWatch = id of watch expression (0..WATCH_MAX)
; Exit:
;	entry's register set is activated
;	bufStdMsg = '<context> <expression>: '
;
;**************************************************************************
cProc	WatchNameId,<PUBLIC,NEAR>
	parmW	id
cBegin
	mov	bx,[id]
	call	WatchInfoBx		;ax = oRs, cx = otx for id
					;bx = ptr to valTyp, value
	call	WatchName		;fill bufStdMsg with title (id)
					;bx = pbMsg, ax = cbMsg
cEnd

;**************************************************************************
; WatchPrint
; Purpose:
;	Display some information in the Watch window
;
; Entry:
;	[iWatch] = 0 to n and identifies an entry in the watch window
;	bx = pbMsg
;	ax = cbMsg
;	cx = ALERT flag (0 for normal, non-zero for WatchBreak value)
;	dx = the type of information as follows:
;	     0:  expression's title
;	     1:  expression's value
;
;**************************************************************************
cProc	WatchPrint,<PUBLIC,NEAR>,<si,di>
	localV	rrc,<size _ARC>
cBegin

	;preserve window's current attribute, set it to Watch Window's attr
	xchg	si,bx			;si = pbMsg
	mov	di,isaWatchWindow	; [17] di = current isa
	jcxz	NotAlert
	mov	di,isaWatchpointHilite	
NotAlert:
	mov	bx,dataOFFSET tCbWatchTitle
	add	bx,[iWatch]		;bx points to cbTitle field
	or	dx,dx
	je	Type0			;brif not printing Watch Value
	mov	dl,[bx]			;dx = 1 column beyond title
	jmp	SHORT DisplayIt

Type0:
	mov	[bx],al			;tCbWatchTitle[iWatch] = cbMsg

;ax = byte count
;dx = 1st column to write
;si = ptr to string to write
;
DisplayIt:
	mov	cx,80d
	mov	bx,ax
	add	bx,dx
	sub	bx,cx
	jbe	Fits
	sub	ax,bx
	jb	WpExit			;if new starting column is negative
Fits:
	PUSHI	cx,<dataOFFSET wndDebug>
	push	dx			;pass rx
	push	[iWatch]		;pass ry
	push	si			;pass ptr to string
	push	ax			;pass cch (byte count)
	push	di			;pass isa
	call	TextOut

WpExit:
cEnd



;**************************************************************************
; WatchValue
; Purpose:
;	Called by DebugWatch and DrawWatch to list
;	an expression's value into a buffer in ASCII format.
;
;	[23] Modified to not call WatchPrint (just list to buffer).
;
; Entry:
;	bx points to 1 byte valTyp, 8 byte value structure
;	[iWatch] = watch id (0..n)
; Exit:
;	bx - points to value in display (ASCII) format
;	ax - cb - length of string pointed to by bx.
;	cx - fAlert - TRUE if watch is a watchpoint.
;
;**************************************************************************
DbPub	WatchValue			
cProc	WatchValue,<NEAR>
cBegin
	mov	al,[bx]			;al = value type
	inc	bx			;bx points to value
	xor	ah,ah			;ax = 0 if no value
	or	al,al
	je	NoValue
	js	WatchErr		;brif value = standard error code
	cmp	al,12h
	je	WValPoint		;brif got watch point
	cmp	al,24h
	je	WValStr			;brif got string
	push	ds
	pop	es			;es = DGROUP (for B$IFOUT)
	;inputs to B$IFOUT are bx->number, al = type, es=ds
	call	B$IFOUT 		;bx = adr of ascii string
					;ax = byte count
	jmp	SHORT WValNoAlert

WValStr:
	mov	ax,[bx.SD_cb]		;ax = byte count for WatchValue
	mov	bx,[bx.SD_pb]		;bx = ptr to WatchValue
;bx = pbMsg, ax = cbMsg
WValNoAlert:
	sub	cx,cx			;normal, not Alert attribute
	jmp	SHORT WValPrint

WatchErr:
	sub	cx,cx			;cx = FALSE (no alert)
	mov	ax,[bx]			;ax = MSG_xxx (standard error code)
	jmp	SHORT PrintStdMsg

WValPoint:
	sub	cx,cx			;cx = FALSE (no alert)
	mov	ax,MSG_FALSE
	cmp	WORD PTR [bx],0		;test boolean's value
	je	PrintStdMsg		;brif boolean expression is TRUE
	.errnz	MSG_TRUE - MSG_FALSE - 1
	inc	ax			;ax = MSG_TRUE
	dec	cx			;cx = TRUE (alert)
PrintStdMsg:
	push	cx			;preserve alert flag
	push	ax			;pass msg id to ListStdMsg
	call	ListStdMsg		;ax = byte count of msg
	pop	cx			;restore alert flag
	mov	bx,dataOFFSET bufStdMsg	;bx points to start of msg

;bx = pbMsg, ax = cbMsg
;cx = ALERT flag (0 for normal, non-zero for WatchBreak value)
WValPrint:
NoValue:
cEnd

;**************************************************************************
; DrawWatch()
; Purpose:
;	Called to draw Watch Window whenever the debug screen is being drawn.
;
;**************************************************************************
cProc	DrawWatch,<PUBLIC,NEAR>
cBegin
	mov	ax,[cWatch]		;ax = # watch active expressions
;if      FV_INSTWAT 		     
;	     sub     ax,[cInstWatch]	     ; Leave out any instant watch.
;endif   ;FV_INSTWAT		     
	mov	[iWatch],ax		;start with bottom WATCH line
DwLoop:
	mov	ax,[iWatch]
	dec	ax
	mov	[iWatch],ax
	js	DwExit			;brif end of watch expressions
					;i.e. if iWatch == UNDEFINED

	call	WatchInfoUI		;ax = oRs, cx = otx for iWatch
					;[bx] = ptr to valTyp, value
	push	bx			;save ptr to watch value
	call	WatchName		;fill bufStdMsg with title (iWatch)
					;bx = pbMsg, ax = cbMsg
	sub	dx,dx			;watchInfo = TITLE
	sub	cx,cx			;not ALERT
	call	WatchPrint		;display Watch title
	pop	bx			;bx = ptr to watch value
	call	WatchValue		;display Watch value on screen
					;bx = pbMsg, ax = cbMsg, cx = fAlert
	mov	dx,1			;print value, not title
	call	WatchPrint		
	jmp	SHORT DwLoop

DwExit:
cEnd

;**************************************************************************
; DebugWatch()
; Purpose:
;	This is called when we enter direct mode while any watch expressions
;	are active.  It updates the display by executing the watch opcodes.
; Note:
;	Currently, the only watch expressions which get updated are those
;	from the current context (i.e. if a SUB is active, only expressions
;	entered while the SUBs list window was active are updated).
;	If you are tempted to allow all watch expressions to be updated
;	no matter which oRs is active, be warned:  The scanner must
;	prevent function and DEF FN references in WATCH pcode, the
;	most recent BP for the sub must be loaded into BP temporarily
;	(so the most recent incarnation of the SUBs variables can be
;	accessed), error and event trapping would have to be disabled.
; Entry:
;	[iWatch] = UNDEFINED if UserInterface was entered after executing
;		   user pcode.
;	[iWatch] = 0..n if UserInterface was entered after executing
;		   watch expression [iWatch]
; Exit:
;	if next pcode to execute is Watch pcode
;	   iWatch is set to 0..n, indicating which Watch pcode is being executed
;	   grs.otxCur is set pointing to the watch pcode to execute
;	   grs.fDirect is set FALSE.
;	   grs.GRS_flags.FG_WatchActive is set
;	   returns TRUE (non-zero)
;	if next pcode to execute is user pcode
;	   iWatch is set to UNDEFINED
;	   grs.otxCur, grs.fDirect, grs.oRsCur are restored from the
;	      static values which were saved by DebugWatch when the last
;	      user pcode finished executing
;	   grs.GRS_flags.FG_WatchActive is clear
;	   returns FALSE
;	Condition codes are set based on value in ax
;
;**************************************************************************
;Note:
;	The code is organized so that the most common path makes no branches
;	so it is as fast as possible.
;

;NOTE:	This isn't the main entry --- DebugWatch is below.  This is here
;	for optimal short-jump space.
;	dl = [debugFlags]
UserPcode:
	;If we execute Watch pcode after each direct mode statement, we could
	;never execute RUN or SYSTEM if one of the Watchpoints was TRUE.
	;So, we just execute it at the end (opEot) of the direct mode stmt.
	
	test	dl,DEBUG_ERROR OR DEBUG_STOP
	jne	J1_DWatchFalse		;brif runtime error in user-pcode
	mov	ax,[grs.GRS_otxCur]	;capture cur execution state in ax,bl
	mov	bl,[grs.GRS_fDirect]
	or	bl,bl
	je	SaveState1		;brif not executing Direct Mode stmts
	test	[grs.GRS_flags],FG_allSsExecute
	je	J1_DWatchFalse		;can't execute WATCH pcode if some
					; text table isn't scanned to SS_EXECUTE
	inc	ax			;test for UNDEFINED
	je	SaveState		;brif just executed an dir mode opEot
J1_DWatchFalse:
	jmp	DWatchFalse		;brif user stmt had an error

SaveState:
	;preserve state of user's pcode before we begin executing WATCH pcode
	dec	ax			;restore ax = grs.otxCur
SaveState1:
	mov	[bpWatchSave],bp
	mov	[otxWatchSave],ax
	mov	ax,[b$errnum]		
	mov	[errnumSave],ax 	
	mov	[fDirectSave],bl
	sub	ax,ax			;initial iWatch is 0
	jmp	SHORT ExWatchPcode


cProc	DebugWatch,<PUBLIC,FAR>
cBegin
NextWatch:
	mov	dl,[debugFlags]
	or	dl,dl
	.errnz	DEBUG_CANT_CONT - 80h
	js	J1_DWatchFalse		;don't try to watch if can't continue
					; otherwise it screws up error reporting
	mov	ax,[iWatch]
	inc	ax			;test for UNDEFINED
	je	UserPcode		;brif just executed user pcode
;ax = index for next WATCH pcode to execute
ExWatchPcode:
	cmp	bp,[bpWatchSave]
	jb	WatchInUserFunc		;brif Watch expression is evaluating
					; a user-pcode function.  Don't execute
					; watch expressions recursively.
	test	[debugFlags],DEBUG_ERROR
	je	NoWatchErr		;brif no error in previous watch-pcode
	push	ax			;save iWatch for next watch expression
	and	[debugFlags],NOT DEBUG_ERROR
	call	WatchInfoUI		;bx = ptr to valTyp, value
					; for watch expression with error
	push	bx			;save ptr to watch entry
	push	bx			;pass parm = ptr to watch entry
	call	ZeroWatchVal		;release string descriptor if any
	pop	bx			;bx = ptr to watch entry
	mov	BYTE PTR [bx],0FFh	;valtyp = std error code
	sub	ax,ax
	xchg	ax,[b$ErrNum]
	mov	[bx+1],ax		;save error code
	pop	ax			;restore ax = iWatch for next expression
;ax = index for next WATCH pcode to execute
NoWatchErr:
	cmp	ax,[cWatch]
	jae	EndWatch		;brif last watch exp has been executed
	mov	[iWatch],ax
	xchg	bx,ax			;bx = iWatch
	call	WatchInfo		;ax = oRs for text table for iWatch
					;cx = otx to start of watch pcode
					;bx = ptr to valTyp, value
					;grs.fDirect = FALSE
	cmp	ax,[grs.GRS_oRsCur]
	jne	DOutOfScope		;brif exp isn't from current context
	mov	[pWatchVal],bx		;tell executor where to store value
	mov	[grs.GRS_otxCur],cx
	mov	[grs.GRS_fDirect],0	
	or	[grs.GRS_flags],FG_WatchActive
	DbAssertTst [grs.GRS_flags],ne,FG_allSsExecute,UI,<DebugWatch err1>
DWatchTrue:
	mov	ax,sp			;return TRUE - tells caller we're
					; about to execute watch-pcode
	or	ax,ax			;set condition codes for caller
DWatchExit:
cEnd

;bx points to entry in watch table for current watch expression
DOutOfScope:
	DbHalt	UI,<DOutOfScope: Watch code not enabled for LQB>	
	or	[debugFlags],DEBUG_ERROR
	jmp	NextWatch		;go get next watch expression

;Watch expression is evaluating a user supplied function
;If runtime error occurs within a watch expression, it is untrappable
; and reported.
;Otherwise, just return and continue executing the function.
;This causes TRACE to be disabled during WATCH pcode.
;
WatchInUserFunc:
	test	[debugFlags],DEBUG_ERROR OR DEBUG_STOP
	je	DWatchTrue		;brif watch expression had no error
	or	[debugFlags],DEBUG_CANT_CONT
					;don't allow user to continue after
					; error in Watch function
	jmp	SHORT DWatchFalse	;let error/breakpoint/stop within
					;user-function be reported.

EndWatch:
	cmp	[fDebugScr],FALSE
	je	NoDebugScr		;brif debug screen not visible
DebDrawLoop:
	call	WatchInfoUI		;bx = ptr to valTyp, value
	call	WatchValue		;display Watch value on screen
	mov	dx,1			;print value, not title
	call	WatchPrint		
	dec	[iWatch]
	jns	DebDrawLoop

;Restore state of user-pcode that was interrupted to execute watch-pcode
NoDebugScr:
	mov	al,[fDirectSave]
	mov	[grs.GRS_fDirect],al
	mov	ax,[errnumSave] 	;restore value of b$errnum from
	mov	[b$errnum],ax		;  before WATCH pcode execution
	mov	ax,[otxWatchSave]
	mov	[grs.GRS_otxCur],ax
	DbAssertRel bp,e,[bpWatchSave],UI,<DebugWatch: invalid bp>
DWatchFalse:
	and	[grs.GRS_flags],NOT FG_WatchActive
	mov	ax,UNDEFINED
	mov	[iWatch],ax
	inc	ax			;return FALSE - tells caller we're
	jmp	SHORT DWatchExit	;about to execute user-pcode
					;Condition codes are also set for caller


sEnd	UI

end

⌨️ 快捷键说明

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