📄 uidebug.asm
字号:
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 + -