home *** CD-ROM | disk | FTP | other *** search
- ;
- ; --- Version 2.0 89-12-13 17:15 ---
- ;
- ; CTask - Local Stack Switch handler module.
- ;
- ; Public Domain Software written by
- ; Thomas Wagner
- ; Patschkauer Weg 31
- ; D-1000 Berlin 33
- ; West Germany
- ;
- ; This file is new with version 1.2.
- ;
- ; In this version, all Hard- and Software INT handlers switch
- ; to a local stack (INT 16 for AH=0 only). Stack overruns have
- ; been observed, especially in conjunction with VDISK and the
- ; Microsoft Editor. Some Microsoft products (and some other TSR's)
- ; link into interrupts without switching to local stacks. This
- ; can lead to situations where just a few words are available
- ; for use by the CTask handlers. In the abovementioned combination,
- ; a keyboard interrupt occurring while VDISK is active leaves
- ; four (!) words of stack space for INT 16 execution.
- ; Since most of the interrupts should be reentrant, a number
- ; of stacks are maintained (constant NUM_STACKS), and the call
- ; is passed without a stack switch if all local stacks are in use.
- ;
- ; To avoid duplication of the stack switch and register save code
- ; in all handlers, a global stack switcher is implemented here.
- ; It pushes the address of a back-switch routine on the new stack,
- ; so the calling routine doesn't have to care about explicitly
- ; calling the restore routine.
- ;
- ; No registers may be pushed prior to the call to switch_stack if
- ; the auto-switchback is to be used, since switch_stack assumes
- ; the old stack to contain the caller's flags at offset 8.
- ;
- ; When old_stack is called to explicitly switch back, stack
- ; contents prior to the call to switch_stack are insignificant.
- ;
- ; Switch_stack will set up registers as follows:
- ; BP = base of register save area on stack
- ; DS,ES = DGROUP
- ; Direction flag clear
- ; Interrupts enabled
- ; All other registers are unchanged.
- ;
- ; Since the switch_stack routine pushes the caller's flags on
- ; the stack, the original flags will be restored if an IRET is used
- ; to enter the auto-backswitch. For RET 2, the flags on entry
- ; to the backswitch-routine will be preserved.
- ; To allow preservation of the flag state on entry to switch_stack,
- ; the flags are pushed on the save area, but not automatically
- ; restored. Copy the entry_flags into caller_flags to restore
- ; the entry flags on return.
- ;
- ; old_stack will not restore flags from the stack, it will preserve
- ; the flag state.
- ;
- .model large,c
- ;
- include tsk.mac
- ;
- public tsk_switch_stack
- public tsk_old_stack
- ;
- extrn tsk_dgroup: word
- ;
- STACKSIZE = 256 ; local stack size (bytes)
- NUM_STACKS = 8 ; Number of local stacks
- ;
- .tsk_data
- ;
- lstacks label word ; Stacks for INT 16
- db NUM_STACKS * STACKSIZE dup (?)
- ;
- .tsk_edata
- .tsk_code
- ;
- ;
- stack_full dw 0 ; count all stacks in use events
- ;
- r_ss dw ?
- r_sp dw ?
- r_bx dw ?
- r_cx dw ?
- r_bp dw ?
- call_ip dw ?
- call_cs dw ?
- retaoff dw ?
- retaseg dw ?
- sflags dw ?
- ;
- ; Caution: Since a zero slot offset is used to detect
- ; that no stack was allocated, the "stacks" array may not
- ; be located at offset 0 in the code segment.
- ;
- stacks label word
- xst = offset lstacks + STACKSIZE
- rept NUM_STACKS
- dw xst
- xst = xst + STACKSIZE
- endm
- ;
- ;
- tsk_switch_stack proc near
- ;
- pushf
- cli
- pop cs:sflags
- pop cs:retaoff ; return address
- mov cs:r_bx,bx ; save bx & cx in CS
- mov cs:r_cx,cx
- mov cs:r_bp,bp ; save BP
- mov bp,sp
- mov bx,[bp] ; get caller's IP
- mov cs:call_ip,bx
- mov bx,2[bp] ; get caller's CS
- mov cs:call_cs,bx
- mov bp,4[bp] ; get caller's flags into BP
- ;
- mov cx,NUM_STACKS ; total number of stacks
- mov bx,offset stacks ; stack table
- stlp:
- cmp word ptr cs:[bx],0 ; in use ?
- jne st_found ; jump if free
- inc bx
- inc bx
- loop stlp
- ;
- ; No unused stack, continue on caller's stack
- ;
- inc cs:stack_full
- xor bx,bx
- jmp short st_old
- ;
- ; Stack found, perform switch
- ;
- st_found:
- mov cs:r_ss,ss ; save SS/SP
- mov cs:r_sp,sp
- mov ss,cs:tsk_dgroup ; load new SS/SP
- mov sp,cs:[bx]
- mov cx,sp ; save new SP value
- mov word ptr cs:[bx],0 ; mark stack in use
- push cs:r_ss ; push old SS/SP
- push cs:r_sp
- st_old:
- push cs:r_bx
- push cs:r_cx
- push bx ; push stack slot index
- push cx ; push new SP
- ;
- push ax ; push remaining regs
- push dx
- push si
- push di
- push cs:r_bp
- push ds
- push es
- ;
- push cs:sflags ; push entry flags
- push cs:call_cs ; push caller's CS
- push cs:call_ip ; push caller's IP
- ;
- push bp ; push caller's flags
- push cs ; and special return
- mov cx,offset stsw_retn
- push cx
- mov bx,cs:r_bx ; restore regs bx,cx
- mov cx,cs:r_cx
- mov bp,sp ; set BP to stack bottom
- push cs:retaoff ; push retaddr on new stack
- cld
- sti
- mov ds,cs:tsk_dgroup
- mov es,cs:tsk_dgroup
- ret ; restore flags & return
- ;
- tsk_switch_stack endp
- ;
- ;
- tsk_old_stack proc near
- ;
- pushf ; save flags
- cli
- pop cs:sflags
- pop cs:retaoff ; return address
- add sp,12 ; discard dummy return & flags
- ;
- pop es ; restore regs
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop ax
- ;
- pop cx ; new SP
- pop bx ; stack slot index
- or bx,bx ; no new stack?
- jnz old_sw
- pop cx
- pop bx
- jmp short old_ret
- old_sw:
- mov cs:[bx],cx ; reset stack slot
- pop cx
- pop bx
- pop cs:r_sp
- pop ss ; old SS
- mov sp,cs:r_sp
- old_ret:
- push cs:retaoff ; push retaddr on old stack
- push cs:sflags
- popf ; restore flags
- ret ; and return
- ;
- tsk_old_stack endp
- ;
- ; stsw_retn is where the call returns to when there is no explicit
- ; call to old_stack.
- ;
- stsw_retn proc far
- ;
- pushf ; save flags
- cli
- pop cs:sflags ; in CS
- ;
- add sp,6 ; discard caller CS/IP & entry flags
- ;
- pop es ; restore regs
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop ax
- ;
- pop cx ; new SP
- pop bx ; stack slot index
- or bx,bx ; no new stack?
- jnz retn_sw
- pop cx
- pop bx
- jmp short retn_ret
- retn_sw:
- mov cs:[bx],cx ; reset stack slot
- pop cx
- pop bx
- pop cs:r_sp
- pop ss ; old SS
- mov sp,cs:r_sp
- retn_ret:
- push cs:sflags ; push flags on old stack
- popf ; restore flags
- ret 2 ; and return
- ;
- stsw_retn endp
- ;
- end
-
-