📄 rtm86.asm
字号:
TITLE RTM86 - 8086 Runtime Module Dispatcher
;***
; RTM86 - 8086 Runtime Module Dispatcher
;
; Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
; Contains the runtime module entry point for direct
; execution which outputs the copyright messages.
; It also contains the RTM software interrupt handler
; and the runtime entry dispatch tables.
;
;******************************************************************************
INCLUDE switch.inc
INCLUDE rmacros.inc
USESEG <CONST>
USESEG <_DATA>
USESEG <_BSS>
USESEG <CDATA>
USESEG <_TEXT>
USESEG <RT_TEXT>
INCLUDE seg.inc
INCLUDE idmac.inc
INCLUDE intasg.inc
INCLUDE intmac.inc
INCLUDE files.inc
INCLUDE addr.inc
INCLUDE stack.inc
INCLUDE ulib.inc
sBegin _BSS
externW b$pULVars ;ptr to shared data items
;defined in User lib.
sEnd _BSS
sBegin _TEXT
externW VecTbl ; Start of dispatch table
externW _TEXT_START ; Start of _TEXT entries
externW _TEXT_END ; Past end of _TEXT entries
sEnd _TEXT
assumes CS,RT_TEXT
sBegin RT_TEXT
; values saved in code segment:
staticW SaveAX,,1 ;saved AX register
staticW SaveBX,,1 ;saved BX register
staticW SaveSI,,1 ;saved SI register
staticW SaveDS,,1 ;saved DS register
staticD RTMChainPtr,,1 ; RTM interrupt chain pointer
staticB UserTableFlag,,1 ;flag whether or not we're using user-table
;***
; B$RTMInstall - install the RTM interrupt vector
;
;Purpose:
; To install the RTM interrupt vector by first saving the
; current vector and then setting it to the new value.
;Entry:
; None.
;Exit:
; None.
;Uses:
; None.
;Exceptions:
; None.
;******************************************************************************
cProc B$RTMInstall,<FAR,PUBLIC>,<AX,BX,DX,DS,ES>
cBegin
PUSH CS ; DS = code segment for SAVINT
POP DS ; storage and SETVEC
SAVINT RTMChainPtr,(W0__NM*4) ;save the vector
SETVEC W0__NM,RTMVector ;set vector to the new value
cEnd
;***
; B$RTMDeinstall - deinstall the RTM vector
;
;Purpose:
; To deinstall the RTM interrupt vector by setting it
; to its previous value.
;Entry:
; None.
;Exit:
; None.
;Uses:
; None.
;Exceptions:
; None.
;******************************************************************************
cProc B$RTMDeinstall,<FAR,PUBLIC>,<AX,DX,DS>
cBegin
RSTVEC W0__NM,RTMChainPtr ;restore to the old vector
cEnd
;***
; RTMVector - Runtime module interrupt service routine.
;
;Purpose:
; This routine is executed when a compiled (non /O) module
; requests runtime support. The routine address is looked
; up in a table based upon the index postbyte (which may be
; preceded by a flag postbyte indicating special handling).
; If the requested routine is found, the far call to the
; interrupt request is backpatched into a far call to the
; requested routine and reexecuted. If a valid request is
; made that does not have a defined entry, an advanced
; feature error is issued.
;
; Before backpatch:
; <FAR CALL stubroutine> --> <INT + postbyte(s)> --> RTMVector
;
; After backpatch:
; <FAR CALL realroutine>
;Entry:
; [SS:SP] - far pointer to first post byte.
;Exit:
; FAR CALL to the Interrupt is backpatched and execution is restarted
; at the backpatched call.
;Uses:
; None.
;Exceptions:
; B$ERR_AFE.
;****
; These two code fragments are out here so that the normal case (single
; postbyte) can be a complete fall through for speed. If either of
; the double postbyte cases are encountered, the code will jump out
; here to one of these fragments which will jump back when they are done.
Part2: LODSB ; [AL] = second post byte
INC AH ; [AX] = index into table (adjusted)
JMP SHORT DoIt ; continue
DbPub RTMVector
cProc RTMVector,<FAR>
cBegin <nogen>
MOV CS:[SaveAX],AX ;save AX, but not on stack
MOV CS:[SaveBX],BX ;...and BX
MOV CS:[SaveSI],SI ;...and SI
MOV CS:[SaveDS],DS ;...and DS
POP SI ;get return offset (third byte in call)
POP DS ;get return segment
POPF ; enable ints
; Some trickery for handling table indicies:
; The RTM dispatch table is "missing" the entry corresponding to
; 255 because a postbyte of FF is a special flag, and IF NOT EI_QB
; it is also "missing" the entry at 254 (another flag). To allow
; addressing the table as a contiguous block, indicies in part 1
; of the table (single postbyte entries) are bumped up (as a side
; effect of testing for flag values). This makes the index set
; contiguous but 2 bytes (or 4 IF NOT EI_QB) too high. We adjust
; for this by addressing 2 bytes (or 4) below the table base.
MOV BX,_TEXTOFFSET VecTbl - 2 ;base of table minus 2 bytes
LODSB ; [AL] = dispatch table index or flag
XOR AH,AH ; [AX] = dispatch table index or flag
INC AL ; part 2 of table? (2 post bytes)
JZ Part2 ; yes, go read second post byte
DoIt: ADD AX,AX ; [AX] = word offset+2 into dispatch table
ADD BX,AX ; [BX] = CS Pointer into dispatch table
MOV AX,SEG _TEXT
MOV DS,AX ; [DS:BX] points to table
MOV AX,[BX] ; [AX] = target offset
POP SI
POP DS ; [DS:SI] = return address into USER code
SUB SI,5 ; [DS:SI] = call instruction in USER code
PUSH DS ; restore return segment
PUSH SI ; stack far pointer will execute new far CALL
MOV [SI+1],AX ; backpatch OFFSET part of far call
; Determine target segment for backpatch
MOV AX,RT_TEXTBASE ; [AX] = target segment
CMP BX,_TEXTOFFSET _TEXT_START ; past start of _TEXT entries?
JB RTMVEC_20 ; Jump if not
CMP BX,_TEXTOFFSET _TEXT_END ; past end of _TEXT entries?
JAE RTMVEC_20 ; brif so
MOV AX,_TEXTBASE ; _TEXTBASE = target segment
RTMVEC_20:
MOV [SI+3],AX
MOV DS,CS:[SaveDS] ;restore original DS
MOV SI,CS:[SaveSI] ;restore original SI
MOV BX,CS:[SaveBX] ;restore original BX
MOV AX,CS:[SaveAX] ;restore original AX
RET ;far return to routine address just pushed
cEnd <nogen>
labelNP <PUBLIC,B$Undef1> ; This is a list of empty slots in
labelNP <PUBLIC,B$Undef2> ; the RTMINT table. Remove them when
labelNP <PUBLIC,B$Undef3> ; the slot is re-used to eliminate
labelNP <PUBLIC,B$Undef4> ; confusion and extranious labels.
externNP B$FrameFC
JMP B$FrameFC ; Give "Illegal Function Call"
sEnd RT_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -