home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / DOOG / CTASK.ZIP / TSKSTCK.ASM < prev    next >
Assembly Source File  |  1989-12-20  |  6KB  |  262 lines

  1. ;
  2. ;    --- Version 2.0 89-12-13 17:15 ---
  3. ;
  4. ;    CTask - Local Stack Switch handler module.
  5. ;
  6. ;    Public Domain Software written by
  7. ;        Thomas Wagner
  8. ;        Patschkauer Weg 31
  9. ;        D-1000 Berlin 33
  10. ;        West Germany
  11. ;
  12. ;    This file is new with version 1.2.
  13. ;
  14. ;    In this version, all Hard- and Software INT handlers switch
  15. ;    to a local stack (INT 16 for AH=0 only). Stack overruns have
  16. ;    been observed, especially in conjunction with VDISK and the
  17. ;    Microsoft Editor. Some Microsoft products (and some other TSR's)
  18. ;    link into interrupts without switching to local stacks. This
  19. ;    can lead to situations where just a few words are available
  20. ;    for use by the CTask handlers. In the abovementioned combination,
  21. ;    a keyboard interrupt occurring while VDISK is active leaves
  22. ;    four (!) words of stack space for INT 16 execution.
  23. ;    Since most of the interrupts should be reentrant, a number
  24. ;    of stacks are maintained (constant NUM_STACKS), and the call 
  25. ;    is passed without a stack switch if all local stacks are in use. 
  26. ;
  27. ;    To avoid duplication of the stack switch and register save code 
  28. ;    in all handlers, a global stack switcher is implemented here. 
  29. ;    It pushes the address of a back-switch routine on the new stack, 
  30. ;    so the calling routine doesn't have to care about explicitly
  31. ;    calling the restore routine.
  32. ;
  33. ;    No registers may be pushed prior to the call to switch_stack if
  34. ;    the auto-switchback is to be used, since switch_stack assumes
  35. ;    the old stack to contain the caller's flags at offset 8.
  36. ;
  37. ;    When old_stack is called to explicitly switch back, stack 
  38. ;    contents prior to the call to switch_stack are insignificant.
  39. ;
  40. ;    Switch_stack will set up registers as follows:
  41. ;        BP = base of register save area on stack
  42. ;        DS,ES = DGROUP
  43. ;        Direction flag clear
  44. ;        Interrupts enabled
  45. ;    All other registers are unchanged.
  46. ;
  47. ;    Since the switch_stack routine pushes the caller's flags on
  48. ;    the stack, the original flags will be restored if an IRET is used
  49. ;    to enter the auto-backswitch. For RET 2, the flags on entry
  50. ;    to the backswitch-routine will be preserved.
  51. ;    To allow preservation of the flag state on entry to switch_stack,
  52. ;    the flags are pushed on the save area, but not automatically
  53. ;    restored. Copy the entry_flags into caller_flags to restore
  54. ;    the entry flags on return.
  55. ;
  56. ;    old_stack will not restore flags from the stack, it will preserve
  57. ;    the flag state.
  58. ;
  59.     .model    large,c
  60. ;
  61.     include    tsk.mac
  62. ;
  63.     public    tsk_switch_stack
  64.     public    tsk_old_stack
  65. ;
  66.     extrn    tsk_dgroup: word
  67. ;
  68. STACKSIZE    =    256    ; local stack size (bytes)
  69. NUM_STACKS    =    8    ; Number of local stacks
  70. ;
  71.     .tsk_data
  72. ;
  73. lstacks    label    word        ; Stacks for INT 16
  74.     db    NUM_STACKS * STACKSIZE dup (?)
  75. ;
  76.     .tsk_edata
  77.     .tsk_code
  78. ;
  79. ;
  80. stack_full    dw    0    ; count all stacks in use events
  81. ;
  82. r_ss        dw    ?
  83. r_sp        dw    ?
  84. r_bx        dw    ?
  85. r_cx        dw    ?
  86. r_bp        dw    ?
  87. call_ip        dw    ?
  88. call_cs        dw    ?
  89. retaoff        dw    ?
  90. retaseg        dw    ?
  91. sflags        dw    ?
  92. ;
  93. ;    Caution: Since a zero slot offset is used to detect
  94. ;    that no stack was allocated, the "stacks" array may not
  95. ;    be located at offset 0 in the code segment.
  96. ;
  97. stacks    label    word
  98. xst    =    offset lstacks + STACKSIZE
  99.     rept    NUM_STACKS
  100.     dw    xst
  101. xst    =    xst + STACKSIZE
  102.     endm
  103. ;
  104. ;
  105. tsk_switch_stack    proc    near
  106. ;
  107.     pushf
  108.     cli
  109.     pop    cs:sflags
  110.     pop    cs:retaoff        ; return address
  111.     mov    cs:r_bx,bx        ; save bx & cx in CS
  112.     mov    cs:r_cx,cx
  113.     mov    cs:r_bp,bp        ; save BP
  114.     mov    bp,sp
  115.     mov    bx,[bp]            ; get caller's IP
  116.     mov    cs:call_ip,bx
  117.     mov    bx,2[bp]        ; get caller's CS
  118.     mov    cs:call_cs,bx
  119.     mov    bp,4[bp]        ; get caller's flags into BP
  120. ;
  121.     mov    cx,NUM_STACKS        ; total number of stacks
  122.     mov    bx,offset stacks    ; stack table
  123. stlp:
  124.     cmp    word ptr cs:[bx],0    ; in use ?
  125.     jne    st_found        ; jump if free
  126.     inc    bx
  127.     inc    bx
  128.     loop    stlp
  129. ;
  130. ;    No unused stack, continue on caller's stack
  131. ;
  132.     inc    cs:stack_full
  133.     xor    bx,bx
  134.     jmp    short st_old
  135. ;
  136. ;    Stack found, perform switch
  137. ;
  138. st_found:
  139.     mov    cs:r_ss,ss        ; save SS/SP
  140.     mov    cs:r_sp,sp
  141.     mov    ss,cs:tsk_dgroup    ; load new SS/SP
  142.     mov    sp,cs:[bx]
  143.     mov    cx,sp            ; save new SP value
  144.     mov    word ptr cs:[bx],0    ; mark stack in use
  145.     push    cs:r_ss            ; push old SS/SP
  146.     push    cs:r_sp
  147. st_old:
  148.     push    cs:r_bx
  149.     push    cs:r_cx
  150.     push    bx            ; push stack slot index
  151.     push    cx            ; push new SP
  152. ;
  153.     push    ax            ; push remaining regs
  154.     push    dx
  155.     push    si
  156.     push    di
  157.     push    cs:r_bp
  158.     push    ds
  159.     push    es
  160. ;
  161.     push    cs:sflags        ; push entry flags
  162.     push    cs:call_cs        ; push caller's CS
  163.     push    cs:call_ip        ; push caller's IP
  164. ;
  165.     push    bp            ; push caller's flags
  166.     push    cs            ; and special return
  167.     mov    cx,offset stsw_retn
  168.     push    cx
  169.     mov    bx,cs:r_bx        ; restore regs bx,cx
  170.     mov    cx,cs:r_cx
  171.     mov    bp,sp            ; set BP to stack bottom
  172.     push    cs:retaoff        ; push retaddr on new stack
  173.     cld
  174.     sti
  175.     mov    ds,cs:tsk_dgroup
  176.     mov    es,cs:tsk_dgroup
  177.     ret                ; restore flags & return
  178. ;
  179. tsk_switch_stack    endp
  180. ;
  181. ;
  182. tsk_old_stack    proc    near
  183. ;
  184.     pushf                ; save flags
  185.     cli
  186.     pop    cs:sflags
  187.     pop    cs:retaoff        ; return address
  188.     add    sp,12            ; discard dummy return & flags
  189. ;
  190.     pop    es            ; restore regs
  191.     pop    ds
  192.     pop    bp
  193.     pop    di
  194.     pop    si
  195.     pop    dx
  196.     pop    ax
  197. ;
  198.     pop    cx            ; new SP
  199.     pop    bx            ; stack slot index
  200.     or    bx,bx            ; no new stack?
  201.     jnz    old_sw
  202.     pop    cx
  203.     pop    bx
  204.     jmp    short old_ret
  205. old_sw:
  206.     mov    cs:[bx],cx        ; reset stack slot
  207.     pop    cx
  208.     pop    bx
  209.     pop    cs:r_sp
  210.     pop    ss               ; old SS
  211.     mov    sp,cs:r_sp
  212. old_ret:
  213.     push    cs:retaoff        ; push retaddr on old stack
  214.     push    cs:sflags
  215.     popf                ; restore flags
  216.     ret                ; and return
  217. ;
  218. tsk_old_stack    endp
  219. ;
  220. ; stsw_retn is where the call returns to when there is no explicit
  221. ; call to old_stack.
  222. ;
  223. stsw_retn    proc    far
  224. ;
  225.     pushf                ; save flags
  226.     cli
  227.     pop    cs:sflags        ; in CS
  228. ;
  229.     add    sp,6            ; discard caller CS/IP & entry flags
  230. ;
  231.     pop    es            ; restore regs
  232.     pop    ds
  233.     pop    bp
  234.     pop    di
  235.     pop    si
  236.     pop    dx
  237.     pop    ax
  238. ;
  239.     pop    cx            ; new SP
  240.     pop    bx            ; stack slot index
  241.     or    bx,bx            ; no new stack?
  242.     jnz    retn_sw
  243.     pop    cx
  244.     pop    bx
  245.     jmp    short retn_ret
  246. retn_sw:
  247.     mov    cs:[bx],cx        ; reset stack slot
  248.     pop    cx
  249.     pop    bx
  250.     pop    cs:r_sp
  251.     pop    ss               ; old SS
  252.     mov    sp,cs:r_sp
  253. retn_ret:
  254.     push    cs:sflags        ; push flags on old stack
  255.     popf                ; restore flags
  256.     ret    2            ; and return
  257. ;
  258. stsw_retn    endp
  259. ;
  260.     end
  261.  
  262.