home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c220 / 7.ddi / EXAMPLES / INTHNDLR / ERR387.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-11-29  |  7.7 KB  |  288 lines

  1.     .386p
  2.     .387
  3. ;************************************************************************/
  4. ;*    Copyright (C) 1986-1990 Phar Lap Software, Inc.            */
  5. ;*    Unpublished - rights reserved under the Copyright Laws of the    */
  6. ;*    United States.  Use, duplication, or disclosure by the         */
  7. ;*    Government is subject to restrictions as set forth in         */
  8. ;*    subparagraph (c)(1)(ii) of the Rights in Technical Data and     */
  9. ;*    Computer Software clause at 252.227-7013.            */
  10. ;*    Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138    */
  11. ;************************************************************************/
  12.  
  13. ;
  14. ; This program demonstrates how to write a protected mode hardware 
  15. ; interrupt handler.  It takes over the coprocessor exception (IRQ13),
  16. ; and then causes a 387 exception to let the handler get invoked.
  17. ;
  18.  
  19. ;
  20. ; Constants and data structures
  21. ;
  22. include    dosx.ah
  23.  
  24. ;
  25. ; Segment definitions and ordering
  26. ;
  27. _codeseg    segment    byte public use32 'code'
  28. _codeseg    ends
  29. _data        segment    dword public use32 'data'
  30. _data        ends
  31. _stack        segment dword stack use32 'stack'
  32.     db    2048 dup (?)    ; 2K stack
  33. _stack        ends
  34.  
  35. ;
  36. ; Global data
  37. ;
  38. _data    segment    
  39.  
  40.     public    irq8_vec,irq13_offs,irq13_sel,envblk
  41. irq8_vec    db    ?    ; interrupt vector for IRQ8 interrupt
  42.     align    4
  43. irq13_offs    dd    ?    ; original IRQ13 handler address
  44. irq13_sel    dw    ?        ;
  45.     align    4
  46. ctl_387    dw    0        ; 387 control word with exceptions unmasked
  47.     align    4
  48. minus_one dq    -1.0        ; floating point constant
  49. envblk    dd    7 dup (?)    ; buffer for 387 environment block
  50.  
  51. no387msg db    'No 387 coprocessor on this machine',0Dh,0Ah,'$'
  52. pmenvmsg db     '80387 environment block:',0Dh,0Ah,'$'
  53.  
  54. _data    ends
  55.  
  56. ;****************************************************************************
  57. ; Program entry point
  58. ;****************************************************************************
  59.  
  60.     assume    cs:_codeseg,ds:_data
  61. _codeseg    segment    
  62.  
  63.     public    main
  64. main proc    near
  65.  
  66. ;
  67. ; Check for a 387 present, exit if not
  68. ;
  69.     int    11h            ; BIOS equipment check
  70.     test    ax, 2            ; branch if no coprocessor
  71.     jz    #no_coproc            ;
  72.  
  73. ;
  74. ; Save current IRQ13 handler vector and install our own handler.  We
  75. ; only need to hook protected mode interrupts because we are only going
  76. ; to execute coprocessor instructions in protected mode, so the coprocessor
  77. ; exception will never occur in real mode.
  78. ;
  79.     mov    ax, 250Ch        ; get H/W int vector mappings
  80.     int    21h                ;
  81.     mov    irq8_vec, ah            ; 
  82.     mov    cl, irq8_vec        ; save current IRQ13 handler
  83.     add    cl, 5                ; 
  84.     mov    ax, 2502h            ;
  85.     int    21h                ; 
  86.     mov    irq13_sel, es            ;
  87.     mov    irq13_offs, ebx            ;
  88.     push    ds            ; install our IRQ13 handler
  89.     lea    edx, irq13_hndlr        ; 
  90.     mov    cl, irq8_vec            ;
  91.     add    cl, 5                ; 
  92.     mov    ax, cs                ;
  93.     mov    ds, ax                ; 
  94.     mov    ax, 2504h            ;
  95.     int    21h                ;
  96.     pop    ds                ;
  97.  
  98. ;
  99. ; Cause a coprocessor exception
  100. ;
  101.     finit                ; init the 387    
  102.     fldcw    ctl_387            ; unmask all exceptions
  103.     fld    minus_one        ; square root of a negative number
  104.     fsqrt                    ;
  105.  
  106. ;
  107. ; Restore original IRQ13 handler and exit
  108. ;
  109.     push    ds            ; restore original handler
  110.     mov    cl, irq8_vec            ;
  111.     add    cl, 5                ; 
  112.     mov    edx, irq13_offs            ; 
  113.     mov    ax, irq13_sel            ;
  114.     mov    ds, ax                ;
  115.     mov    ax, 2504h            ; 
  116.     int    21h                ;
  117.     pop    ds                ;
  118.     mov    ax, 4C00h        ; exit to DOS
  119.     int    21h                ;
  120.  
  121. #no_coproc:
  122. ;
  123. ; No 387;  print an error message and exit
  124. ;
  125.     lea    edx, no387msg        ; print message
  126.     mov    ah, 9                ;
  127.     int    21h                ;
  128.     mov    ax, 4C01h        ; exit to DOS
  129.     int    21h                ; 
  130. main endp
  131.  
  132. ;****************************************************************************
  133. ; IRQ13_HNDLR - Protected Mode Coprocessor Exception Handler
  134. ;    This handler just stores the coprocessor environment and prints it
  135. ;    out, clears the source of the exception, and returns.
  136. ;****************************************************************************
  137.     public    irq13_hndlr
  138. irq13_hndlr proc    near
  139. ;
  140. ; Save regs and re-enable interrupts.  It's good to re-enable interrupts
  141. ; when possible in an interrupt handler, so other hardware interrupts can
  142. ; occur.
  143. ;
  144.     sti                ; re-enable interrupts
  145.     push    eax            ; save all registers we modify
  146.     push    ds                ;
  147.  
  148. ;
  149. ; Acknowledge the interrupt.  Until we do this, neither this interrupt
  150. ; (IRQ13) nor any lower priority hardware interrupt can occur.  After
  151. ; we do this, we must be prepared to deal with being reentered.  In the
  152. ; case of a coprocessor exception handler, we don't have to worry about
  153. ; reentrancy because we won't cause another coprocessor exception inside
  154. ; the handler.
  155. ;
  156.     mov    al, 20h            ; issue EOI to master 8259 interrupt
  157.     out    20h, al                ; controller
  158.     out    0A0h, al        ; issue EOI to slave 8259
  159.     xor    ax, ax            ; Clear 387 BUSY signal
  160.     out    0F0h, al            ;
  161.  
  162. ;
  163. ; Get the coprocessor environment and print it out
  164. ;
  165.     mov    ax, SS_DATA        ; set DS to our data segment
  166.     mov    ds, ax                ; 
  167.     fstenv    envblk            ; get 387 environment
  168.     call    display_env        ; displays coprocessor environment
  169.  
  170. ;
  171. ; Clear the 387 status and return to interrupted code.
  172. ;
  173.     wait                ; clear exception bits in 387 status
  174.     fclex                    ; 
  175.     fldcw    ctl_387            ; unmask all 387 exceptions
  176.     pop    ds            ; restore regs 
  177.     pop    eax                ;
  178.     iretd                ; return to interrupted code
  179. irq13_hndlr endp
  180.  
  181. ;****************************************************************************
  182. ; DISPLAY_ENV - Routine that displays the saved 387 environment block
  183. ;    Destroys EAX, preserves all other registers.
  184. ;****************************************************************************
  185.     public    display_env
  186. display_env    proc    near
  187.     push    ecx            ; save regs we use
  188.     push    edx                ;
  189.  
  190.     lea    edx, pmenvmsg        ; print message 
  191.     mov    ah, 09h                ;
  192.     int    21h                ;
  193.  
  194.     mov    ecx, 7            ; 7 DWORDs in environment
  195.     lea    edx, envblk        ; ptr to beginning of block
  196. #loop:
  197.     mov    ax, [edx+2]        ; print this doubleword
  198.     call    hwout                ;
  199.     mov    ax, [edx]            ;
  200.     call    hwout                ;
  201.     call    newline            ; output newline
  202.     add    edx, 4            ; step to next dword in env
  203.     loop    #loop            ; continue loop
  204.  
  205.     pop    edx            ; restore registers and exit
  206.     pop    ecx                ;
  207.     ret                    ;
  208.  
  209. display_env    endp
  210.  
  211. ;****************************************************************************
  212. ; hwout - Print word in AX in ascii hex, without modifying any regs except
  213. ;    EAX.
  214. ;****************************************************************************
  215. hwout    proc    near
  216.     push    edx            ; save regs
  217.  
  218.     push    ax            ; save current AX value
  219.     shr    ax,8            ; convert MS byte to ascii
  220.     call    btohex                ;
  221.     push    ax            ; save result
  222.     mov    dl,al            ; print MS digit
  223.     mov    ah,2                ;
  224.     int    21h                ;
  225.     pop    dx            ; print LS digit
  226.     mov    dl,dh                ;
  227.     int    21h                ;
  228.     pop    ax            ; convert LS byte to ascii
  229.     call    btohex                ;
  230.     push    ax            ; save result
  231.     mov    dl,al            ; print MS digit
  232.     mov    ah,2                ;
  233.     int    21h                ;
  234.     pop    dx            ; print LS digit
  235.     mov    dl,dh                ;
  236.     int    21h                ;
  237.  
  238.     pop    edx            ; restore modifed regs & exit
  239.     ret
  240. hwout    endp
  241.  
  242. btohex    proc    near    ; convert byte to hex
  243.     push    bx            ; save regs
  244.     mov    ah,0            ; make sure AH is 0
  245.     mov    bx,ax            ; save value to convert
  246.     call    ntohex            ; get LS hex digit into BL
  247.     xchg    ax,bx                ;
  248.     shr    ax,4            ; get MS hex digit into AL
  249.     call    ntohex                ;
  250.     shl    bx,8            ; combine the two digits in AX
  251.     or    ax,bx                ;
  252.     pop    bx            ; restore regs & exit
  253.     ret
  254. btohex    endp
  255.  
  256. ntohex    proc    near    ; convert nibble to ascii hex
  257.     and    ax,0Fh            ; mask out all but low nibble
  258.     cmp    ax,10            ; branch if digit from 0 - 9
  259.     jb    short #digit            ;
  260.     add    ax,'A' - 10        ; digit from A-F
  261.     ret                    ;
  262. #digit:
  263.     add    ax,'0'            ; digit from 0-9
  264.     ret
  265. ntohex    endp
  266.  
  267. ;****************************************************************************
  268. ; newline - output newline without modifying any regs
  269. ;****************************************************************************
  270. newline    proc    near
  271.     push    eax            ; save regs
  272.     push    edx                ;
  273.  
  274.     mov    dl,0Dh            ; output CR/LF
  275.     mov    ah,2                ;
  276.     int    21h                ;
  277.     mov    dl,0Ah                ;
  278.     int    21h                ;
  279.  
  280.     pop    edx            ; restore regs & exit
  281.     pop    eax                ;
  282.     ret
  283. newline    endp
  284.  
  285. _codeseg    ends
  286.  
  287.     end main
  288.