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,®,®,&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