📄 rtmload.asm
字号:
; CX - contains count of bytes in name pointed to by SI.
; DX - advanced to next sd in segment name list.
;Uses:
; None.
;Exceptions:
; None.
;****
;***
; ULFindData - Get ptr to Data item. (UL only)
;
;Purpose:
; Added as part of revision [15].
; Find a data item in user library.
;Entry:
; DX - points to string descriptor for data item.
;Exit:
; AX - DGROUP offset of data item (0 if not found).
;Uses:
; BX, CX, DX, SI, DI
;Exceptions:
; Consistency error if not found.
;****
SUBTTL QBC Exec support
PAGE
;***
; LoadQBExe - Reload the interpreter into memory (QBI only)
;
;Purpose:
; Added with revision [18].
; Reloads the interpreter into memory after completing a COMPILE
; Dialog.
;Entry:
; BX - QB.EXE file handle.
;Exit:
; None.
;Uses:
; AX,CX,DX,SI,DI,BP.
;Exceptions:
; DOS Memory allocation error.
; Out of memory error.
;******************************************************************************
PAGE
;***
; SearchForChar - Search for specified char in buffer (QBI Only)
;
;Purpose:
; Added with revision [18].
; Searches for a specified char in a buffer and returns
; the distance from buffer start to the specified char.
; ASSUMES THAT CHAR WILL ALWAYS BE FOUND.
;Entry:
; AL - Char to search for.
; ES:DI - points to buffer
;Exit:
; CX - distance from ES:DI on entry to specified Char (not including char)
; ES:DI - points to requested char.
;Uses:
; None.
;Exceptions:
; None.
;******************************************************************************
PAGE
;***
; ExecCommands - Exec list of commands for COMPILE dialog (QBI Only)
;
;Purpose:
; Added with revision [18].
; Execs the list of commands built from the COMPILE dialog box.
;Entry:
; envSeg = ENV seg to pass on to B$SHELL
;Exit:
; b$QBCData.fErrorCode - non-zero if error occurred.
;Uses:
; AX,BX,CX,DX,SI,DI,ES,BP.
;Exceptions:
; Disk IO Error.
;******************************************************************************
PAGE
;***
; B$ExecQBC - Exec list of commands as requested from COMPILE Dialog (QBI Only)
;
;Purpose:
; Added with revision [18].
; Invokes list of commands generated by the user interface in
; response to a COMPILE dialog box. The interpreter will be
; released except for this loader, the error messages, and DGROUP.
; The list of commands will then be processed.
;Entry:
; psdCommands - ptr to sd containing command list.
;Exit:
; AX = 0 if no error occurred.
;Uses:
; Per Convention.
;Exceptions:
; Out of memory error.
; Disk IO error.
;****
;****
;B$FindFileOnPaths (pszFile, pszUserPath, pEnvVar, cbEnvVar)
;
;Purpose:
; Moved here from uipaths.asm with revision [69].
; Searches the current directory, the appropriate user-specified
; search path, and the appropriate environment variable for the
; file pszFile and returns a pointer to a fully-qualified pathfile
; name where the file was found. If the filename contains a path
; then we just look in that one place and no further searching is
; done.
;
;Input:
; pszFile - far pointer to null-terminated file name to open
; pszUserPath - near pointer to user-specified path from Options menu
; pEnvVar - far pointer to environment variable name specifying
; last-chance search path
; cbEnvVar - length of environment variable pointed to by pEnvVar
;
;Output:
; if successful
; DX:AX == pointer to pathfile name where file was found
; else
; AX == 0
;
;****
cProc B$FindFileOnPaths,<PUBLIC,FAR>,<SI>
parmD pszFile
parmW pszUserPath
parmD pEnvVar
parmW cbEnvVar
cBegin
ASSUMES DS,NOTHING
; First check for a path/file name.
LES SI,[pszFile] ; es:si points to file name
SearchLoop:
LODS BYTE PTR ES:[SI] ; read a byte
OR AL,AL ; end of string?
JZ NotPathFile ; yes, no path found, go do search
CMP AL,'\' ; found a path specifier?
JE PathSpecified ; yes, go try open without search
CMP AL,'/' ; found a path specifier?
JE PathSpecified ; yes, go try open without search
CMP AL,':' ; found a path specifier?
JNE SearchLoop ; no, keep searching
; If we fall through to here then the filename contains an explicit path.
; Check for existence of the specified path/file and do no more searching.
PathSpecified:
PUSH DS
LDS DX,[pszFile] ; ds:dx points to path/file name
CALL OpenFile2 ; try to open the file
XCHG AX,BX ; BX = file handle (if open worked)
MOV AX,0 ; can't use XOR because we need PSW.C
JC FileNotFound ; it's not there, exit with ax = 0
PUSH DX ; save offset of successful filespec
CALL CloseFile ; close the file
MOV DX,DS
POP AX ; DX:AX = ptr to successful filespec
FileNotFound:
POP DS
JMP SHORT FindFileExit ; exit
; Look for file in current directory first
NotPathFile:
; Note: We have to use fully-qualified pathspec to current directory for
; many reasons, including checking for "File already loaded" and
; disabling DPATH.
PUSH DS ; preserve ds
PUSH CS
POP DS ; DS = LOADRTM
MOV SI,OFFSET LOADRTM:SpecBuffer ; point to target buffer
PUSH SI ; save ptr to SpecBuffer for call
MOV AH,19h ; "get current drive" function
INT 21h
PUSH AX ; save drive number (0 relative)
ADD AL,'A' ; drive number -> drive letter
MOV [SI],AL ; store drive letter
MOV WORD PTR [SI+1],"\:" ; store ":" and "\"
ADD SI,3 ; DS:SI points to target
POP DX ; DL = drive number (0 relative)
INC DX ; make 1 relative
MOV AH,47h ; "get current dir" function
INT 21h ; get the current directory
POP BX ; CS:BX = ptr to SpecBuffer for call
POP DS ; restore DS
JC NotInCurDir ; current dir is invalid, the file
; we're looking for can't be there
XOR AX,AX
cCall B$SearchOnePath,<seg_pszFile,off_pszFile,AX,CS,BX>
OR AX,AX ; find file in current directory?
JNZ FindFileExit ; yes, exit with DX:AX = pointer
NotInCurDir:
; Didn't find it in the current directory, try the user-specified
; search path from the options menu.
cCall B$SearchOnePath,<seg_pszFile,off_pszFile,AX,SS,pszUserPath>
OR AX,AX ; find file on that path?
JNZ FindFileExit ; yes, exit with DX:AX = pointer
; Didn't find it there either, try the path defined by the
; specified environment variable.
cCall B$SearchEnv,<seg_pEnvVar,off_pEnvVar,cbEnvVar>
OR AX,AX ; find the environment variable?
JZ FindFileExit ; no, exit with AX = 0
XOR BX,BX ; get a zero
cCall B$SearchOnePath,<seg_pszFile,off_pszFile,BX,DX,AX>
; B$SearchOnePath returns exactly what we want to return here,
; so no further processing is necessary.
FindFileExit:
cEnd
;****
;B$SearchOnePath - find a file on a search path
;
;Purpose:
; Searches the specified path for the specified file.
; Return a pointer to a fully-qualified pathname if search
; is successful, otherwise return AX = 0.
;
;Input:
; pFileName far pointer to filename to open
; cbFileName length of filename
; pSearchPath far pointer to search path (list of directories
; separated by ";" terminated by null)
;Output:
; if successful
; DX:AX = far pointer to fully-qualified pathname
; else
; AX = 0
;
;****
cProc B$SearchOnePath,<NEAR>,<DS,SI,DI>
ParmD pFileName
ParmW cbFileName
ParmD pszSearchPath
CalcLength:
XOR AX,AX ; get a zero for scanning
DEC CX ; CX = -1 for long search
LES DI,[pFileName] ; ES:DI points to filename
REPNE SCASB ; scan for a 0
NOT CX ; length of string (including null)
DEC CX ; length without null
MOV [cbFileName],CX ; store that length
JMP SHORT HaveLength
cBegin
MOV CX,[cbFileName]
JCXZ CalcLength
HaveLength:
ASSUMES DS,NOTHING
LDS SI,[pszSearchPath] ; DS:SI points to search path
SearchPathLoop:
PUSH CS
POP ES
MOV DI,OFFSET LOADRTM:SpecBuffer ; ES:DI points to buffer
CopyPathToBuf:
XOR CX,CX ; initialize count of bytes moved
CopyLoop:
LODSB ; get next byte
OR AL,AL ; done with list?
JE CopyEnd ; yes
CMP AL,';' ; is it path separator?
JE CopyDone ; yes, copy is done
STOSB ; put the byte in the buffer
INC CX ; count this byte
XCHG AH,AL ; save stored byte in AH
JMP SHORT CopyLoop
CopyEnd:
XOR DX,DX ; if CX=0, we want to jump with DX=0
JCXZ OpenError ; ran out of paths, file not found
DEC SI ; point to null terminator
CopyDone:
JCXZ CopyPathToBuf ; skip null path, go get next one
MOV AL,'\'
CMP AH,AL ; was last char backslash?
JE AppendFileName ; yes, don't add another
CMP AH,'/' ; was last char forward slash?
JE AppendFileName ; yes, don't add backslash
CMP AH,':' ; was last char from drive spec?
JE AppendFileName ; yes, don't add backslash
STOSB ; append a backslash to pathname
AppendFileName:
PUSH DS
PUSH SI ; save pointer to next pathname in list
LDS SI,[pFileName] ; DS:SI points to filename
MOV CX,[cbFileName] ; CX = length of filename
REP MOVSB ; append filename to pathname
XCHG AX,CX ; AX = zero
STOSB ; null terminate the filename
PUSH ES
POP DS ; DS = LOADRTM
CALL OpenFile ; attempt to open the file
MOV DI,DS ; save DS in DI in case open worked
POP SI
POP DS ; get back pointer to next path in list
JNC FoundIt ; found it, stop looking
XOR DX,DX ; DX=0 in case we go to OpenError
CMP [off_pszSearchPath],OFFSET LOADRTM:SpecBuffer
JNE SearchPathLoop ; brif input path not in SpecBuffer
MOV AX,CS ; can't use CS for CMP
CMP [seg_pszSearchPath],AX
JNE SearchPathLoop ; brif input path not in SpecBuffer
; If we fall through to here, [pszSearchPath] was really pointing to a
; single-directory path which had been placed in SpecBuffer. Now that
; we have changed SpecBuffer, we can't loop back up. But we don't have
; to because we have already checked the single directory and not found
; the file. So we just exit with "Not Found".
JMP SHORT OpenError
; DI:DX = pointer to pathspec that worked
; AX = file handle returned by open
FoundIt:
XCHG AX,BX ; put handle in BX
CALL CloseFile ; close the file
DbAssertFlags nc,LOADRTM,<B$SearchOnePath: error on close>
OpenError:
XCHG AX,DX
MOV DX,DI ; DX:AX = ptr to filespec that worked,
; or AX = 0 if got here via OpenError
cEnd
;****
;B$SearchEnv - search the environment table
;
;Purpose:
; Searches the environment table for the specified variable.
; If found, return a pointer to the value associated with the
; variable. Otherwise return 0.
;
; Note: we can make no assumptions about the value of DS on input.
;
;Input:
; pEnvVar far pointer to environment variable name
; cbEnvVar length of EnvVar
;
;Output:
; if EnvVar found in environment table
; DX:AX = ptr to value associated with the variable
; else
; AX = 0
;
;****
cProc B$SearchEnv,<NEAR>,<DS,DI,SI>
parmD pEnvVar
parmW cbEnvVar
cBegin
MOV ES,SS:[__psp] ; ProgramPSP doesn't get set up for LQB
MOV ES,ES:[2Ch] ;...get segment of environment table
XOR AX,AX ;zero AX for scan test and zero test
XOR DI,DI ;ES:DI = ptr to start of environment table
SearchEnvLoop:
LDS SI,[pEnvVar] ;DS:SI = ptr to string to search for
MOV CX,[cbEnvVar] ;CX = length of string to search for
REP CMPSB
JE SearchEnvFound ;brif found a match
TryAgain:
MOV CX,0FFFFh ;search for a long time
REPNZ SCASB ;scan to past next zero byte
CMP ES:[DI],AL ;test for double zero for end of table
JNZ SearchEnvLoop ;brif not end of table
; Got to end of table without finding a match. Return zero.
JMP SHORT SearchEnvExit
SearchEnvFound:
CMP BYTE PTR ES:[DI],'=' ;did we match the whole name or just part?
JNE TryAgain ;brif partial match, not good enough
INC DI ;bump pointer past equal sign to value
MOV DX,ES
MOV AX,DI ;DX:AX = pointer to value
SearchEnvExit:
cEnd
sEnd LOADRTM
; The data below is used when the QBI interpreter is reloaded
; after a compile dialog. The values are used prior to fixup, to
; determine what the Fixup boundaries of the reloaded code should
; be.
sBegin LOADRTMEND ;end of Resident loader
QBVersion DW BINSAV_BASICVersion ;QB version
QBRevision DB BINSAV_REVISION_BYTE ;QB revision number
QBCode DW SEG LOADRTMEND ;start of code that gets reloaded
QBData DW DGROUP ;start of DGROUP for QB
sEnd LOADRTMEND
CondEnd StartupStub ; END StartupStub if NOT EI_QB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -