Xref: utzoo comp.os.msdos.programmer:127 comp.sys.ibm.pc.programmer:2416 alt.msdos.programmer:1889 Path: utzoo!attcan!uunet!dino!ux1.cso.uiuc.edu!iuvax!maytag!watserv1!broehl From: broehl@watserv1.waterloo.edu (Bernie Roehl) Newsgroups: comp.os.msdos.programmer,comp.sys.ibm.pc.programmer,alt.msdos.programmer Subject: Re: More "Far Call in C" Message-ID: <1990Jul17.145927.2711@watserv1.waterloo.edu> Date: 17 Jul 90 14:59:27 GMT References: <1990Jul9.195959.13596@ariel.unm.edu> Distribution: na Organization: University of Waterloo Lines: 61 In article <1990Jul9.195959.13596@ariel.unm.edu> saunders@hydra.unm.edu writes: >Here is an example from the XMS docs: > > mov ax,4310h ; XMS int 2fh signiture > int 2Fh > mov word ptr [XMSControl],bx ; XMSControl is a DWORD > mov word ptr [XMSControl+2],es > ; We now have the XMS API entry point > ; then we'de call an XMS function like this: > mov ah,00h ; function code for "Get XMS version number" > call [XMSControl] There are a couple of ways of doing this. In Turbo C 2.00: #include void far (*xmsfn)(); ... union REGS r; struct SREGS s; r.x.ax = 0x4310; int86x(0x2F, &r, &r, &s); xmsfn = MK_FP(s.es, r.x.bx); /* We now have the XMS API entry point */ _AX = 0; (*xmsfn)(); Note that in Turbo C (and presumably other C's), no registers are used in do the (*xmsfn)(); that line of code becomes the single instruction "call dword ptr DGROUP:_xxx" (assuming the xxx is declared globally, which it should be). Thus you can load up the _AX, _BX etc registers with whatever you like before the call, and (if you're careful) get most of them after the call. Not real elegant, but it works. The other way to do it is: #include void interrupt (*xmsfn)(); /* Note interrupt, not far */ int xxx = 0x??; /* pick some unused interrupt vector */ ... union REGS r; struct SREGS s; r.x.ax = 0x4310; int86x(0x2F, &r, &r, &s); xmsfn = MK_FP(s.es, r.x.bx); setvect(xxx, xmsfn); r.h.ah = 0; int86x(xxx, &r, &r, &s); The advantage to this approach is that it makes no assumptions about what code is generated by the compiler, and the technique should work similarly under any reasonable C compiler; the disadvantage is that you have to find one interrupt vector that you *know* isn't being used for anything else. (It would be very nice if there were a "standard" vector for this purpose; the best you can do is search (say, starting at 0x60 or so) for vectors pointing to an IRET instruction). -- Bernie Roehl, University of Waterloo Electrical Engineering Dept Mail: broehl@watserv1.waterloo.edu OR broehl@watserv1.UWaterloo.ca BangPath: {allegra,decvax,utzoo,clyde}!watmath!watserv1!broehl Voice: (519) 747-5056 [home] (519) 885-1211 x 2607 [work]