[comp.lang.c] Accessing data from an interrupt handler

gp@picuxa.UUCP (Greg Pasquariello X1190) (10/08/87)

I ran into a small problem today, and I was wondering if anyone could
shed some light on it.  I wrote a test program in MSC 4.0 that will
set up an interrupt handler for the clock interrupt (0x1C).  The interrupt
handler itself was a small ASM module that simply printed out stars whenever
the interrupt occured.  Fine.  The next thing I did was change the int
handler to increment a word of memory (a variable) rather than print stars, 
and when the interrupt was done being serviced, the C program printed the 
value of the variable.  Problem was, the value was ALWAYS 0.  I then ran
the interrupt handler and the C code (a single, small model program) through
Codeview, and found that the variable *WAS* being incremented.  Now can anyone
tell me why the variable is incremented when the routine is used as a called
function, but not when the routine is used as an interrupt routine?

The MSC routines are compiled using the small memory model option, and the
ASM routine is set up to be compatible with the C code (_TEXT segment, _DATA
segment, DGROUP, and all that).  All publics are declared  within the ASM
module, and properly begin with an '_'.  The code is linked as one program
with the interrupt handler embedded, and the routine that sets up the 
new interrupt vector does so correctly.

Any help will be appreciated.  Thanks in advance.





BTW: 	Thanks to all who responded to my question about the "hole" in the
	stack.  The answer dawned on me just after I posted the question!


Greg Pasquariello

jru@etn-rad.UUCP (John Unekis) (10/09/87)

In article <330@picuxa.UUCP> gp@picuxa.UUCP (Greg Pasquariello X1190) writes:
>I ran into a small problem today, and I was wondering if anyone could
>shed some light on it.  I wrote a test program in MSC 4.0 that will
...
>tell me why the variable is incremented when the routine is used as a called
>function, but not when the routine is used as an interrupt routine?

Remember that addresses on the intel processor are composed of two parts,
a segment, which comes from one of the segment registers, and an offset
which may be a register or part of the instruction. When you use the small
model compiler it is assumed that all of your data fits in one segment, and 
the data segment(DS) register is loaded once at the start of your program
and never changed. When you call your routine as a subroutine, the data
segment register is properly set up, and your routine accesses the increment
variable location as an offset from the DS register. When you come into 
your routine off an interrupt, the data segment is set up to whatever DOS
left it at before jumping to your routine. When you try to increment your 
variable as an offset from the data segment you are actually incrementing
some location in the DOS data space(bad idea). In order to find the variable
that you really want to increment, you will have to have a separate entry 
point to your routine that will save the user mode data segment register 
in a memory loacation in the code portion of your interrupt service routine.
Then when you catch an interrupt, you should push the DS on the stack, 
retreive the user mode DS from the location in your code segment, increment
your variable at the correct location, then pop the DOS mode DS back off the
stack.

BTW: This is why Motorola 680X0 processors are so popular for real - time
applications that require interrupt handling and data sharing, NO SEGMENTS.
An address is an address is an address. The propagation of this archaic
segmented architecture into Intel's state-of-the-art 80X86 chips in order 
to preserve IBM PC compatibility reminds me of an old joke:

Intel to IBM : Mommy, Mommy, why do I keep walking in circles?
IBM to Intel : Shut up or I'll nail your other foot to the floor.

daveb@laidbak.UUCP (Dave Burton) (10/09/87)

In article <330@picuxa.UUCP> gp@picuxa.UUCP (Greg Pasquariello X1190) writes:
>...
>I wrote a test program in MSC 4.0 that will
>set up an interrupt handler for the clock interrupt (0x1C).
>...
>The next thing I did was change the int
>handler to increment a word of memory (a variable) rather than print stars, 
>and when the interrupt was done being serviced, the C program printed the 
>value of the variable.  Problem was, the value was ALWAYS 0.  I then ran
>the interrupt handler and the C code (a single, small model program) through
>Codeview, and found that the variable *WAS* being incremented.  Now can anyone
>tell me why the variable is incremented when the routine is used as a called
>function, but not when the routine is used as an interrupt routine?
>...

(venturing to speak without the manuals handy...)
The way you have described the problem, your variable is not being referenced
properly ONLY when called by the interrupt router. I believe (95% sure) that
SS is changed when the interrupt is first serviced. If you wish to access any
variables from your C program, you must retrieve the SS pointer from the
stack, then add the variable's offset to it.

A good book to read which addresses this subject is
"Supercharging C with Assembly".
It is 100% PC/MSDOS specific, but if you're unfortunate enough to be stuck
there, this book gives decent advice and examples.
-- 
--------------------"Well, it looked good when I wrote it"---------------------
 Verbal: Dave Burton                        Net: ...!ihnp4!laidbak!daveb
 V-MAIL: (312) 505-9100 x325            USSnail: 1901 N. Naper Blvd.
#include <disclaimer.h>                          Naperville, IL  60540

flaps@utcsri.UUCP (10/16/87)

gp@picuxa.UUCP (Greg Pasquariello X1190) writes, slightly edited by ajr:
>I wrote a test program in MSC 4.0 [on the ibm-pc] that will
>set up an interrupt handler...
>The next thing I did was change the int
>handler to increment a word of memory (a variable), 
>and when the interrupt was done being serviced, the C program printed the 
>value of the variable.  Problem was, the value was ALWAYS 0.  I then ran
>the interrupt handler and the C code through
>[a symbolic debugger], and found that the variable *WAS* being incremented.

This may or may not be your problem, but you should be declaring this
variable to be volatile.  Otherwise, the compiler is free to compile
something like the printf in:

    function()
    {
	static int i = 8;

	... [no statements affecting the value of i]

	printf("%d\n",i);

	... [no more statements affecting the value of i, or getting any
		pointers to it]
    }

as:
	printf("%d\n",8);


If you add in a 'volatile', the compiler is required to generate code
which actually fetches the value every time you tell it to.

ajr