WHAT ARE INTERRUPTS?
Interrupts are special functions, which is built in the
BIOS (basic input output system). There are nearly hundreds of interrupt in the BIOS and
we are dealing with Interrupt 0x33 (mouse functions). Whenever an interrupt is called, any
task, which is in progress, will be interrupted to execute the requested task. This
interrupt is called by setting the appropriate register value, call the interrupt and
output value will be set to the same register. Either the programmer can look at the
output value in the specified register to determine the called interrupt is performed
perfectly or error has occurred.
WHAT ARE REGISTERS?
Register is a special memory placed in the microprocessor
chip, i.e. the 8086, 80186, 80286, 80386, 80486 or Pentium® Chip for faster
calculation. This memory location is used during calculation and other stuff. There are
several kind of register in the chip and what I am listing here is just the information
enough for us to get to mouse programming.
The Intel® 80x86 family and Pentium® has the following
registers in their chips.
- General-purpose register: AX, BX, CX, DX which will be used
widely in our program.
- AX (16 bits) is a combination of AH and AL (H-higher 8 bits,
L-lower 8 bits). This combination is also applicable to BX, CX, DX register.
8 bits |
8 bits |
Names |
AH |
AL |
Accumulator |
BH |
BL |
Base |
CH |
CL |
Counter |
DH |
DL |
Data |
- Segment Register which in our consideration
16 bits |
Names |
ES |
Extra Segment |
CS |
Code Segment |
SS |
Stack Segment |
DS |
Data Segment |
16 bits |
Names |
SI |
Source Index |
DI |
Destination Index |
CALLING INTERRUPT
To access the interrupts, we need special function or
routine, which can access the microprocessor register and interrupts as well. For example,
In Borland Turbo C (TC), there are special routines that deals with interrupts, the header
file for this library routine is <dos.h>. i.e you have to #include<dos.h>
int86(int intrptnum, struct REGS *regs, struct REGS *regs);
int86x(int intrptnum, struct REGS *inregs, struct REGS *outregs, struct SSREGS *sregs);
Accessing General Purpose Register and Segment Register
in C (Unions & Structures)
General Purpose Register
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
Structures: BYTEREGS & WORDREGS Structures for storing
byte and word registers.
struct BYTEREGS {
unsigned char al, ah, bl, bh;
unsigned char cl, ch, dl, dh;
};
struct WORDREGS {
unsigned int ax, bx, cx, dx;
unsigned int si, di, cflag, flags;
};
Segment Register
struct SREGS {
unsigned int es;
unsigned int cs;
unsigned int ss;
unsigned int ds;
};
For example if we want to to use interrupt 0x33, 0x00,
which will check the existance of mouse driver. The code is
/*****************************************************
*** this code will check the existance of mouse driver
*****************************************************/
int check_mouse(void)
{
union REGS inregs={0}
union REGS outregs={0}; /* declaring regs unions */
regs.x.ax=0x00; /* set the value in reg.x.ax :input*/
int86(0x33,&inregs,&outregs); /* call the interrupt 0x33 */
return outregs.x.ax; /* returning 0x0000 or 0xFFFF :output*/
}
After the interrupt is called, the returned value
will be in outregs. For example, If the mouse is NOT installed, the AX value in regs will
now be 0xFFFF. We can also use the same variables for input and output.
The value of output will be send to regs.
In above code, we are using int86 function because
the register, which is under consideration, is from AX to DX. There are certain cases when
we need to access other register like ES, DI, and SI. Therefore the second function, int86x,
is desireable.
If you're working with other C compiler, you can search the
help file and look for a function, which does the similar function, i.e. calling
interrupt.
FAR & NEAR, SEGMENT:OFFSET thing.
- Each memory location in the computer RAM is represented by
SEGMENT:OFFSET.
- For example if we declared char buffer[10]. The address of
"buffer" can be referred as FP_SEG(buffer):FP_OFF(buffer).
- FP_SEG is a macro that returns the segment address, while
FP_OFF is a macro that return the offset address.
- This representation is widely use when we want to refer a
location of memory location to an interrupt. Look at the example below.
/*******************************
*** set graphic cursor.
*** cursor is 64 byte array.
*** 0-31 screen mask.
*** 32-63 cursor mask.
*** >> using int 33,0x09
********************************/
void mouse_set_grphcur(void *cursor) /* custom cursor*/
{
union REGS regs={0}; /* using AX,BX,CX,DX */
struct SREGS sregs={0}; /* using ES */
regs.x.ax=0x09;
regs.x.bx=0; /* active horiz pixel */
regs.x.cx=0; /* active vert pixel */
regs.x.dx=FP_OFF(cursor); /* offset address of cursor */
sregs.es=FP_SEG(cursor); /* segment address of cursor */
int86x(0x33,®s,®s,&sregs);
}
The DX register needs to be the offset of
the cursor address and ES register needs to the segment of the cursor
address in order for the function to work. |