Sam Trenholme's webpage
This article was posted to the Usenet group alt.hackers in 1995; any technical information is probably outdated.

Re: executing interrupts from C...?

Article: 7486 of alt.hackers
From: Ralf Brown <>
Newsgroups: alt.msdos.programmer,alt.hackers
Subject: Re: executing interrupts from C...?
Followup-To: alt.msdos.programmer
Date: 6 Mar 1995 16:42:34 GMT
Organization: Just me and my PC....
Lines: 94
Approved: Hackers don't need anyone else's approval!
Message-ID: 2f59e9ac@ralf
In-Reply-To: <3jbtif$>
Originator: ralf@B.GP.CS.CMU.EDU
Status: RO

[alt.hackers: ObHack follows below; followups set to alt.msdos.programmer only]

In article <3jbtif$>, (Ethan
Rohrer) wrote:
}I am writing some C code which will need to execute a software interrupt
}or two.  I am trying to choose between two implementations (but will
}listen to any other good ideas out there...)
}1. use the register pseudo-variables and geninterrupt()
}      _AX = 0x1012;
}      _BX = 0x0000;
}      _CX = 0x0100;
}      _ES = FP_SEG(table);
}      _DX = FP_OFF(table);
}      geninterrupt(0x10);
}2. use the clunky union REGS and struct SREGS with int86x()
}      union  REGS   gen_regs;
}      struct SREGS  seg_regs;
}      ...
} = 0x1012;
}      int86x(0x10, &gen_regs, &gen_regs, &seg_regs);
}I prefer the first implementation, but I thought I heard somewhere
}that you could only use the register pseudo variables to directly
}access the registers if those registers aren't currently in use by
}the compiler.  Is this true?  If it is, it would seem to indicate
}that the first implementation won't always work as desired.

You can use any of the registers, but if you are not VERY careful, the
compiler will stomp all over them....  For instance, in your example
above, the compiler will most likely clobber AX when it loads ES.  The
compiler is smart enough not to use SI or DI for register variables if
you use their pseudovariables, but that is about all.

Probably the biggest drawback of using the pseudovariables is that it
makes the code non-portable (as far as I know, Borland's is the *only*
compiler supporting that feature).  So here's a hack I came up with some
years ago (1988) to make the pseudovariables portable, though I have not
previously published it because I wound up rewriting the affected code
in assembler.

ObHack: (for alt.hackers)

---begin file register.h---

#ifdef __TURBOC__
#  define USES_REG
#  define USES_REG  union REGS reg ; struct SREGS sreg ;
#  define _AH reg.h.ah
#  define _AL
#  define _BH
#  define _BL
#  define _CH
#  define _CL
#  define _DH reg.h.dh
#  define _DL reg.h.dl
#  define _AX
#  define _BX reg.x.bx
#  define _CX
#  define _DX reg.x.dx
#  define _SI
#  define _DI reg.x.di
#  define _DS sreg.ds
#  define _ES
#  define _SS
#  define geninterrupt(n)  int86x(n,&reg,&reg,&sreg)

---end file register.h---

Usage in your code:

   #include "register.h"

   int getkey()

      _AH = 0x10 ;
      geninterrupt(0x16) ;
      return _AX ;

Now, when compiling under Turbo/Borland C/C++, you get the efficiency of
the register pseudovariables, and when compiling under a different MS-DOS
compiler, you get the far more portable int86(), without having to change
your code or using ugly #ifdefs.

Internet: RALF+@CS.CMU.EDU  | The University would disclaim this if it knew...
FIDO: Ralf Brown 1:129/26.1 | "Determine that the thing can and shall
be done,
BIT: RALF%CS.CMU.EDU@MITVMA | and then we shall find the way." Abraham

Back to index