home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c100 / 3.ddi / TASK.ZIP / PRIM.ASM < prev    next >
Encoding:
Assembly Source File  |  1989-08-20  |  5.6 KB  |  212 lines

  1. COMMENT %
  2. PRIM.ASM  Copyright 1989 by Dlugosz Software
  3.  
  4. This is the assembly language primitives needed by the C++ multitasking
  5. system.  It is written for Zortech C++ large model, to assemble under
  6. MASM 5.1
  7.  
  8. %
  9.  
  10.    .MODEL LARGE
  11.  
  12. PUBLIC _from_scheduler,__DS, _tasker_install, _tasker_remove
  13. PUBLIC _preempt_off, _preempt_on, _task_yield
  14. ;for debugging...
  15. PUBLIC to_scheduler, new_timer_tick
  16.  
  17.          .DATA
  18. __DS dw SEG DGROUP
  19.  
  20.          .CODE
  21.  
  22. old_timer LABEL DWORD
  23. old_timer_ofs  dw ?
  24. old_timer_seg  dw ?
  25.  
  26. preempt_inhibit  dw 1  ;starts out inhibited
  27.  
  28. ;------------------------------------------------
  29. ;  void preempt_off();
  30. ;  void preempt_on();
  31. ;  these functions change the state of the preempt_inhibit flag.  They
  32. ;  are in here for two reasons:  1)you must change the state in an
  33. ;  uninterruptable cycle, and I don't want to trust the compiler to
  34. ;  do so.  2)Zortech cannot access a FAR variable, and this flag is not
  35. ;  in DGROUP.  It must be in the CSEG of the timer interrupt.
  36.  
  37. _preempt_off PROC FAR
  38.    inc CS:preempt_inhibit
  39.    ret
  40. _preempt_off ENDP
  41.  
  42. _preempt_on PROC FAR
  43.    dec CS:preempt_inhibit
  44.    ret
  45. _preempt_on ENDP
  46.  
  47.  
  48. ;------------------------------------------------
  49. ;  void* from_scheduler(unsigned state[]);
  50. ;  This is where the scheduler gives up control to another
  51. ;  task, and where another task returns to the scheduler.
  52.  
  53. stack_save_SP dw ?
  54. stack_save_SS dw ?
  55.  
  56. taskSS  dw ?
  57. taskSP  dw ?
  58.  
  59. _from_scheduler PROC FAR
  60.    push BP
  61.    mov BP,SP
  62.    ;The only thing restored when control is transferd back is the CS:IP
  63.    ;which is obveously required since that tells where code is executing.
  64.    ;It can restore the SS:SP from code segment variables, and than restore
  65.    ;other registers.
  66.  
  67.    ;Zortech manual, page 233:  Functions must preserve SI,DI,BP,SP,SS,CS,DS.
  68.    ;functions can alter AX,BX,CX,DX,ES.  Direction flag must be set to
  69.    ;forward.  I reset the D flag in case the interrupted function was in the
  70.    ;middle of a string operation.  Preserving SI and DI is pretty standard,
  71.    ;but ES varies on the compiler.  You might add it to the list if the
  72.    ;compiler used on the C++ end of the scheduler needs it, and you can
  73.    ;likewise remove SI & DI if the C++ end will not need them.
  74.    push SI
  75.    push DI
  76.    push DS
  77.    ;after all pushes are done, store stack pointer somewhere safe.
  78.    mov CS:stack_save_SS,SS
  79.    mov CS:stack_save_SP,SP
  80.    ;I am now done saving the required state of the scheduler.  I can now
  81.    ;resume the state of the interrupted task.
  82.    lds BX,[BP+6]  ;should be SS:SP
  83.    mov AX,DS
  84.    mov SS,AX     ;SS and SP
  85.    mov SP,BX     ;must be loaded consecutivly
  86.    pop AX
  87.    pop BX
  88.    pop CX
  89.    pop DX
  90.    pop SI
  91.    pop DI
  92.    pop BP
  93.    pop ES
  94.    pop DS
  95.    dec CS:preempt_inhibit
  96.    iret  ;pops Flags,IP,CS
  97. _from_scheduler ENDP
  98.    ; This is a function sawed in half
  99. to_scheduler PROC FAR
  100. ;this restores the stack and returns to the scheduler.
  101. ;an interrupt jumps to this point.
  102.    mov SS, CS:stack_save_SS
  103.    mov SP, CS:stack_save_SP ;SS and SP must be loaded consecutively
  104.    pop DS
  105.    pop DI
  106.    pop SI
  107.    pop BP
  108.    cld
  109.    mov DX,CS:taskSS
  110.    mov AX,CS:taskSP
  111.    ret
  112. to_scheduler ENDP
  113.  
  114. ;------------------------------------------------
  115. ; void task_yield()
  116. ; give up control to the scheduler
  117.  
  118. _task_yield PROC FAR
  119.   inc CS:preempt_inhibit
  120.   ;CS,IP,and already on stack.  I don't need to save the general purpose
  121.   ; registers, and I don't need to save the flags but I need to get the
  122.   ; proper stack setup for returning.  I need to insert the flags over
  123.   ; the return address.
  124.   pop AX
  125.   pop BX
  126.   pushf  ;the conditional flags don't matter, but the system flags
  127.          ; need to be correct.
  128.   push BX
  129.   push AX
  130.   ; now save the other regs
  131.   push DS
  132.   push ES ;don't really need to save this one, but no shortcut
  133.   push BP
  134.   push DI
  135.   push SI
  136.   ;don't need to save AX,BX,CX,DX
  137.   sub SP,8 ;leave room on the stack for them
  138.   mov CS:taskSS,SS
  139.   mov CS:taskSP,SP
  140.   jmp to_scheduler
  141. _task_yield ENDP
  142.  
  143.  
  144.  
  145. ;------------------------------------------------
  146. ; new timer interrupt
  147. ; this saves the state, and then alters the return address so that
  148. ; the interrupt will return to the scheduler.  Then the normal service
  149. ; routine is jumped to.
  150.  
  151. new_timer_tick PROC FAR  ;actually, its an INTERRUPT
  152.   cmp CS:preempt_inhibit,0
  153.   jne skip_switch   ;don't do any of this
  154.   inc CS:preempt_inhibit
  155.   ;CS,IP,and Fl already on stack.
  156.   push DS
  157.   push ES
  158.   push BP
  159.   push DI
  160.   push SI
  161.   push DX
  162.   push CX
  163.   push BX
  164.   push AX
  165.   mov CS:taskSS,SS
  166.   mov CS:taskSP,SP
  167.   ; now put the new return address on the stack
  168.   mov AX, 246h
  169.   push AX  ;flags upon returning to switcher
  170.   push CS  ;same segment as me
  171.   mov AX, OFFSET CS:to_scheduler
  172.   push AX
  173.   ;operation complete.  Do the real timer stuff.
  174. skip_switch:
  175.   jmp old_timer
  176. new_timer_tick ENDP
  177.  
  178.  
  179. ;------------------------------------------------
  180. ;  void tasker_install();
  181. ;  install switcher as front end to timer tick
  182. _tasker_install PROC FAR
  183.    push DS
  184.    mov AX,3508h
  185.    int 21h  ;old timer int in ES:BX
  186.    mov old_timer_seg, ES
  187.    mov old_timer_ofs, BX
  188.    mov AX, SEG new_timer_tick
  189.    mov DS,AX
  190.    mov DX, OFFSET new_timer_tick
  191.    mov AX,2508h
  192.    int 21h  ;new timer in place.  We're off!
  193.    pop DS
  194.    ret
  195. _tasker_install ENDP
  196.  
  197. ;------------------------------------------------
  198. ;  void tasker_remove();
  199. ;  restore the timer to its normal state
  200. _tasker_remove PROC FAR
  201.    push DS
  202.    mov AX,2508h
  203.    lds DX, old_timer
  204.    int 21h
  205.    pop DS
  206.    ;return task's stack value
  207.    ret
  208. _tasker_remove ENDP
  209.  
  210.  
  211.    END
  212.