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 <ralf@telerama.lm.com>
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
NNTP-Posting-Host: b.gp.cs.cmu.edu
In-Reply-To: <3jbtif$meo@ucsbuxb.ucsb.edu>
Originator: ralf@B.GP.CS.CMU.EDU
Status: RO

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

In article <3jbtif$meo@ucsbuxb.ucsb.edu>, nuthing@mcl.ucsb.edu (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;
}      ...
}      gen_regs.x.ax = 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
#else
#  define USES_REG  union REGS reg ; struct SREGS sreg ;
#  define _AH reg.h.ah
#  define _AL reg.h.al
#  define _BH reg.h.bh
#  define _BL reg.h.bl
#  define _CH reg.h.ch
#  define _CL reg.h.cl
#  define _DH reg.h.dh
#  define _DL reg.h.dl
#  define _AX reg.x.ax
#  define _BX reg.x.bx
#  define _CX reg.x.cx
#  define _DX reg.x.dx
#  define _SI reg.x.si
#  define _DI reg.x.di
#  define _DS sreg.ds
#  define _ES sreg.es
#  define _SS sreg.ss
#  define geninterrupt(n)  int86x(n,&reg,&reg,&sreg)

---end file register.h---

Usage in your code:

   #include "register.h"

   int getkey()
   {
      USES_REG

      _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
Lincoln



Back to index