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 + -
显示快捷键?