Showing posts with label int86(). Show all posts
Showing posts with label int86(). Show all posts

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.


Sunday, May 21, 2017

C Program to restrict mouse pointer in a window

Graphics in C – Restrict Mouse Pointer in a Window


In the previous post I have explained the features which are essential to know for mouse programming using C computer language. Now, here is a simple program, by which you will understand these concepts better. Please type this program in your editor. 

#include<graphics.h>
#include<dos.h>

union REGS in, out;
int mousestart();
void showpointer();
void boundpointer(int x1, int y1, int x2, int y2);

void main()
{
      int gd = DETECT, gm, maxx, maxy, x, y;
      initgraph(&gd, &gm, "c:\\tc\\bgi");
      maxx = getmaxx();
      maxy = getmaxy();
      rectangle(0, 20, maxx, maxy-20);
      setviewport(1, 21, maxx-1, maxy-21, 1);
      if(mousestart() == 0)
      {
            closegraph();
            restorecrtmode();
            printf("\nMouse driver not loaded");
            exit(1);
      }
      boundpointer(1, 21, maxx-1, maxy-21);
      showpointer();
      getch();
      closegraph();
      restorecrtmode();
}

int mousestart()
{
      in.x.ax = 0;
      int86(0x33, &in, &out);
      return(out.x.ax);
}

void showpointer()
{
      in.x.ax = 1;
      int86(0x33, &in, &out);
}

void boundpointer(int x1, int y1, int x2, int y2)
{
      in.x.ax = 7;
      in.x.cx = x1;
      in.x.dx = x2;
      int86(0x33, &in, &out);

      in.x.ax = 8;
      in.x.cx = y1;
      in.x.dx = y2;
      int86(0x33, &in, &out);
}

Compile and execute this program. Output will be a rectangle or window, in which mouse pointer shows up. Move the mouse pointer. You will see that mouse pointer moves within this rectangular boundary or box and does not cross the boundaries.

In this program, I have declared three functions. The task of first function is to check whether mouse driver is loaded or not. Second function does the task of showing mouse pointer in a user-defined window. Third function restricts the movement of mouse pointer in this window. These functions are defined after the function main().

int mousestart();
void showpointer();
void boundpointer(int x1, int y1, int x2, int y2);

In the start, I have declared two variables ‘in’ and ‘out’ of type union REGS. I have told you about union REGS in my previous post. Here is a quick revision.

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;
};

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

Thus, union REGS is a user-defined data type, which contains two struct WORDREGS and BYTEREGS variables ‘x’ and ‘h’. What is the use of these union variables, you will see later. These structures and union are defined in dos.h file.

In the function main(), I have obtained maximum screen coordinates and stored these in  variables ‘maxx’ and ‘maxy’.

maxx = getmaxx();
maxy = getmaxy();

I have drawn a rectangle, in which mouse pointer will move.

rectangle(0, 20, maxx, maxy-20);

Then, I have defined the user-defined view-port.

setviewport(1, 21, maxx-1, maxy-21, 1);

Function setviewport() establishes a new view-port for graphics output.

Declaration:

void far setviewport(int left, int top, int right, int bottom, int clip);

Where (left, top) is the upper-left corner, and (right, bottom) is the bottom-right corner of the view-port. The ‘clip’ argument determines whether drawings are clipped or truncated at the current view-port boundaries. If ‘clip’ is non-zero, all drawings will be truncated to the current view-port. The current position (C.P.) moves to (0, 0) in the new window.

Syntax for calling this function is given below-

setviewport(left, top, right, bottom, clip);

Therefore, whatever you draw beyond these boundaries, will not be drawn on the screen, because value of ‘clip’ has been given 1.

Now, an ‘if’ construct checks whether mouse driver has been installed or not. If installed, take further actions, otherwise exit. To check the availability of mouse driver, a function mousestart() has been called.

int mousestart()
{
      in.x.ax = 0;
      int86(0x33, &in, &out);
      return(out.x.ax);
}

To understand this function, please recall from the previous post.

Interrupt : 33h
Service : 0
Call with AX = 0
Returns
AX = 0000 (if mouse driver is not installed)
AX = FFFFh (if mouse driver is installed)

Thus, in the function mousestart(), I have given the value 0 (service number = 0) to the element  ‘ax’ of structure WORDREGS, now ‘x’ is the element of type struct WORDREGS in the union REGS, and ‘in’ is the variable of type union REGS. To refer ‘ax’, I have given the full notation like this- in.x.ax.

in.x.ax = 0;

Then, I have called the function int86() and passed the interrupt number 33h, and addresses of variables ‘in’ & ‘out’. After execution, this function returns the value of register ‘ax’ in the variable ‘out’. If it is 0, it means driver not loaded. If value of out.x.ax is FFFFh, it means driver is loaded.

return (out.x.ax);

Now, control returns to function main().  I assume that mouse driver is loaded. In the function main(), function boundpointer() is called. 

void boundpointer(int x1, int y1, int x2, int y2)
{
      in.x.ax = 7;
      in.x.cx = x1;
      in.x.dx = x2;
      int86(0x33, &in, &out);

      in.x.ax = 8;
      in.x.cx = y1;
      in.x.dx = y2;
      int86(0x33, &in, &out);
}

To understand this function, please recall the services from the previous post. These are given below-

Service : 7
Sets horizontal limits for pointer
Call with AX = 7
CX = minimum x coordinate
DX = maximum x coordinate
Returns nothing
à Restricts mouse horizontal movement to window
à If min value is greater than max value they are swapped

Service : 8
Sets vertical limit for pointer
Call with AX = 8
CX = minimum y coordinate
DX = maximum y coordinate
Returns nothing
à Restricts mouse vertical movement to window
à If min value is greater than max value they are swapped

Therefore, to restrict the horizontal movement, we call service 7 under interrupt 33h.

in.x.ax = 7;

To give the horizontal bounds, we have given the values to ‘cx’ and ‘dx’ variables as given below-

in.x.cx = x1; // minimum horizontal bound
in.x.dx = x2; // maximum horizontal bound

Then, we have called the function int86(). This function takes the action.

int86(0x33, &in, &out);

The same way, to give the vertical bounds, we have given the instructions given below-

in.x.ax = 8; // for vertical bounds give service 8
in.x.cx = y1; //minimum vertical bound
in.x.dx = y2; // maximum vertical bound
int86(0x33, &in, &out); // execute the service

Now, for showing the pointer, function showpointer() has been called.

void showpointer()
{
      in.x.ax = 1;
      int86(0x33, &in, &out);
}

This time, service 1 is executed available under interrupt 33h. Please recall from previous post.

Service : 1
Shows mouse pointer
Call with AX = 1
Returns nothing

Therefore, this way mouse pointer is displayed and restricted in the given boundaries. To understand this program better, please refer my previous post.

OUTPUT: