Category : C Source Code
Archive   : CTSK22.ZIP
Filename : TSKSTCK.ASM

 
Output of file : TSKSTCK.ASM contained in archive : CTSK22.ZIP
;
; --- Version 2.2 90-10-12 15:33 ---
;
; CTask - Local Stack Switch handler module.
;
; Public Domain Software written by
; Thomas Wagner
; Ferrari electronic Gmbh
; Beusselstrasse 27
; D-1000 Berlin 21
; 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 callers flags at offset 4.
;
; 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.
;
; 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.
;
; Version 2.1 slightly changes the handling of flag restoration
; on auto-backswitch. The old algorithm restored the caller flags
; on entry to the backswitch routine, which caused problems with
; debuggers if the interrupted code was being single-stepped.
; Now the original flags always will be restored on exit of the
; back-switch, regardless of the return used (IRET or RET 2).
; To modify the flags returned, you have to explicitly modify
; the caller_flags field in the saved register area.
;
name tskstck
;
include tsk.mac
include tskdeb.h
;
.tsk_model
;
Pubfunc tsk_switch_stack
Pubfunc tsk_old_stack
;
IF DEBUG AND DEB_FLASHERS
Locext tsk_inccdis
extrn tsk_debflash: word
extrn tsk_dtposn: dword
ENDIF
;
;
STACKSIZE = 256 ; local stack size (bytes)
NUM_STACKS = 8 ; Number of local stacks
;
IF FAR_STACKS
ctask_stacks segment word public 'CTASK_STACKS'
ELSE
.tsk_data
ENDIF
;
lstacks label word
db NUM_STACKS * STACKSIZE dup (?)
;
IF FAR_STACKS
ctask_stacks ends
.tsk_data
ENDIF
;
IF NOT ROM_CODE
;
.tsk_edata
.tsk_code
;
sseg equ
ENDIF
;
stack_full dw 0 ; count 'all stacks in use' events
IF DEBUG AND DEB_FLASHERS
usecnt db 0
ENDIF
EVEN
;
;
IF ROM_CODE
r_ds dw ?
ENDIF
r_ss dw ?
r_sp dw ?
r_bx dw ?
r_cx dw ?
r_bp dw ?
call_ip dw ?
call_cs dw ?
retaoff dw ?
IF LOCALS_FAR
retaseg dw ?
ENDIF
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 segment.
;
stacks label word
xst = offset lstacks + STACKSIZE
rept NUM_STACKS
dw xst
xst = xst + STACKSIZE
endm
;
IF ROM_CODE
;
.tsk_edata
.tsk_code
;
sseg equ
ENDIF
;
tsk_dgroup dw @CTASK_DATA
;
IF FAR_STACKS
stackseg dw SEG ctask_stacks
ELSE
stackseg equ
ENDIF
;
;
Localfunc tsk_switch_stack
;
IF ROM_CODE
push ds
mov ds,cs:tsk_dgroup
pop r_ds
ENDIF
pushf
cli
pop sseg:sflags
pop sseg:retaoff ; return address
IF LOCALS_FAR
pop sseg:retaseg
ENDIF
mov sseg:r_bx,bx ; save bx & cx in CS
mov sseg:r_cx,cx
mov sseg:r_bp,bp ; save BP
mov bp,sp
mov bx,[bp] ; get caller's IP
mov sseg:call_ip,bx
mov bx,2[bp] ; get caller's CS
mov sseg: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 sseg:[bx],0 ; in use ?
jne st_found ; jump if free
inc bx
inc bx
loop stlp
;
; No unused stack, continue on caller's stack
;
IF DEBUG AND DEB_FLASHERS
push ds
mov ds,cs:tsk_dgroup
cmp tsk_debflash,0
je debdd0
push ax
mov ax,DEBP_CNTSTOFL
call tsk_inccdis
pop ax
debdd0:
pop ds
ENDIF
inc sseg:stack_full
xor bx,bx
jmp short st_old
;
; Stack found, perform switch
;
st_found:
mov sseg:r_ss,ss ; save SS/SP
mov sseg:r_sp,sp
mov ss,cs:stackseg ; load new SS/SP
mov sp,sseg:[bx]
mov cx,sp ; save new SP value
mov word ptr sseg:[bx],0 ; mark stack in use
push sseg:r_ss ; push old SS/SP
push sseg:r_sp
st_old:
push sseg:r_bx
push sseg: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 sseg:r_bp
IF ROM_CODE
push r_ds
ELSE
push ds
ENDIF
push es
;
push bp ; push caller's flags
push sseg:call_cs ; push caller's CS
push sseg:call_ip ; push caller's IP
;
push sseg:sflags ; push entry flags
push cs ; and special return
mov cx,offset @stsw_retn
push cx
mov bx,sseg:r_bx ; restore regs bx,cx
mov cx,sseg:r_cx
mov bp,sp ; set BP to stack bottom
IF LOCALS_FAR
push sseg:retaseg
ENDIF
push sseg:retaoff ; push retaddr on new stack
cld
sti
mov ds,cs:tsk_dgroup
mov es,cs:tsk_dgroup
IF DEBUG AND DEB_FLASHERS
cmp slot_idx[bp],0
je debdd1
cmp tsk_debflash,0
je debdd1
inc sseg:usecnt
push ax
push ds
push si
mov al,sseg:usecnt
add al,'0'
lds si,tsk_dtposn
mov DEBP_STACKNUM[si],al
pop si
pop ds
pop ax
debdd1:
ENDIF
ret ; restore flags & return
;
tsk_switch_stack endp
;
;
Localfunc tsk_old_stack
;
pushf ; save flags
cli
IF ROM_CODE
mov ds,cs:tsk_dgroup
ENDIF
pop sseg:sflags
pop sseg:retaoff ; return address
IF LOCALS_FAR
pop sseg:retaseg
ENDIF
add sp,12 ; discard dummy return & flags
;
IF DEBUG AND DEB_FLASHERS
mov ds,cs:tsk_dgroup
cmp slot_idx[bp],0
je debdd2
cmp tsk_debflash,0
je debdd2
dec sseg:usecnt
mov al,sseg:usecnt
add al,'0'
lds si,tsk_dtposn
mov DEBP_STACKNUM[si],al
IF ROM_CODE
mov ds,cs:tsk_dgroup
ENDIF
debdd2:
ENDIF
;
pop es ; restore regs
IF ROM_CODE
pop r_ds
ELSE
pop ds
ENDIF
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 sseg:[bx],cx ; reset stack slot
pop cx
pop bx
pop sseg:r_sp
pop ss ; old SS
mov sp,sseg:r_sp
old_ret:
IF LOCALS_FAR
push sseg:retaseg
ENDIF
push sseg:retaoff ; push retaddr on old stack
push sseg:sflags
IF ROM_CODE
mov ds,r_ds
ENDIF
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
;
cli
add sp,4 ; discard caller CS/IP
IF ROM_CODE
mov ds,cs:tsk_dgroup
ENDIF
pop sseg:sflags ; store caller's flags in CS
;
IF DEBUG AND DEB_FLASHERS
mov ds,cs:tsk_dgroup
cmp slot_idx[bp],0
je debdd3
cmp tsk_debflash,0
je debdd3
dec sseg:usecnt
mov al,sseg:usecnt
add al,'0'
lds si,tsk_dtposn
mov DEBP_STACKNUM[si],al
IF ROM_CODE
mov ds,cs:tsk_dgroup
ENDIF
debdd3:
ENDIF
;
pop es ; restore regs
IF ROM_CODE
pop r_ds
ELSE
pop ds
ENDIF
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 sseg:[bx],cx ; reset stack slot
pop cx
pop bx
pop sseg:r_sp
pop ss ; old SS
mov sp,sseg:r_sp
retn_ret:
push bp
mov bp,sp
push ax
mov ax,sseg:sflags ; push flags on old stack
mov 6[bp],ax
pop ax
pop bp
IF ROM_CODE
mov ds,r_ds
ENDIF
iret
;
@stsw_retn endp
;
.tsk_ecode
end



  3 Responses to “Category : C Source Code
Archive   : CTSK22.ZIP
Filename : TSKSTCK.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/