📄 rtmload.asm
字号:
;Exit:
; None.
;Uses:
; AX, SI, DI, ES.
;Exceptions:
; None.
;****
;***
; ULAdjustDXAX - back up far ptr in DX:AX by number of bytes in ULSquishSize
;
;Purpose:
; Because of leading-zero compression in QLib files, the file pointers
; need to be adjusted before calling LoadRtmBlock to load the Data
; and Symbol segments. The number of bytes compressed from the file
; is in ULSquishSize. This routine takes a far pointer in DX:AX and
; backs it up ULSquishSize bytes. (Added with revision [38].)
;Entry:
; DX:AX - far pointer to be adjusted
; DS:[ULSquishSize] - number of bytes for adjustment
; DS - LOADRTM
;Exit:
; DX:AX - adjusted far pointer
;Uses:
; None
;Exceptions:
; None
;******************************************************************************
;***
; FixupRtmFile - apply fixups to RTM load (RTM only)
;
;Purpose:
; Read the fixup items from the RTM file and apply them
; appropriately to the code and data section loaded into
; memory.
;Entry:
; BX - handle of opened RTM file
; SI - zero to fixup both code and data (used in init)
; nonzero to fixup just code (used in SHELL)
; BP - segment RTM is loaded in
;Exit:
; None.
;Uses:
; AX, CX, DX, DI, BP, ES.
;Exceptions:
; DiskIOError if error during disk read of RTM file.
;******************************************************************************
;***
; FixupULFile - apply fixups to UL load (UL only)
;
;Purpose:
; Added as part of revision [10].
; Read the fixup items from the UL file and apply them
; appropriately to the code, data, and segment sections
; loaded into memory.
;Entry:
; BX - handle of opened RTM file
; CX - symbol table fixup value (0 if already done).
;Exit:
; None.
;Uses:
; AX, CX, DX, SI, DI, BP, ES.
;Exceptions:
; DiskIOError if error during disk read of RTM file.
;******************************************************************************
;***
; AppendExt - Append def extension to Filename in SpecBuffer if needed (UL Only)
;
;Purpose:
; Added with revision [24].
; Appends appropriate extension to the file in SpecBuffer if an extension
; does not already exist. If we are opening a user library, then .QLB
; will be appended, otherwise .EXE is appended.
;
; In addition to appending an extension to the file in SpecBuffer,
; this routine will also save a copy of the basename and extension
; in FNameBuff
;
; If SpecBuffer contains a pathname without a filename (recognized by
; the last char being a path char), then append the filename in FNameBuff
; to the path in SpecBuffer.
;
; No matter what the entry conditions, on exit from this routine the
; following will be set up:
; FNameBuff has null-terminated filename part of filespec
; FNameBuffLen has length of what is in FNameBuff
; SpecBuffer has null-terminated filespec (ready for dos open)
; InputStrLen has length of what is in SpecBuffer
;
;Entry:
; ES:DI = pointer in spec buffer after last byte of filespec.
;Exit:
; ES:DI = pointer to first byte of filename part of filespec.
; (if DI = OFFSET SpecBuffer, then there is no path specified)
;Uses:
; AX, CX, DX, SI.
;Exceptions:
; None.
;******************************************************************************
SearchChars DB ':','/','\','.' ;List of chars in order of search
cbSearchChars = $ - SearchChars ;size of list
DbPub AppendExt
cProc AppendExt,<NEAR>
cBegin
MOV AX,DI ; In case buffer is empty
CMP DI,OFFSET SpecBuffer ; Is the buffer empty?
JE JE_NoFileName ; Yes, go special-case it
MOV CX,cbSearchChars ;get number of chars to search for
MOV SI,OFFSET SearchChars ;point to list
XOR DX,DX
; Search for path chars, '/' and '\'. Remember the address of
; the last such char found. Then search for an extension char
; '.'. If the address of this char is > than the address of the
; last path char, then the filename had an extension. This is
; true since it is impossible to have a '.' after a path char
; and not have it be part of a filename (eg it cannot be part
; of a directory spec.
AppendSearchLoop:
PUSH CX ;save loop count
PUSH DI ;save end of file name
MOV CX,DI
DEC DI ;point to last char in name
SUB CX,OFFSET SpecBuffer ;compute char count in SpecBuffer
LODSB ;[AL] = search char
STD ;search backwards in file name
REPNE SCASB ;search backward for char
CLD ;go forward again
JNE CharNotFound ;brif we did not find character
INC DI ;Set DI to char before last
CharNotFound:
INC DI ; REPNE SCASB subtracts 1 at end.
XCHG AX,DI ;save address of char/start of buffer
;NOTE: Be careful here. The results of the Next compare are used after
; the loop is terminated. The current algorithm ensures that the
; instructions used between this compare and the next branch after
; the loop is terminated do not alter the carry and/or zero flag.
CMP AX,DX ;Is this char after prev char?
JB AppendSearchNext ;brif not
XCHG AX,DX ;remember address of char
AppendSearchNext:
POP DI ;recover end of filename
POP CX ;recover loop count
LOOP AppendSearchLoop ;continue until all chars searched for
;NOTE: See NOTE above.
JA AppendExtExit ;brif already have the extension
; There are two conditions in which we do not have a filename:
; 1.) An empty buffer, in which case we wont get here.
; 2.) A path without a name, when DX = DI
MOV AX,DX ; Set AX = ptr to last path char
CMP DI,DX ; Check for no name specified
JE_NoFileName:
JE NoFileName ; None given, append the old one
; File name needs an extension appended. If we are loading a user lib,
; then the extension is .QLB, otherwise, we must be loading an .EXE
; file as the result of a QBC exec. All of these files are .EXE
; files.
MOV SI,EXEExt ;get ptr to .EXE extension
CMP fQBCExec,CL ;are we loading a user lib?
JNZ AddExt ;brif not - QBC exec loads .EXE files
MOV SI,QLBExt ;get ptr to .QLB extension for ulib
AddExt:
MOVSW ; add 4-byte extension to file name
MOVSW
AppendExtExit:
DbAssertRel CX,Z,0,LOADRTM,<AppendExt: trying to use CX for 0 and it's not>
XCHG CX,AX ; AL = zero, saving AX in CX
STOSB ; null terminate the filename
XCHG CX,AX ; restore AX
; The starting point to copy is AX => SI
; The number of characters in the name is DI - AX => CX
MOV CX,DI ; Calculate Length of name
SUB CX,AX ; without path
CMP CX,MaxFNameBuff ; Are there too many characters
; in filename?
JBE ValidLength ; No, name is valid
; There are a couple cases where we will have a double-null terminated
; name here. That could create a name 1 byte longer than ValidLength,
; but it's not really a problem. The release code will fall through
; and cut back the length by 1, removing 1 null. If there is a name
; even longer than that, it's a bug. Assert it.
DbAssertRel CX,E,<MaxFNameBuff+1>,LOADRTM,<AppendExt: filename is too long>
MOV CX,MaxFNameBuff ; Truncate name to max length
ValidLength:
MOV FNameBuffLen,CX ; Save Length of FName
MOV SI,AX ; DS:SI points to begining of name
MOV DI,OFFSET FNameBuff ; ES:DI points to FNameBuff
REP MOVSB ; Copy the name only into FNameBuff
MOV DI,SI ; DI points 1 past end of filespec
; Set InputStrLen = length of filespec in SpecBuffer
Return:
SUB DI,OFFSET LOADRTM:SpecBuffer ; DI = length of filespec
XCHG AX,DI ; DI = return value, AX = length
MOV [InputStrLen],AL ; Store the length
DbAssertRelB AH,Z,0,LOADRTM,<AppendExt: filespec longer than 127 characters>
cEnd
NoFileName:
; If we get here, SpecBuffer has a pathname (terminated with a path char)
; but no filename. If we already have a filename in FNameBuff, we'll
; append it to the path in SpecBuffer
MOV CX,FNameBuffLen ; length of name in FNameBuff
MOV SI,OFFSET LOADRTM:FNameBuff ; source pointer
REP MOVSB ; append the filename
JMP SHORT Return ; set return value and exit
;***
; OpenFile - Open the file specified in SpecBuffer.
;
;Purpose:
; Added with revision [13].
; Opens the filespec in SpecBuffer
;Entry:
; SpecBuffer set up.
;Exit:
; if open worked
; PSW.C reset
; AX = file handle
; else
; PSW.C set
; endif
;Uses:
; Per convention.
;Exceptions:
; Disk IO Error.
;******************************************************************************
cProc OpenFile,<NEAR> ;common routine to open file
cBegin
MOV DX,OFFSET SpecBuffer ;DS:DX has pointer to file specification
OpenFile2:
cmp ss:fDebugScr,0 ; brif not initialized and not
jz NoCheckDrive ; displaying QB's screen
push ds ; save LOADRTM segment
mov bx,dx ; put ptr into index register
push ds:[bx] ; OpenCheckDrive parm = first 2
; of file spec (possible DRIVE:)
push ss ; DS = DGROUP for UI call
pop ds
call OpenCheckDrive ; if required, switch DOS's logical
; disk drive, and display message
; "insert disk in drive X:"
; PRESERVES ALL REGISTERS
pop ds ; restore register
NoCheckDrive:
MOV AX,(C_OPEN SHL 8)+0 ;DOS function to open the file for input only
INT 21H ;perform the open - carry set if failed
cEnd
;***
; CloseFile - Close the file handle in BX (RTM and UL)
;
;Purpose:
; Added with revision [18].
; Closes the file handle in BX.
;Entry:
; BX - file handle to close.
;Exit:
; None.
;Uses:
; AX.
;Exceptions:
; Disk IO Error.
;******************************************************************************
cProc CloseFile,<NEAR>
cBegin
MOV AH,C_CLOSE
INT 21H ;close the file
JC DiskError ;brif error
cEnd
DiskError:
JMP DiskIOError ;report the error and die.
assumes DS,DGROUP
;***
; ULConsisCheck - performs consistency checks on user libs (UL only)
;
;Purpose:
; Added as part of [10].
; Does user library consistency checking. Verifies correct
; segment ordering and size of hole allocated in UL for
; QB4 static data.
;Entry:
; SI - size of QB4 static data
;Exit:
; SI - offset of XIB in UL data
; DI - offset of XIE in UL data
; CX - offset of BC_SAB in UL data
;Uses:
; AX, BX, DX
;Exceptions:
; Consistency errors.
;****
;***
; ULCheckNextName - Verify that next segment is expected. (UL only)
;
;Purpose:
; Added as part of [10].
; Checks the next segment name in the symbol table and see
; if it matches the expected segment name. If not then
; segments are out of order, and a consistency error is issued.
;Entry:
; DX - points to expected segment name string descriptor
; ES:BX - points to previous symbol table entry
;Exit:
; DX - advanced to next sd in segment name list
; ES:BX - advanced to next symbol table entry
;Uses:
; CX, SI, DI
;Exceptions:
; Consistency error if next segment isn't the expected segment.
;****
;***
; ULFindName - Finds a specified segment name in symbol table (UL Only)
;
;Purpose:
; Added as part of revision [10].
; Finds the specified segment name in the symbol table.
; If the segment name is not found, a consistency error
; is detected.
;Entry:
; ES:BX - points to next symbol table entry
; SI - points to segment name to search for
; CX - count of characters in segment name
;Exit:
; ES:BX - points to symbol table entry containing segment name
;Uses:
; DI
;Exceptions:
; Consistency error if name not found.
;****
;***
; ULFindNameBegin - Finds a specified segment name in symbol table (UL Only)
;
;Purpose:
; Added as part of revision [10].
; Finds the specified segment name in the symbol table.
; This routine starts searching from beginning of symbol table
; If the segment name is not found, a consistency error
; is detected.
;Entry:
; ES - symbol table segment
; DX - points to sd of segment to search for
;Exit:
; ES:BX - points to symbol table entry containing segment name
; AX - offset of segment that was found from DS:0
; DX - advanced to next sd in segment name list
;Uses:
; CX, DI
;Exceptions:
; Consistency error if name not found.
;****
;***
; ULNextName - Get ptr to next expected segment name. (UL only)
;
;Purpose:
; Added as part of revision [10].
; Get next segment name from list of segment name string
; descriptors. Set up a ptr to the actual name in SI
; and the length of the name in CX. Advance DX to point
; to next sd in list.
;Entry:
; DX - points to expected segment name string descriptor
;Exit:
; SI - points to zero terminated segment name.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -