home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c070 / 4.ddi / TOOLS.4 / TCTSRC1.EXE / ISCALL.ASM < prev    next >
Encoding:
Assembly Source File  |  1989-03-31  |  5.2 KB  |  207 lines

  1.     page 60,126
  2. ;
  3. ; Name        iscall -- Simulate software-interrupt-style call to
  4. ;              interrupt service routine.
  5. ;
  6. ; Synopsis    ercode = iscall(pisr,preg);
  7. ;
  8. ;        int    ercode      Error code:  0 if okay;
  9. ;                  1 if pisr is invalid.
  10. ;        void far *pisr      Far pointer to interrupt service
  11. ;                  routine
  12. ;        ALLREG *preg      Standard registers
  13. ;
  14. ; Description    This function invokes the interrupt service routine
  15. ;        whose address is pisr and returns the results in the
  16. ;        most general fashion.  All values specified in *preg are
  17. ;        passed to the interrupt service routine in the
  18. ;        corresponding registers except for CS, IP, SS, and SP.
  19. ;        All the resulting register contents are returned in
  20. ;        *preg (again, except for CS, IP, SS, and SP).
  21. ;
  22. ;        The interrupt state (that is, whether interrupts are
  23. ;        enabled or disabled) is preserved.
  24. ;
  25. ; Returns    ercode          Error code:  0 if okay, 1 if pisr
  26. ;                  vector is invalid.
  27. ;        *preg          The values of the registers may be
  28. ;                  altered by the interrupt handler.
  29. ;
  30. ; Version    6.00  (C)Copyright Blaise Computing Inc. 1986,1987,1989
  31. ;
  32.  
  33.      include beginasm.mac
  34.  
  35.      beginProg iscall
  36.  
  37. ERR_BADVEC  equ     1            ; Error code indicating invalid
  38.                     ; interrupt vector.
  39.  
  40. pisr     equ    dword ptr [bp + stkoff]
  41.  
  42.      if    LONGDATA
  43. preg     equ    dword ptr [bp + stkoff + 4]
  44.      else
  45. preg     equ    word ptr [bp + stkoff + 4]
  46.      endif
  47.  
  48. ALLREG     struc                ; ALLREG structure
  49. reg_ax     dw    ?            ; (This must match declaration in
  50. reg_bx     dw    ?            ; BUTIL.H).
  51. reg_cx     dw    ?
  52. reg_dx     dw    ?
  53. reg_si     dw    ?
  54. reg_di     dw    ?
  55. reg_ds     dw    ?
  56. reg_es     dw    ?
  57. reg_ss     dw    ?
  58. reg_cs     dw    ?
  59. reg_flags dw    ?
  60. reg_bp     dw    ?
  61. reg_sp     dw    ?
  62. reg_ip     dw    ?
  63. ALLREG     ends
  64.  
  65.  
  66.      push    bp
  67.      mov    bp,sp
  68.  
  69.      push    si            ; Save registers that are important
  70.      push    di            ; to the C environment.
  71.      push    ds
  72.      push    es
  73.                     ; Obtain interrupt vector
  74.      les    si,pisr
  75.      assume es:nothing        ; Now ES:SI is address of interrupt
  76.                     ; handler.
  77.      mov    ax,es            ; Quit if pisr is 0:0.
  78.      or    ax,si
  79.      jnz    ok_vector
  80.  
  81. bad_vector:
  82.      mov    ax,ERR_BADVEC
  83.      jmp    short exit
  84.  
  85. ok_vector:
  86.                     ; Obtain contents of preg.
  87.      if    LONGDATA
  88.      lds    bx,preg
  89.      assume ds:nothing
  90.      else
  91.      mov    bx,preg
  92.      endif
  93.                     ; Now DS:BX points to *preg
  94.                     ; (ALLREG structure is at DS:BX).
  95.  
  96.                     ; Begin setting up for the call:
  97.  
  98.      push    ds            ; Step 1:  Save stack frame pointer
  99.      push    bp            ; so we can restore it in Step 10.
  100.  
  101.      pushf                ; Step 2:  Save our own flags
  102.                     ; for restoration in Step 9.
  103.  
  104.                     ; Step 3:  Push the stack items that
  105.                     ; the ISR will see:  a copy of its
  106.                     ; flags and its return address
  107.                     ; (CS:ret_addr).
  108.  
  109.      mov    ax,[bx.reg_flags]   ; Push the flags
  110.      push    ax            ;    without clearing IF and TF.
  111.      push    cs            ; Push CS.
  112.      mov    cx,offset ret_addr
  113.      push    cx            ; Push ret_addr.
  114.  
  115.                     ; Step 4:
  116.                     ; We will enter the handler by doing
  117.                     ; an IRET, so push the flags and the
  118.                     ; vector.
  119.  
  120.      and    ah,0fch         ; Push the flags
  121.      push    ax            ;    with IF and TF cleared.
  122.      push    es            ; Push the vector.
  123.      push    si
  124.  
  125.      mov    ax,[bx.reg_ax]        ; Step 5:  Load the easy registers.
  126.      mov    cx,[bx.reg_cx]
  127.      mov    dx,[bx.reg_dx]
  128.      mov    si,[bx.reg_si]
  129.      mov    di,[bx.reg_di]
  130.      mov    es,[bx.reg_es]
  131.      assume es:nothing
  132.      mov    bp,[bx.reg_bp]
  133.  
  134.      push    [bx.reg_bx]        ; Step 6:  Load DS and BX
  135.      mov    ds,[bx.reg_ds]        ; by temporarily using the stack.
  136.      assume ds:nothing
  137.      pop    bx
  138.  
  139.      iret                ; Step 7:  Load the flags and jump
  140.                     ; to the handler.  (This IRET uses &
  141.                     ; removes what was pushed in Step 4.)
  142.  
  143. ret_addr:
  144.      assume es:nothing,ds:nothing
  145.                     ; The interrupt handler brought us here
  146.                     ; by performing an IRET, thus popping
  147.                     ; what was pushed in Step 3.
  148.                     ; (However, the interrupt handler
  149.                     ; may choose to modify the flags
  150.                     ; before popping them.)
  151.  
  152.      push    bp            ; Step 8:  Temporarily preserve
  153.      push    ds            ; returned values of BP, DS, BX,
  154.      push    bx            ; and flags.
  155.      pushf
  156.  
  157.      mov    bp,sp            ; Step 9:  Restore our own flags
  158.      mov    bx,[bp+8]        ; (which were pushed in Step 2).
  159.      push    bx            ; (They may contain special values
  160.      popff                ; required by the C environment).
  161.  
  162.      lds    bp,[bp+10]        ; Step 10:    Restore stack frame pointer
  163.      assume ds:nothing        ; (pushed in Step 1) so we can find preg.
  164.  
  165.                     ; Obtain contents of preg.
  166.      if    LONGDATA
  167.      lds    bx,preg
  168.      assume ds:nothing
  169.      else
  170.      mov    bx,preg
  171.      endif
  172.                     ; Now DS:BX points to *preg
  173.                     ; (ALLREG structure is at DS:BX).
  174.  
  175.      mov    [bx.reg_ax],ax        ; Store the easy registers in
  176.      mov    [bx.reg_cx],cx        ; the *preg structure.
  177.      mov    [bx.reg_dx],dx
  178.      mov    [bx.reg_si],si
  179.      mov    [bx.reg_di],di
  180.      mov    [bx.reg_es],es
  181.  
  182.      pop    [bx.reg_flags]        ; Transfer values pushed in Step 8
  183.      pop    [bx.reg_bx]        ; to the *preg structure.
  184.      pop    [bx.reg_ds]
  185.      pop    [bx.reg_bp]
  186.  
  187.      add    sp,6            ; Discard values pushed in
  188.                     ; Steps 2 and 1.
  189.  
  190.      xor    ax,ax            ; Success code.
  191.  
  192. exit:
  193.                     ; Now AX contains the error/success code.
  194.  
  195.      cld                ; Restore registers that are important
  196.      pop    es            ; to the C environment.
  197.      pop    ds
  198.      pop    di
  199.      pop    si
  200.  
  201.      pop    bp
  202.      ret
  203.  
  204.      endProg iscall
  205.  
  206.      end
  207.