novlmain.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 783 行 · 第 1/2 页
ASM
783 行
jne bd_1a ; yes, get started
mov BP,BPChain ; get BP of active task
else
mov BP,BPChain ; get BP
endif
jmp short bd_1a
_loop
shl CX,1 ; restore bp
mov BP,CX
bd_1a: mov CX,[BP] ; get next bp
mov DX,[BP+4] ; get (possible) segment
shr CX,1 ; check if near or far ret
ifdef OVL_MULTITHREAD
je skip_context ; NULL => not on this thread...
endif
_loopif nc ; was near so try again
cmp DX,AX ; is it our handle?
_until e ; loop until our handle
; fill in the return trap & modify stack
mov DX,[BP+2] ; get original ret addr
ifdef OVL_MULTITHREAD
mov [BX+te_stack_trap],BP
mov [BX+te_ret_offset],DX
else
mov byte ptr DS:[rt_call_far],CALL_FAR
mov word ptr DS:[rt_entry],offset __OVLRETTRAP__
mov word ptr DS:[rt_entry+2],seg __OVLRETTRAP__
mov word ptr DS:[rt_stack_trap],BP
mov word ptr DS:[rt_old_code_handle],AX
mov word ptr DS:[rt_ret_offset],DX
endif
xor DX,DX ; zero head of list
mov [BP+4],DS ;set far ret to the ret trap
mov [BP+2],DX ;. . .
_loop ; loop to link any other returns on stack
shl CX,1 ; restore bp
_quif e ; finished loop if bp 0
mov BP,CX ; advance BP
mov CX,[BP] ; check if far or near ret
shr CX,1 ; . . .
_loopif nc ; continue loop if near ret
cmp [BP+4],AX ; check if it's our code_handle
_loopif ne ; continue loop if not one of ours
dec byte ptr [BP] ; unset the far bit
mov [BP+4],DX ; add it to the list
mov DX,BP ; . . .
_endloop ; continue loop
ifdef OVL_MULTITHREAD
mov [BX+te_ret_list],DX
add BX,size TRAP_ENTRY
skip_context:
pop BP
mov BP,[BP+tl_next] ; get next context
test BP,BP
_until e ; loop until end of list
mov word ptr [BX+te_stack_trap],0 ; mark end of list
pop BX
else
mov DS:[rt_ret_list],DX
endif
pop CX
pop DS
pop BP
ret
__OVLBUILDRETTRAP__ endp
;ifdef OVL_MULTITHREAD
;
; unsigned near __OVLUNDORETTRAP__( unsigned rt_seg, unsigned new_handle );
;
;else
;
; void near __OVLUNDORETTRAP__( unsigned stack_trap, unsigned ret_offset,
; unsigned ret_list, unsigned new_handle );
;
;endif
public "C",__OVLUNDORETTRAP__
__OVLUNDORETTRAP__ proc near
;
; Walk up the linked list created by __OVLBUILDRETTRAP__ and set the segments
; to their new value. Also set the far bit in the BP chain. Remove the
; actual trap if necessary (i.e., the section has been loaded before the trap
; was invoked).
;
push BP
ifdef OVL_MULTITHREAD
; Return != 0 if the return trap is still used, 0 if no longer needed
push BX
push CX
push SI
push DS
mov DS,AX ; get segment of trap
mov BX,rt_traps ; start at first trap
xor SI,SI ; used = FALSE
_loop ; loop for each context
mov CX,[BX+te_stack_trap]
test CX,CX
_quif e ; done when stack_trap == 0
mov BP,[BX+te_context]
mov BP,[BP+tl_saved_bp]
test BP,BP
_if e
mov BP,BPChain ; get BP of active task
_endif
cmp CX,BP ; if stack_trap >= BP
_if ae
mov BP,CX
mov [BP+4],DX ; set proper return segment
mov AX,[BX+te_ret_offset]; and offset
mov [BP+2],AX
inc SI ; used = TRUE
_endif
mov AX,[BX+te_ret_list]
_loop
cmp AX,CX ; are we done yet? i.e. BP == 0 or BP is
_quif b ; . . . below chain
mov BP,AX
inc byte ptr [BP] ; set the far bit
mov AX,[BP+4] ; get the link
mov [BP+4],DX ; store new_handle as segment of return
inc SI ; used = TRUE
_endloop
add BX,size TRAP_ENTRY
_endloop
mov AX,SI ; set return code
pop DS
pop SI
pop CX
pop BX
else
cmp AX,BPChain ; check if we can remove trap from stack
_if ae ; we can if the stack is below us
mov BP,AX ; get offset of stack_trap
mov [BP+4],CX ; new return seg
mov [BP+2],DX ; restore return offset
_endif
mov AX,BPChain
_loop
cmp BX,AX ; are we done yet? i.e., BX == 0 or BX is
_quif b ; . . . below chain
mov BP,BX ; get the next link
inc byte ptr [BP] ; set the far bit
mov BX,CX ; get the new_handle
xchg BX,[BP+4] ; store handle and get next link
_endloop
endif
pop BP
ret
__OVLUNDORETTRAP__ endp
;
; void near __OVLFIXCALLCHAIN__( unsigned old, unsigned new )
;
public "C",__OVLFIXCALLCHAIN__
__OVLFIXCALLCHAIN__ proc near
;
; Scan through the call chain and change any far rets that point to seg
; in AX to point to the seg in DX.
;
push BP
push CX
ifdef OVL_MULTITHREAD
mov BP,Context_list
_loop
push BP
mov BP,[BP+tl_saved_bp]
test BP,BP
jne fix_start ; used saved bp if not current task
mov BP,BPChain ; otherwise use BPChain
else
mov BP,BPChain ; get the BP on entry
endif
jmp short fix_start
_loop
shl CX,1 ; fix the BP.
_quif z ; done if BP zero
mov BP,CX ; restore BP
fix_start:
mov CX,[BP] ; get next BP
shr CX,1 ; test if odd
_loopif nc ; nc if BP was even (near rtn)
cmp AX,[BP+4] ; compare segment
_loopif ne ; continue loop if not right seg
mov [BP+4],DX ; set new value
_endloop
ifdef OVL_MULTITHREAD
pop BP ; restore context
mov BP,[BP+tl_next] ; get next context
test BP,BP
_until e ; until NULL
endif
pop CX
pop BP
ret
__OVLFIXCALLCHAIN__ endp
;
; int near __NCheckRetAddr__( ovl_addr far *data )
;
public "C",__NCheckRetAddr__
__NCheckRetAddr__ proc near
;
; This routine is for debugging support. It checks if the return address
; pointed to by data is a return trap.
;
push BX ; save registers
push DI ; . . .
push DS ; . . .
push ES ; . . .
_guess
mov DS,DX ; segment of data
mov BX,AX ; offset of data
xor DX,DX ; set up return code
cmp [BX],DX ; all ret traps have offset 0
_quif ne
mov AX,[BX+2] ; get seg of (possible) ret trap
call __WhichArea__ ; check if in an overlay area
_quif nc ; . . .
mov AX,[BX+2] ; get seg of ret trap
dec AX ; . . .
mov ES,AX ; . . .
mov DI,ES:[0eH] ; get overlay number
push CX ; save CX
mov CL,4 ; multiply by size OVLTAB_ENTRY
mov AX,DI ; save overlay number in ax
shl DI,CL ; . . . multiply
pop CX ; restore CX
test byte ptr [DI+__OVLTAB__.ov_entries.ove_flags_anc+1- size OVLTAB_ENTRY],10H
; check if FLAG_RET_TRAP set
_quif e ; . . .
inc DX ; this is a return trap
mov [BX+4],AX ; set the overlay number
ifdef OVL_MULTITHREAD
mov AX,10H + rt_traps; find the active context
_loop ; (assume return trap is in active stack)
mov DI,AX ; save pointer
mov DI,ES:[DI+te_context]
cmp word ptr SS:[DI+tl_saved_bp],0
_quif e
add AX,size TRAP_ENTRY
_endloop ; done when found active context
mov DI,AX
mov AX,ES:[DI+te_ret_offset]
else
mov AX,ES:[10H + rt_ret_offset]
endif
mov DI,ES:[10H + rt_old_code_handle]
mov [BX+2],DI ; give seg to debugger
mov [BX],AX ; give offset to debugger
_endguess
mov AX,DX ; get return code
pop ES ; restore registers
pop DS ; . . .
pop DI ; . . .
pop BX ; . . .
ret
__NCheckRetAddr__ endp
;
; void far __OVLRETTRAP__( void )
;
align 16
public "C",__OVLRETTRAP__
__OVLRETTRAP__ proc far
;
; This is the entry point that all return traps use.
;
mov SaveWord,AX ; save AX
pop AX ; pop offset of ret trap (not used)
pop AX ; pop segment of ret trap
pushf ; save flags
call do_ret_trap ; unload the trap & load the section
popf ; restore flags
mov AX,SaveWord ; restore AX
jmp dword ptr __OVLCAUSE__ ; return to overlay
__OVLRETTRAP__ endp
align 4
do_ret_trap proc near
;
; do a return trap. this expects the segment of the return trap in AX
;
mov BPChain,BP ; save call chain
push DX ; save registers
push CX ; . . .
push BX ; . . .
push DS ; . . .
dec AX ; get the overlay number and
mov DS,AX ; get return offset
ifdef OVL_MULTITHREAD
mov AX,10H + rt_traps
_loop
mov BX,AX
add AX,size TRAP_ENTRY ; (note that loop must end)
mov CX,[BX+te_ret_offset] ; get return offset
mov BX,[BX+te_context] ; get context
cmp word ptr SS:[BX+tl_saved_bp],0
_until e ; until active task found
mov BX,CX ; save return offset
else
mov BX,DS:[010H + rt_ret_offset]; save return offset
endif
mov AX,DS:[0EH] ; get the overlay number
mov CX,AX ; save overlay number
call __LoadNewOverlay__ ; load overlay
mov __OVLCAUSE__,BX ; save offset of return
mov __OVLCAUSE__+2,AX ; save segment of return
xchg CX,AX ; ovl num in AX, seg in CX
mov DL,1 ; overlay load cause by return
call __NDBG_HOOK__ ; tell debugger
pop DS ; restore registers
pop BX ; . . .
pop CX ; . . .
pop DX ; . . .
mov BP,BPChain ; . . .
ret
do_ret_trap endp
pcode_ret_trap proc far
;
; this is the return trap routine called by the pcode interpreter
; this expects the segment of the trap in AX, and returns the new segment in AX
;
call do_ret_trap ; do the return trap;
mov AX,__OVLCAUSE__+2 ; load the segment of section
retf
pcode_ret_trap endp
;
; void __NOVLLDR__( void )
;
align 16
public __NOVLLDR__
__NOVLLDR__ proc near
;
; Notice by the time we get here, the bp chain calling convention has
; been violated (two calls in a row). We must farkle the stack to
; restore the bp chain linkage.
;
mov SaveWord,AX ; save original AX
pop AX ; get vector ret addr from stack
sub AX,3 ; make point to beginning of vector
inc BP ; restore BP chain
push BP ; . . .
mov BP,SP ; . . .
mov BPChain,SP ; store BP for scanning later
push SaveWord ; save original AX on stack
mov SaveWord,AX ; save vector in SaveWord
push DX ; save original DX
mov DX,[BP+2] ; get original return offset
mov __OVLCAUSE__,DX ; stash it for the debugger
mov DX,[BP+4] ; get original return segment
mov __OVLCAUSE__+2,DX ; stash it for the debugger
mov DX,CS ; move CS to where the fn. can get it
call __WOVLLDR__ ; load overlay
pop DX ; restore registers
pop AX ; . . .
pop BP ; . . .
dec BP ; . . .
jmp word ptr SaveWord ; exit through vector
__NOVLLDR__ endp
longjmp_wrap proc far
ifdef OVL_MULTITHREAD
mov BPChain,BP
call __OVLLONGJMP__
else
push BX
mov BPChain,BP
mov BX,BP
call __OVLLONGJMP__
pop BX
endif
NullHook proc far
ret
NullHook endp
longjmp_wrap endp
_TEXT ends
end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?