BIOS (Basic I/O System) Interrupts

14.2 BIOS (Basic I/O System) Interrupts

All MS-DOS computers have some basic routines stored in read-only memory in the computer. These routines provide a mechanism for communicating with the keyboard and screen, amongst others, and hence this part of memory is given the title BIOS (Basic Input/Output System). The BIOS can be thought of as coming between our C programs and the hardware of the computer itself. When we use a printf statement in our program, the compiler produces machine code which calls a subroutine in the BIOS to make characters appear on the computer screen. So generally we need not trouble ourselves with trying to understand exactly how the BIOS works.

OUCS

58 October 1996 58 October 1996

Examples include communicating with serial/parallel ports, video card control (scrolling, writing, reading etc.), disk access, keyboard access (read key states, is a key waiting to be read, changing auto-repeat delay etc.) and many others. Remember C is supposed to be a portable language, and the examples given above are all specific to the IBM PC and the 8086 processor. Some versions of C do provide access to some of these routines via library functions.

All MS-DOS C compilers do provide a mechanism for calling BIOS routines directly though. Armed with a good guide to the BIOS routines (like Peter Norton's Programmers Guide To The IBM PC [4]) we can make our PC sing and dance at lightning speed.

I give some simple examples below, but for more information I suggest you consult [4]. The program below will move the cursor to any valid screen location - any subsequent

screen output will start at this point. #include <dos.h>

void GotoXY(int x, int y) /* positions cursor at line y, column x */

{ union REGS regs;

regs.h.ah = 2; regs.h.dh = y; regs.h.dl = x; regs.h.bh = 0; int 6(0x10, ®s, ®s); }

The int86 function copies the variable regs into the processor registers, executes the BIOS interrupt (routine) specified – in this case 0x10 (the video interrupt) - and then copies the processor registers into regs again. Modifying regs does not change the processor registers directly.

The following program will set the attribute bits of a given file.

October 1996

59 OUCS

Programming in C l9.2/2 #include <stdio.h>

#include <dos.h> int attrib(char *, int); int main(int argc, char *argv[])

{ int

attributes; if (argc != 3)

{ fprintf(stderr, "USAGE:

%s attributes filename\n", argv[0]);

fprintf(stderr, "

eg: %s 33 fred.c\n", argv[0]);

would set archive & read- only ");

fprintf(stderr, "

fprintf(stderr, "

attributes of fred.c\n");

return 1; }

if ((attributes = atoi(argv[1])) > 0xFF) /* atoi converts an ASCII string to an int */

{ fprintf(stderr, "ERROR: invalid attributes %d\n",

attributes);

return 2; }

switch (attrib(argv[2],attributes))

{ case 0 : /* OK */

break;

case 2 : fprintf(stderr,"ERROR: file %s not found\n",argv[2]);

return 3;

case 3 : fprintf(stde rr,"ERROR: path %s not found\n",argv[2]);

return 4;

case 5 : fprintf(stderr,"ERROR: access denied on file %s\n",

argv[2]); return 5; } return 0; }

int attrib(char *filename,int attributes) { union REGS regs;

regs.x.dx = (int) filename; regs.x.cx = attributes; regs.h.al = 1; regs.h.ah = 67; int86(0x21, ®s, ®s); return regs.x.ax; }

OUCS

60 October 1996 60 October 1996

realising it (these can be discovered with a small findfirst / findnext program or with dir/ah in DOS 5 or higher).