Tuesday, February 18, 2020

Interrupt Handling With C


Interrupt Handling with C Programming Language

C computer language is a very powerful language for hardware programming. It has several predefined functions, which can call different interrupts. Some of them, which are important, are given below:

Note: What are interrupts, to know this, please refer my article: Playing with mouse using C language

int86( ): Invokes MS-DOS interrupts.
int86x( ): Invokes MS-DOS interrupts with segment register values.
intdos( ): invokes MS-DOS service using registers other than DX and AL
intdosx( ): invokes MS-DOS service with segment register values.
segread( ): Reads Segment registers

We shall discuss some predefined structure and unions that are frequently or necessarily used with these functions.

SREGS Structure :

This structure has been defined in dos.h and it is a structure of the segment registers passed to and filled in by the functions int86x( ), intdosx( ) and segread( ). The declaration of the structure is as follows:

struct SREGS {
                            unsigned int es;
                            unsigned int cs;
                            unsigned int ss;
                            unsigned int ds;
};

REGS union :

REGS is the union of two structures. The union REGS has been defined in dos.h and it is used to pass information to and from the functions int86( ), int86x( ), intdos( ) and intdosx( ). The declaration of the union is given below:-

union REGS {
                           struct WORDREGS x;
                           struct BYTEREGS h;
};

BYTEREGS and WORDREGS Structures :

The BYTEREGES and WORDREGS structures have been defined in dos.h and these are used for storing byte and word registers. The WORGREGS structure allows the user to access the full 16-bit CPU registers, whereas BYTEREGES structure gives access to the individual 8-bit registers.

The BYTEREGS structure is declared as given below:-

struct BYTEREGS {
                                     unsigned char al, ah, bl, bh;
                                     unsigned char cl, ch, dl, dh;
};

And the WORDREGS structure is declared as given below:-

struct WORDREGS {
                                         unsigned int ax, bx, cx, dx;
                                         unsigned int si, di, cflag, flags;
};


Now, we shall discuss the functions specified earlier in this article.

int86( ) and int86x( ) functions :

These functions are the general 8086 software interrupt interfaces defined in dos.h. Registers are set to the desired values and these functions are called to invoke the MS-DOS interrupts. The declaration of the int86( ) function is given below:-

int int86(int intno, union REGS *inregs, union REGS *outregs);

Function int86x( ) is the variation of function int86( ). It is declared as given below:-

int int86x(int intno, union REGS *inregs, union REGS *outregs, struct SREGS *segregs);

Both the functions int86( ) and int86x( ) execute an 8086 software interrupt specified by the argument intno (Where ‘intno’ is the interrupt number corresponding to the ROM-BIOS function to be invoked).  With int86x( ) function, access is possible only to ES and DS and not to CS and SS, so you can invoke an 8086 software interrupt that takes a value of DS, different from the default data segment and/or takes an argument in ES. These functions copy register values from inregs into the registers before execution of the software interrupt. The function int86x( ) also copies the segregs->ds and segregs->es values into the corresponding registers before executing the software interrupt. This feature allows programs that use far pointers or a large data memory model to specify which segment is to be used for the software interrupt. The functions copy the current register values to outregs, status of the carry flag to the x.cflag field in outregs and the value of the 8086 flags register to the x.flags field in outregs, after the software interrupt returns. The function int86x( ) also restores DS and sets the segregs->es and segregs->ds fields to the values of the corresponding segment registers. In both functions inregs and outregs can point to the same structure and both functions return the value of AX after completion of the software interrupt. If the carry flag is set, it usually indicates that an error has occurred.

segread( ) Function :

This function has been defined in dos.h. This function reads the segment registers. The declaration of the function is given below:-

void segread(struct SREGS *segp);

where segread( ) puts the current values of the segment registers into the structure *segp. Nothing is returned by the function and the call is intended for use with functions intdosx( ) and int86x( ).

intdos( ) and intdosx( ) Functions :

These functions have been defined in dos.h. These are the general DOS interrupt interfaces. The function intdos( ) invokes MS-DOS service registers, whereas the function intdosx( ) invokes MS-DOS service with segment register values.

The Declaration of the intdos( ) function is given below:-

int intdos(union REGS *inregs, union REGS *outregs);

The declaration of intdosx( ) function is given below:-

int intdosx(union REGS *inregs, union REGS *outregs, struct SREGS *segregs);

The functions intdos( ) and intdosx( ) execute DOS interrupt 0x21 to invoke a specified DOS function. The value of inregs->h.ah specifies the DOS function to be invoked. The function intdosx( ) also copies the segregs ->ds and segregs ->es values into the corresponding registers before invoking the DOS function and then restores DS. This feature of the functions allows the programs that use far pointers or a large data memory model specify which segment is to be used for the function execution. With intdosx( ) function you can invoke a DOS function that takes a value of DS different from the default data segment and/or takes an argument in ES.

Both the functions return the value of AX after completion of the DOS function call and if the carry flag is set (outregs -> x.cflag != 0), it indicates that an error occurred.