📄 error.asm
字号:
TITLE ERROR - Error trapping for 8086 Basic Compiler
page ,132
;***
; ERROR - Error trapping for 8086 Basic Compiler
;
; Copyright <C> 1986, 1987, Microsoft Corporation
;
;Purpose:
; This module contains the run-time support for error trapping in addition to
; the standard routines.
;
; BASIC Syntax mapping to included runtime entry points:
;
; - ERR Variable:
;
; v = ERR
; |
; B$FERR
;
;
; - ERL Variable:
;
; v = ERL
; |
; B$FERL
;
;
; - ON ERROR Statement:
;
; ON ERROR GOTO line
; ------------------
; |
; B$OEGA
;
;
; - RESUME Statement
;
; RESUME [0 | NEXT | line]
;
; Examples:
;
; RESUME RESUME 0 RESUME NEXT RESUME 10
; | -------- ----------- ---------
; | | | |
; B$RES0 B$RES0 B$RESN B$RESA
;
;
;******************************************************************************
INCLUDE switch.inc ;Rutime switch file
INCLUDE rmacros.inc ;General runtime macros
useSeg _BSS
useSeg _DATA
useSeg ER_TEXT
useSeg NH_TEXT
INCLUDE seg.inc ;Segment definitions
INCLUDE addr.inc ;Frame and module specific data definitions
INCLUDE idmac.inc
INCLUDE messages.inc ;error message label definitions
INCLUDE stack.inc
sBegin _BSS
externD b$erradr ; Far ptr to basic error address
externW b$errnum ; Error number encountered
externW b$errlin ; Basic line number of error
externB b$inonerr ; flag indicating we're in an on error
externW b$curlevel ;current program level
externW b$curframe ; pointer to current BASIC frame
externW b$cCSubs ; <> 0 means compiled code
sEnd _BSS
externFP B$EXSA ; clear frame state info
externFP B$SERR
externFP B$CEND
sBegin NH_TEXT
externNP B$STDALCALLTMP
sEnd NH_TEXT
sBegin ER_TEXT
externNP B$CALCLINE ;Get line number & start address of stmnt
externNP B$GETMODCODE ;Get module specific code data.
externNP B$RES_SETUP ;Clear flags for RESUME
assumes CS,ER_TEXT
SUBTTL B$OEGA - ON ERROR GOTO statement handler
PAGE
;***
; B$OEGA - ON ERROR GOTO statement handler
;
;Purpose:
; sets the address to which an error is to branch. If zero, and we are in an
; on error handler, then declare a fatal error.
;
;Entry:
; erradr = statement address or 0
;
;Exit:
; Sets error vector with line number address
;
;Exceptions:
; erradr == 0 and an error is in progress, will jump to B$SERR instead of
; returning.
;
;******************************************************************************
cProc B$OEGA,<FAR,PUBLIC>
parmD erradr
cBegin
MOV AL,OF_DAT ;Get location of module specific data
PUSH SI
CALL B$GETMODCODE ;From the module specific code segment
XCHG AX,SI ;Into SI
MOV CX,off_erradr ; [CX] = offset of on error target
INC CX
JCXZ OEGA_3 ; disable error handling if CX = -1 or 0
DEC CX
OEGA_3:
MOV [SI].OFD_ONERROR,CX ; Set error vector
POP SI
JCXZ OEGA_10 ; jump if not setting a valid address
OEGA_5:
cEnd
;
; In error handling routine, must pretend we just had last error
;
OEGA_10:
CMP [b$inonerr],CL ; Test if error in progress
JE OEGA_5 ; No - just return
MOV BP,[BP] ;restore to user program frame
ADD SP,8 ;toss return address and param
PUSH [b$errnum] ;parameter is the error number
PUSH [WORD PTR b$erradr +2] ;"Return Address" use error segment
PUSH [WORD PTR b$erradr] ;"Return Address" Use error offset
JMP B$SERR ;Process error (Never Returns)
SUBTTL B$RESA - RESume At line number
PAGE
;***
; B$RESA - RESume At line number
;
;Purpose:
; Runtime entry for the RESUME <linenumber> statement
;
;Entry:
; [AX] = Address to RESUME to.
;
;Exit:
; to address. Clears on-error-in-progress
;
;Exceptions:
; Aborts if no error in progress
;
;******************************************************************************
cProc B$RESA,<FAR,PUBLIC,FORCEFRAME>
cBegin
; Warning! This assumes B$RES_SETUP never returns with AX trashed
CALL B$RES_SETUP ;perform initial RESUME stuff
PUSH AX ; save address to resume to
MOV BX,[b$curframe] ; current BASIC frame
MOV BX,[BX] ; want previous BASIC frame
CALL B$CEvtHndlr ; Was it an event handler?
OR AX,AX ; AX = 0 if an event handler
POP BX ; [BX] = address to resume to
JZ RESRET ; treat event handlers specially
XOR AX,AX ; set to zero for string dealloc
CALL B$STDALCALLTMP ;dealloc all temp strings
CMP [b$curlevel],1 ; check for main module
JE RESRET ; At main level - use old frame
MOV [b$curlevel],AX ; set [b$curlevel] to main level (AX=0)
DEC [b$cCSubs] ; INCed in B$ENSA
MOV [BP].FR_RETOFF,BX ; replace return offset with resume addr.
cEnd ; RETF to resume address
SUBTTL B$RES0 - RESUME [0]
PAGE
;***
; B$RES0 - RESUME [0]
; void pascal B$RES0()
;
;Purpose:
; Runtime Entry Point for RESUME [0]
;
;Input:
; NONE
;
;Output:
; Clears error flags and error number
;
;******************************************************************************
cProc B$RES0,<FAR,PUBLIC,FORCEFRAME>
cBegin
CALL B$RES_SETUP ; clear error flags and error number
MOV AX,[WORD PTR b$erradr] ;Get error address
MOV BX,[BP] ;Get User program frame pointer
cCall B$CALCLINE ; [BX] = address of start of statement
DbAssertFlags NZ,ER_TEXT,<Statement start not found in B$RES0>
RESRET: ; moved here from B$RESA
POP BP ; Restore saved BP
POP AX ; Throw away return offset
XCHG AX,BX ; [AX] = return offset
POP DX ; [DX:AX] = resume address
CALL B$EXSA ; Preserves DX:AX
PUSH DX
PUSH AX ; Save line number as offset
RET ; Return
cEnd nogen
SUBTTL B$RESN - RESUME NEXT
PAGE
;***
; B$RESN - RESUME NEXT
; void pascal B$RESN
;
; Purpose:
; Runtime Entry Point - RESUME NEXT
;
; Input:
; NONE
;
; Output:
; NONE
;
;******************************************************************************
cProc B$RESN,<FAR,PUBLIC,FORCEFRAME>,SI
cBegin
CALL B$RES_SETUP ; clear error flags and error number
PUSH DS ;Save DS
MOV AL,OF_STA
CALL B$GETMODCODE ; Get statement number address table
XCHG AX,SI
MOV CX,[WORD PTR b$erradr] ; Get return offset
MOV DS,BX ; Get module CS
MOV BX,-1 ;Start out with maximum address
rsnlop: LODSW ;(AX) = next address to check
OR AX,AX ;Check if end of table
JZ rsnend ; Yes
CMP AX,CX ;Are we less than original address
JB rsnnxt ; Yes - skip this one
CMP AX,BX ;Are we less than current closest
JAE rsnnxt ; No - skip this one
XCHG AX,BX ;Save address in (BX) as new closest
rsnnxt: INC SI ;Skip line number entry
INC SI
JMP rsnlop ;Keep looping
rsnend:
POP DS ;restore DGROUP to DS
INC BX ;Bump by 1 to map -1 to 0 (maybe)
JNZ rsnret ; Not 0 - return to user program
JMP B$CEND ; Resume off the bottom is an END
rsnret:
DEC BX ;Restore to correct values
POP SI ;Restore SI
JMP RESRET ; go return
cEnd nogen
SUBTTL ERR and ERL funcitons
PAGE
;***
; B$FERR - ERR function
; I2 pascal B$FERR()
;
;Purpose:
; Runtime Entry Point - ERR function
;
;Input:
; NONE
;
;Output:
; [AX] = error number
;
;******************************************************************************
cProc B$FERR,<FAR,PUBLIC>
cBegin
MOV AX,[b$errnum] ;Get error number
cEnd
;***
; B$FERL - ERL function
; I4 pascal B$FERL()
;
;Purpose:
; Runtime Entry Point - ERL function
;
;Input:
; NONE
;
;Output:
; [DX:AX] = error line number
;
;******************************************************************************
cProc B$FERL,<FAR,PUBLIC>
cBegin
MOV AX,[b$errlin]
XOR DX,DX
cEnd
;***
;B$CEvtHndlr - Checks if a frame is an event handler
;
;Purpose:
; Determine whether the frame is for an active compiled event handler.
;
;Entry:
; BX = pointer to the COMPILED BASIC frame to check (ie. [b$curframe]).
;
;Exit:
; AX = 0 IFF an event handler is detected.
;
;Uses:
; AX, BX.
;
;Exceptions:
; None.
;
;******************************************************************************
cProc B$CEvtHndlr,<PUBLIC,NEAR>
cBegin
;
; This is the compiler-specific logic to check for a BASIC event handler:
;
MOV AX,[BX].FR_GOSUB ; AX = count of GOSUBS
DbAssertRel AX,GE,0,ER_TEXT,<More than 32767 GOSUBs in B$CEvtHndlr> ;
DEC AX ; if AX = 0, return AX <> 0
JS No_handler ; no gosubs => no event handler
SUB BX,[BX].FR_CLOCALS ; BX = BX - number of local bytes
MOV AX,[BX-FR_SIZE-2] ; AX = 0 IFF event handler
No_Handler:
cEnd ; return
sEnd ER_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -