jfjr@mbunix.mitre.org (Freedman) (02/12/91)
I have been using MSC 6.00. I have seen, used and written code accepted by this compiler where the keyword/attribute "interrupt" or "_interrupt" is used but I can't find the documentation for it anywhere. Can anyone give me the exact definitio/semantics of it and where it can be found? Jerry Freedman,Jr
jvb7u@fermi.clas.Virginia.EDU (Jon Brinkmann) (02/12/91)
In article <1991Feb11.171349.11579@linus.mitre.org> jfjr@mbunix.mitre.org (Freedman) writes:
#
# I have been using MSC 6.00. I have seen, used and written code
#accepted by this compiler where the keyword/attribute "interrupt"
#or "_interrupt" is used but I can't find the documentation for
#it anywhere. Can anyone give me the exact definitio/semantics
#of it and where it can be found?
Try:
Christian, Kaare, "Using MicroSoft C Version 5.1 to Write
Terminate-and-Stay-Resident Programs", MicroSoft Systems
Journal, September 1988, Volume 3, Number 5, pages 47 - 57.
The software examples in this article are available from
SIMTEL in the file PD1:<MSDOS.MSJOURNAL>MSJV3-5.ARC.
Jon
--
Jon Brinkmann Astronomy Department
Internet: jvb7u@Virginia.EDU University of Virginia
UUCP: ...!uunet!virginia!jvb7u P.O. Box 3818
SPAN/HEPnet: 6654::jvb7u Charlottesville, VA 22903-0818
rkl@cbnewsh.att.com (kevin.laux) (02/12/91)
In article <1991Feb11.171349.11579@linus.mitre.org>, jfjr@mbunix.mitre.org (Freedman) writes: > > I have been using MSC 6.00. I have seen, used and written code > accepted by this compiler where the keyword/attribute "interrupt" > or "_interrupt" is used but I can't find the documentation for > it anywhere. Can anyone give me the exact definitio/semantics > of it and where it can be found? You can find it in the readme.doc file in the .../source/doc subdirectory under where you installed the compiler. Also I believe you can find it using 'qh' (quick help), MSC's online help facility. -- ________________________________________________________________________________ R. Kevin Laux Email: rkl1@hound.att.com AT&T Bell Labs Voice: (908) 949-1160
gardner@iccgcc.decnet.ab.com (02/12/91)
/******************************************************************************/ /* The following was extracted from Microsofts C compiler, V 6.0.... */ /* ALL RIGHTS RESERVED AND COPYWRITTEN BY MICROSOFT CORPORATION. */ /******************************************************************************/ /******************************************************************************/ /* To obtain this information using MSC 6.0, I used the CL -HELP command */ /* and then SEARCHED for the interrupt keyword... Hope this helps. */ /* */ /* Mike Gardner - Allen-Bradley Company */ /******************************************************************************/ Keyword: _interrupt Syntax: _interrupt declarator Summary: Indicates that the function is an interrupt handler. The compiler generates appropriate entry and exit sequences for the handling function, including saving and restoring all registers and executing an IRET instruction to return. For compatibility with previous versions, interrupt is a synonym for _interrupt. See also: _chain_intr, _dos_getvect, _dos_keep, _dos_setvect The _interrupt keyword applies to interrupt handlers written in C. (This discussion assumes that you understand interrupts, and does not attempt to cover the techniques for interrupt handling or implications of incorrect interrupt handling.) The _interrupt keyword can be applied to a function to tell the compiler that the function is an interrupt handler. This keyword tells the compiler to generate the entry and exit sequences required for an interrupt-handling function, including saving and restoring registers and executing an IRET instruction to return. When an interrupt function is called, the DS register is initialized to the C near data segment. This allows you to access global variables from within an interrupt function. In addition, all registers (except SS) are saved on the stack. You can access these registers within the function if you declare a function parameter list containing a formal parameter for each saved register. The following example illustrates such a declaration: void _interrupt _far int_handler( unsigned _es, unsigned _ds, unsigned _di, unsigned _si, unsigned _bp, unsigned _sp, unsigned _bx, unsigned _dx, unsigned _cx, unsigned _ax, unsigned _ip, unsigned _cs, unsigned flags ) { . . . } Keyword Conflicts to Avoid An interrupt function must be far. If you are compiling with the small or compact memory model, you must explicitly declare the function with the _far attribute. If you do not specify a memory model by using the /A compiler option, small model is used and interrupt functions must be explicitly declared with the _far attribute. Interrupt functions must observe the C calling convention. If you used the /Gc compiler option to make FORTRAN/Pascal calling conventions the default, you must explicitly declare your interrupt-handling function with the _cdecl attribute. You cannot declare a function with both the _interrupt and the _saveregs attributes. Declaring Formal Parameters Formal parameters must be listed in the opposite order from which they are pushed onto the stack. If you do not need access to all of the registers, you can omit parameters from the end of the list in your declaration. You cannot omit formal parameters from the beginning of the parameter list. For example, if your handler needs to use only DI and SI, you must still provide ES and DS, but not necessarily BX or DX or those that follow. The compiler always saves and restores registers in the same fixed order. Thus, no matter what names you use in the formal parameter list, the first parameter in the list refers to ES, the second refers to DS, and so on. Although there is technically no restriction on what you name the register parameters, you should not give them actual register names because they may conflict with future releases of CL or in- line assembler code. A useful convention for avoiding the conflict and retaining the documentation of the register names is to precede each one with an underscore (for example, _ax, _bx). Passing Additional Arguments You can pass additional arguments if your interrupt handler is to be called directly from C rather than by an INT instruction. To do this, you must declare all register parameters and then declare your parameter at the end of the list. Changing Parameters If you change any of the parameters of an interrupt function while the function is executing, the corresponding register contains the changed value when the function returns. For example, the code below causes the DI register to contain -1 when the int_handler function returns. Do not modify the values of the parameters representing the IP and CS registers in interrupt functions. If you need to modify a particular flag, such as the carry flag for certain DOS and BIOS interrupt routines, use the bitwise-OR operator (|) so that other bits in the flags register are not changed. void _interrupt _far int_handler( unsigned _es, unsigned _ds, unsigned _di, unsigned _si) { _di = -1; } Transferring Control to a Second Interrupt Function Interrupt functions often need to transfer control to a second interrupt routine. This can be done in the following two ways: 1. You can call the interrupt routine (after casting it to an interrupt function if necessary), as shown in the code below. Do this if you need to do further processing after the second interrupt routine finishes. void _interrupt _far new_int() { // Initial processing here . . . (*old_int)(); . . . // Final processing here } 2. Call _chain_intr with the interrupt routine as an argument. The code below shows an example of this. Do this if your routine is finished and you want the second interrupt routine to terminate the interrupt call. void _interrupt _far new_int() { . . . // Initial processing here . . . _chain_intr( old_int ); // This is never executed } In general, it is not a good idea for an interrupt function to call standard library functions, especially functions that rely on DOS INT 21H or BIOS calls. Functions that rely on INT 21H calls include I/O functions and _dosxxx functions. Functions that rely on the BIOS include graphics functions and _biosxxx functions. It may be safe to use functions that do not rely on INT 21H or BIOS, such as string-handling functions. Before using a standard library function in an interrupt function, be sure that you are familiar with the library function and what it does. Interrupt functions are primarily for the DOS environment; they should not normally be used under OS/2. Special Considerations When an interrupt function is called by an INT instruction, the interrupt enable flag is cleared. This means that no further interrupts will be processed until your function returns (including keyboard, time-of-day, and other crucial interrupts). If your function needs to do significant processing, you should use the _enable function to set the interrupt flag so that interrupts can be handled. Interrupt functions are special cases of C functions, since they are potentially re-entrant. When designing an interrupt-handling function in C, consider the following guidelines: . If your function does not use the _enable function to set the interrupt flag, important interrupts may be ignored. . If your function does use the _enable function to set the interrupt flag, another interrupt may take place. Make sure that your handler takes this into account. --