home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CASM.ARJ / INTER.ASM < prev    next >
Assembly Source File  |  1988-07-28  |  13KB  |  606 lines

  1. ;_ inter.asm   Thu Feb 25 1988   Modified by: Walter Bright */
  2. ; Copyright (c) 1986-1988 by Northwest Software
  3. ; All Rights Reserved
  4. ; Written by Walter Bright
  5.  
  6. ; Interrupt handling package
  7.  
  8. ; If you are developing ROM applications, and MS-DOS won't be present,
  9. ; define ROM. This is to bypass DOS and manipulate the interrupt vector
  10. ; table directly.
  11.  
  12. ;ROM    equ    1    ;bypass DOS when dealing with the vector table
  13.  
  14. include    MACROS.ASM
  15.  
  16. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  17. ; Silly macro to fake a POPF instruction, which doesn't always work.
  18. .popf    macro
  19.     local    L1,L2
  20.     jmps    L2
  21. L1:    iret
  22. L2:    push    cs
  23.     call    L1
  24.     endm
  25.  
  26. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  27. ; Macro to read interrupt vector vecnum from the interrupt vector table
  28. ; into vecseg and vecoff.
  29.  
  30. getvec    macro    vecnum,vecseg,vecoff
  31.     ifdef ROM
  32.     clr    AX
  33.     mov    ES,AX        ;vector table is at segment 0
  34.     mov    AL,vecnum
  35.     mov    DI,AX
  36.     shl    DI,1
  37.     shl    DI,1        ;offset of vector is (vecnum * 4)
  38.     mov    vecoff,ES:[DI]
  39.     mov    vecseg,ES:2[DI]
  40.     else
  41.       ifdif <vecnum>,<AL>
  42.     mov    AL,vecnum
  43.       endif
  44.     bdos    35h        ;read vector in ES:BX
  45.       ifdif <vecoff>,<BX>
  46.     mov    vecoff,BX
  47.       endif
  48.       ifdif <vecseg>,<ES>
  49.     mov    vecseg,ES
  50.       endif
  51.     endif
  52.     endm
  53.  
  54. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  55. ; Macro to set interrupt vector vecnum into the interrupt vector table
  56. ; from vecseg and vecoff.
  57.  
  58. setvec    macro    vecnum,vecseg,vecoff
  59.     ifdef ROM
  60.     push    ES
  61.       ifdif <vecnum>,<AL>
  62.     mov    AL,vecnum
  63.       endif
  64.     clr    AH
  65.     mov    DI,AX
  66.     shl    DI,1
  67.     shl    DI,1
  68.       ifdif <vecseg>,<DS>
  69.     mov    CX,vecseg
  70.       endif
  71.     clr    AX
  72.     mov    ES,AX
  73.     mov    ES:[DI],vecoff
  74.       ifdif <vecseg>,<DS>
  75.     mov    ES:2[DI],CX
  76.       else
  77.     mov    ES:2[DI],vecseg
  78.       endif
  79.     pop    ES
  80.     else
  81.       ifdif <vecseg>,<DS>
  82.     push    DS
  83.       endif
  84.       ifdif <vecnum>,<AL>
  85.     mov    AL,vecnum
  86.       endif
  87.       ifdif <vecoff>,<DX>
  88.     mov    DX,vecoff
  89.       endif
  90.       ifdif <vecseg>,<DS>
  91.     mov    DS,vecseg
  92.       endif
  93.     bdos    025h
  94.       ifdif <vecseg>,<DS>
  95.     pop    DS
  96.       endif
  97.     endif
  98.     endm
  99.  
  100. ;These structures should match union REGS and struct SREGS in dos.h
  101. REGS    macro
  102.     _ax        dw    ?
  103.     _bx        dw    ?
  104.     _cx        dw    ?
  105.     _dx        dw    ?
  106.     _si        dw    ?
  107.     _di        dw    ?
  108.     _cflag        dw    ?
  109.     _flags        dw    ?
  110.     endm
  111.  
  112. SREGS    macro
  113.     _es        dw    ?
  114.     _cs        dw    ?
  115.     _ss        dw    ?
  116.     _ds        dw    ?
  117.     endm
  118.  
  119. ; For unfathomable reasons, if's don't work in structs.
  120.  
  121.     ifdef I8086S
  122. intstr    struc
  123.     callf        db    ?    ;far call
  124.     faraddr        dw    ?,?    ;far address of interrupt service routine
  125.     prevvec        dw    ?,?    ;previous vector
  126.     stacksize    dw    ?    ;size of newstack
  127.     newstack    dw    ?,?    ;new value for SS and SP
  128.     oldstack    dw    ?,?    ;old value of SS and SP
  129.     funcptr        dw    ?    ;function pointer (offset portion)
  130.     _ax        dw    ?
  131.     _bx        dw    ?
  132.     _cx        dw    ?
  133.     _dx        dw    ?
  134.     _si        dw    ?
  135.     _di        dw    ?
  136.     _cflag        dw    ?
  137.     _flags        dw    ?
  138.     _es        dw    ?
  139.     _cs        dw    ?
  140.     _ss        dw    ?
  141.     _ds        dw    ?
  142. intstr    ends
  143.     endif
  144.  
  145.     ifdef I8086M
  146. intstr    struc
  147.     callf        db    ?    ;far call
  148.     faraddr        dw    ?,?    ;far address of interrupt service routine
  149.     prevvec        dw    ?,?    ;previous vector
  150.     stacksize    dw    ?    ;size of newstack
  151.     newstack    dw    ?,?    ;new value for SS and SP
  152.     oldstack    dw    ?,?    ;old value of SS and SP
  153.     funcptr        dw    ?,?    ;function pointer
  154.     _ax        dw    ?
  155.     _bx        dw    ?
  156.     _cx        dw    ?
  157.     _dx        dw    ?
  158.     _si        dw    ?
  159.     _di        dw    ?
  160.     _cflag        dw    ?
  161.     _flags        dw    ?
  162.     _es        dw    ?
  163.     _cs        dw    ?
  164.     _ss        dw    ?
  165.     _ds        dw    ?
  166. intstr    ends
  167.     endif
  168.  
  169.     ifdef I8086P
  170. intstr    struc
  171.     callf        db    ?    ;far call
  172.     faraddr        dw    ?,?    ;far address of interrupt service routine
  173.     prevvec        dw    ?,?    ;previous vector
  174.     stacksize    dw    ?    ;size of newstack
  175.     newstack    dw    ?,?    ;new value for SS and SP
  176.     oldstack    dw    ?,?    ;old value of SS and SP
  177.     funcptr        dw    ?,?    ;function pointer
  178.     _ax        dw    ?
  179.     _bx        dw    ?
  180.     _cx        dw    ?
  181.     _dx        dw    ?
  182.     _si        dw    ?
  183.     _di        dw    ?
  184.     _cflag        dw    ?
  185.     _flags        dw    ?
  186.     _es        dw    ?
  187.     _cs        dw    ?
  188.     _ss        dw    ?
  189.     _ds        dw    ?
  190. intstr    ends
  191.     endif
  192.  
  193.     ifdef I8086C
  194. intstr    struc
  195.     callf        db    ?    ;far call
  196.     faraddr        dw    ?,?    ;far address of interrupt service routine
  197.     prevvec        dw    ?,?    ;previous vector
  198.     stacksize    dw    ?    ;size of newstack
  199.     newstack    dw    ?,?    ;new value for SS and SP
  200.     oldstack    dw    ?,?    ;old value of SS and SP
  201.     staticseg    dw    ?    ;value for DS
  202.     funcptr        dw    ?    ;function pointer (offset portion)
  203.     _ax        dw    ?
  204.     _bx        dw    ?
  205.     _cx        dw    ?
  206.     _dx        dw    ?
  207.     _si        dw    ?
  208.     _di        dw    ?
  209.     _cflag        dw    ?
  210.     _flags        dw    ?
  211.     _es        dw    ?
  212.     _cs        dw    ?
  213.     _ss        dw    ?
  214.     _ds        dw    ?
  215. intstr    ends
  216.     endif
  217.  
  218.     ifdef I8086L
  219. intstr    struc
  220.     callf        db    ?    ;far call
  221.     faraddr        dw    ?,?    ;far address of interrupt service routine
  222.     prevvec        dw    ?,?    ;previous vector
  223.     stacksize    dw    ?    ;size of newstack
  224.     newstack    dw    ?,?    ;new value for SS and SP
  225.     oldstack    dw    ?,?    ;old value of SS and SP
  226.     staticseg    dw    ?    ;value for DS
  227.     funcptr        dw    ?,?    ;function pointer
  228.     _ax        dw    ?
  229.     _bx        dw    ?
  230.     _cx        dw    ?
  231.     _dx        dw    ?
  232.     _si        dw    ?
  233.     _di        dw    ?
  234.     _cflag        dw    ?
  235.     _flags        dw    ?
  236.     _es        dw    ?
  237.     _cs        dw    ?
  238.     _ss        dw    ?
  239.     _ds        dw    ?
  240. intstr    ends
  241.     endif
  242.  
  243.     if LCODE
  244.     c_extrn    malloc,far, free,far
  245.     else
  246.     c_extrn    malloc,near, free,near
  247.     endif
  248.  
  249.     begcode    int
  250.  
  251. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  252. ; Get interrupt vector.
  253. ; Use:
  254. ;    void int_getvector(vectornumber,&offset,&segment);
  255.  
  256.     c_public    int_getvector
  257. func    int_getvector
  258.     push    BP
  259.     mov    BP,SP
  260.     .save    <SI,DI>
  261.     if SPTR
  262.     push    ES
  263.     getvec    P[BP],ES,BX    ;get vector in ES:BX
  264.     mov    SI,P+2[BP]
  265.     mov    [SI],BX
  266.     mov    SI,P+2+SIZEPTR[BP]
  267.     mov    [SI],ES
  268.     pop    ES
  269.     else
  270.     getvec    P[BP],AX,BX    ;get vector in AX:BX
  271.     les    SI,P+2[BP]
  272.     mov    ES:[SI],BX
  273.     les    SI,P+2+SIZEPTR[BP]
  274.     mov    ES:[SI],AX
  275.     endif
  276. G1:    .restore <DI,SI>
  277.     pop    BP
  278.     ret
  279. c_endp    int_getvector
  280.  
  281. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  282. ; Set interrupt vector.
  283. ; Use:
  284. ;    void int_setvector(vectornumber,offset,segment);
  285.  
  286.     c_public    int_setvector
  287. func    int_setvector
  288.     push    BP
  289.     mov    BP,SP
  290.     .save    <SI,DI>
  291.     mov    DX,P+2[BP]
  292.     setvec    P[BP],P+2+2[BP],DX
  293.     jmps    G1
  294. c_endp    int_setvector
  295.  
  296. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  297. ; Generic interrupt service routine.
  298. ; Figure out who called us, set up the stack, and then call the
  299. ; specified function.
  300. ; Chain to previous vector if funcptr returns a 0.
  301. ; This function is not callable by C, it is public so debuggers will
  302. ; know about it.
  303.  
  304.     public    int_service
  305. int_service    proc    near
  306.     push    BP
  307.     mov    BP,SP
  308.     push    DS
  309.     push    BX
  310.     lds    BX,2[BP]        ;DS:BX -> intstr+5 (!)
  311.     mov    _ax-5[BX],AX
  312.     pop    _bx-5[BX]
  313.     mov    _cx-5[BX],CX
  314.     mov    _dx-5[BX],DX
  315.     mov    _si-5[BX],SI
  316.     mov    _di-5[BX],DI
  317.     pushf
  318.     pop    _flags-5[BX]
  319.     mov    _es-5[BX],ES
  320.     mov    _cs-5[BX],CS
  321.     mov    _ss-5[BX],SS
  322.     pop    _ds-5[BX]
  323.     mov    oldstack-5[BX],SP
  324.     mov    oldstack+2-5[BX],SS    ;remember old stack
  325.     cli                ;for bug in old 8088's
  326.     mov    SS,newstack+2-5[BX]
  327.     mov    SP,newstack-5[BX]    ;set new stack
  328.     sti                ;for bug in old 8088's
  329.     push    BX
  330.     cld                ;no bugs with backwards direction flag
  331.  
  332.     if SPTR
  333.     push    DS
  334.     pop    ES            ;set ES to be same as DS
  335.     push    BX            ;push offset of struct INT_DATA
  336.     if LCODE
  337.     call    dword ptr funcptr-5[BX]
  338.     else
  339.     call    word ptr funcptr-5[BX]
  340.     endif
  341.     add    SP,SIZEPTR
  342.     else ;LPTR
  343.     push    DS
  344.     push    DS
  345.     pop    ES
  346.     mov    DS,staticseg-5[BX]    ;set static data segment
  347.     push    ES            ;push segment of struct SREGS
  348.     push    BX            ;push offset of struct INT_DATA
  349.     if LCODE
  350.     call    ES:dword ptr funcptr-5[BX]
  351.     else
  352.     call    ES:word ptr funcptr-5[BX]
  353.     endif
  354.     add    SP,SIZEPTR
  355.     pop    DS
  356.     endif
  357.     pop    BX
  358.     cli                ;for bug in old 8088's
  359.     mov    SS,oldstack+2-5[BX]
  360.     mov    SP,oldstack-5[BX]    ;restore interrupted stack
  361.     sti                ;for bug in old 8088's
  362.     tst    AX            ;chain?
  363.     jnz    S1            ;no
  364.     mov    AX,prevvec+2-5[BX]    ;segment of previous vector
  365.     mov    2+2[BP],AX
  366.     mov    AX,prevvec-5[BX]    ;offset of previous vector
  367.     mov    2[BP],AX        ;so retf at S2 will jump to prev vector
  368. S1:
  369.     ;Get register return values
  370.     push    _flags-5[BX]
  371.     push    _ds-5[BX]
  372.     mov    ES,_es-5[BX]
  373.     mov    DI,_di-5[BX]
  374.     mov    SI,_si-5[BX]
  375.     mov    DX,_dx-5[BX]
  376.     mov    CX,_cx-5[BX]
  377.     mov    AX,_ax-5[BX]
  378.     mov    BX,_bx-5[BX]
  379.     pop    DS
  380.  
  381.     jz    S2        ;if chain
  382.     .popf
  383.     pop    BP
  384.     add    SP,4        ;pop off address of far call to us
  385.     iret
  386.  
  387. S2:    .popf
  388.     pop    BP
  389.     .retf
  390. int_service endp
  391.  
  392. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  393. ; Intercept a vector.
  394. ; Use:
  395. ;    int int_intercept(unsigned vectornumber,int (*funcptr)(struct INT_DATA *),
  396. ;        unsigned stacksize);
  397. ; Input:
  398. ;    funcptr    Pointer to a function which returns:
  399. ;        0:    chain to previous interrupt vector
  400. ;        !=0:    return from interrupt
  401. ; Returns:
  402. ;    0    success
  403. ;    -1    failure
  404.  
  405.     c_public    int_intercept
  406. func    int_intercept
  407.     push    BP
  408.     mov    BP,SP
  409.     .save    <SI,DI>
  410.     if SPTR
  411.     push    ES
  412.     endif
  413.     mov    AX,size intstr
  414.     push    AX
  415.     callm    malloc
  416.     add    SP,2
  417.     if LPTR
  418.     ifdef MSC
  419.     mov    BX,AX
  420.     mov    AX,DX
  421.     endif
  422.     endif
  423.     tst    AX        ;error allocating?
  424.     jz    err1        ;yes
  425.     if SPTR
  426.     mov    SI,AX
  427.     mov    callf[SI],09Ah            ;opcode for far call
  428.     mov    faraddr[SI],offset int_service    ;offset of interrupt server
  429.     mov    faraddr+2[SI],CS        ;segment of interrupt server
  430.     mov    AX,P+2+SIZEPTR[BP]    ;get stacksize
  431.     .if    AX ae 128, i2
  432.     mov    AX,128            ;128 bytes minimum size
  433. i2:
  434.     mov    stacksize[SI],AX    ;remember stack size
  435.     push    SI
  436.     push    AX
  437.     callm    malloc
  438.     add    SP,2
  439.     pop    SI
  440.     tst    AX
  441. err1:    jz    err            ;error allocating for stack
  442.     add    AX,stacksize[SI]    ;adjust SP to be past top of stack
  443.     mov    newstack[SI],AX        ;value for SP at start of interrupt
  444.     mov    newstack+2[SI],SS    ;value for SS
  445.     ifdef I8086S
  446.     mov    AX,P+2[BP]
  447.     mov    funcptr[SI],AX
  448.     endif
  449.     ifdef I8086M
  450.     mov    AX,P+2[BP]        ;get offset of function
  451.     mov    funcptr[SI],AX
  452.     mov    AX,P+2+2[BP]
  453.     mov    funcptr+2[SI],AX    ;get segment of function
  454.     endif
  455.     ifdef I8086P            ;Lattice type P model
  456.     mov    BX,P+2[BP]        ;what we really have is a pointer to
  457.     mov    AX,[BX]            ; a function
  458.     mov    funcptr[SI],AX
  459.     mov    AX,2[BX]
  460.     mov    funcptr+2[SI],AX
  461.     endif
  462.  
  463.     getvec    P[BP],ES,BX        ;get old vector in ES:BX
  464.     mov    prevvec[SI],BX
  465.     mov    prevvec+2[SI],ES    ;store in struct
  466.  
  467.     setvec    AL,DS,SI    ;set vector to DS:SI
  468.     else ;LPTR
  469.     mov    ES,AX
  470.     mov    SI,BX
  471.     mov    ES:callf[SI],09Ah        ;opcode for far call
  472.     mov    ES:faraddr[SI],offset int_service ;offset of interrupt server
  473.     mov    ES:faraddr+2[SI],CS        ;segment of interrupt server
  474.     mov    ES:staticseg[SI],DS        ;segment of static data
  475.     mov    AX,P+2+SIZEPTR[BP]    ;get stacksize
  476.     .if    AX ae 128, i2
  477.     mov    AX,128            ;128 bytes minimum size
  478. i2:
  479.     mov    ES:stacksize[SI],AX    ;remember stack size
  480.     .push    <ES,SI>
  481.     push    AX
  482.     callm    malloc
  483.     add    SP,2
  484.     .pop    <SI,ES>
  485.     ifdef MSC
  486.     mov    BX,AX
  487.     mov    AX,DX
  488.     endif
  489.     tst    AX
  490. err1:    jz    err            ;error allocating for stack
  491.     add    BX,ES:stacksize[SI]    ;adjust SP to be past top of stack
  492.     mov    ES:newstack[SI],BX    ;value for SP at start of interrupt
  493.     mov    ES:newstack+2[SI],AX    ;value for SS
  494.     mov    AX,P+2[BP]        ;get offset of function
  495.     mov    ES:funcptr[SI],AX
  496.     ifdef I8086L
  497.     mov    AX,P+2+2[BP]
  498.     mov    ES:funcptr+2[SI],AX    ;get segment of function
  499.     endif
  500.  
  501.     push    ES
  502.     getvec    P[BP],CX,BX        ;get old vector in CX:BX
  503.     pop    ES
  504.     mov    ES:prevvec[SI],BX
  505.     mov    ES:prevvec+2[SI],CX    ;store in struct
  506.  
  507.     push    DS
  508.     push    ES
  509.     pop    DS
  510.     setvec    AL,DS,SI    ;set vector to DS:SI
  511.     pop    DS
  512.     endif
  513.     clr    AX        ;success
  514.     jmps    i1
  515.  
  516. err:    mov    AX,-1
  517. i1:
  518.     if SPTR
  519.     pop    ES
  520.     endif
  521.     .restore <DI,SI>
  522.     pop    BP
  523.     ret
  524. c_endp    int_intercept
  525.  
  526. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  527. ; Restore previous interrupt vector.
  528. ; Use:
  529. ;    int int_restore(vectornumber);
  530. ; Returns:
  531. ;    0    success
  532. ;    -1    failure
  533.  
  534.     c_public    int_restore
  535. func    int_restore
  536.     push    BP
  537.     mov    BP,SP
  538.     .save    <SI,DI>
  539.     getvec    P[BP],ES,BX    ;ES:BX -> intstr (also, ES == DS if req'd)
  540.     if SPTR
  541.     mov    AX,newstack[BX]
  542.     sub    AX,stacksize[BX]
  543.     push    BX        ;save BX
  544.     push    AX
  545.     callm    free        ;free allocated stack
  546.     pop    CX
  547.     pop    BX
  548.     ifndef MSC
  549.     tst    AX
  550.     jnz    R1        ;failed
  551.     endif
  552.  
  553.     mov    DX,prevvec[BX]
  554.     setvec    P[BP],prevvec+2[BX],DX    ;restore previous vector
  555.     push    BX
  556.     callm    free        ;free intstr
  557.     pop    BX
  558.     else
  559.     mov    AX,ES:newstack[BX]
  560.     sub    AX,ES:stacksize[BX]
  561.     .push    <ES,BX>            ;save ES,BX
  562.     push    ES:newstack+2[BX]    ;segment of allocated stack
  563.     push    AX            ;offset of allocated stack
  564.     callm    free            ;free allocated stack
  565.     add    SP,SIZEPTR
  566.     .pop    <BX,ES>
  567.     ifndef MSC
  568.     tst    AX
  569.     jnz    R1            ;failure
  570.     endif
  571.  
  572.     mov    DX,ES:prevvec[BX]
  573.     setvec    P[BP],ES:prevvec+2[BX],DX    ;restore previous vector
  574.     push    ES        ;segment of intstr
  575.     push    BX        ;offset of intstr
  576.     callm    free        ;free intstr
  577.     add    SP,SIZEPTR
  578.     endif
  579.     ifdef MSC
  580.     clr    AX        ;no return value from free()
  581.     endif
  582. R1:    .restore <DI,SI>
  583.     pop    BP        ;return value of free() indicates success
  584.     ret            ; or failure
  585. c_endp    int_restore
  586.  
  587. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  588. ; Turn interrupts on/off.
  589.  
  590.     c_public    int_on
  591. func    int_on
  592.     sti
  593.     ret
  594. c_endp    int_on
  595.  
  596.     c_public int_off
  597. func    int_off
  598.     cli
  599.     ret
  600. c_endp    int_off
  601.  
  602.     endcode    int
  603.  
  604.     end
  605.  
  606.