[alt.msdos.programmer] More "Far Call in C"

saunders@hydra.unm.edu (07/10/90)

   MSDOS/8086 gurus:

   Thanks for the responses.  Alas, most weren't what I needed.  I'll come
clean right away: I am totally incompetent at 8086 assembly language!  The
Novell IPX/SPX and Microsoft XMS interfaces are CALLed, but with parms in
the registers.  Sort of a cross between a normal function call and a DOS
"int 21h" call.  Both IPX/SPX and XMS hook into "multiplex interrupt" 2fh
and return their main address for the API (damn all these TLAs!) in ES:DI
or ES:BX.  Then, Joe-Assembly-Programmer would just store the result 
someplace and make indirect jumps through it.  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]

   Notice how weird that is.  It's neither a int86() call nor a normal
function call.  What I need is a general-purpose routine kind of like
int86x(), but I'm unable to write one.  e.g.
    void farcall(void far *api_entry, 
                 union REGS regstuff,
                 struct SREGS sregstuff);
   I hear some of the mega-optimizing compilers have ways of declaring
functions that take register parms, but I need something for MIX or MSC.

      -- Rich Saunders

shields@yunexus.YorkU.CA (Paul Shields) (07/11/90)

In article <1990Jul9.195959.13596@ariel.unm.edu>, saunders@hydra.unm.edu writes:
>    MSDOS/8086 gurus:
> 
>    Thanks for the responses.  Alas, most weren't what I needed.  I'll come
> clean right away[...explanation deleted...]
> 
>       -- Rich Saunders

Well, it took a couple hours, but here is the result that I think will
work:
	call86() and call86x()

They're analogous to the int86() and int86x() calls (which were built
for microsoft C and a few other compilers.)  I've tested them a little
on MSC 5.1 and they seem to handle registers properly.  Since I don't
have the network software that Rich writes about I can't give them a
throrough test.  Anyway, here they are.  I've increased the
distribution from "na" to world since it could be useful to others,
and included the .obj and .exe files as a uuencoded zip file (just for
completeness.)

Paul Shields
shields@nccn.yorku.ca

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  COPYRIGHT REQUEST build.bat call86.asm call86.c call86.h
#   objects.z.uue test.c
# Wrapped by shields@yunexus on Wed Jul 11 03:58:28 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'COPYRIGHT'\"
else
echo shar: Extracting \"'COPYRIGHT'\" \(483 characters\)
sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE'
XCopyright 1990 by Paul A. Shields.  This software may be distributed
Xand used in other works free of charge provided that all source code
Xversions of this software and its derivatives contain this copyright
Xnotice and license.  As this software is distributed in source code
Xform, the author shall not be held responsible for damages resulting
Xfrom its use.  If the software fails to perform as specified, you
Xassume all costs of servicing it or repairing damages that it may
Xcause.
END_OF_FILE
if test 483 -ne `wc -c <'COPYRIGHT'`; then
    echo shar: \"'COPYRIGHT'\" unpacked with wrong size!
fi
# end of 'COPYRIGHT'
fi
if test -f 'REQUEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'REQUEST'\"
else
echo shar: Extracting \"'REQUEST'\" \(2144 characters\)
sed "s/^X//" >'REQUEST' <<'END_OF_FILE'
XPath: yunexus!geac!torsqnt!news-server.csri.toronto.edu!rutgers!mephisto!ncar!unmvax!ariel.unm.edu!hydra.unm.edu!saunders
XFrom: saunders@hydra.unm.edu
XNewsgroups: comp.os.msdos.programmer,comp.sys.ibm.pc.programmer,alt.msdos.programmer
XSubject: More "Far Call in C"
XMessage-ID: <1990Jul9.195959.13596@ariel.unm.edu>
XDate: 9 Jul 90 19:59:59 GMT
XArticle-I.D.: ariel.1990Jul9.195959.13596
XPosted: Mon Jul  9 15:59:59 1990
XSender: usenet@ariel.unm.edu (USENET News System)
XDistribution: na
XOrganization: University of New Mexico, Albuquerque
XLines: 32
XXref: yunexus comp.os.msdos.programmer:48 comp.sys.ibm.pc.programmer:2523 alt.msdos.programmer:1771
X
X
X   MSDOS/8086 gurus:
X
X   Thanks for the responses.  Alas, most weren't what I needed.  I'll come
Xclean right away: I am totally incompetent at 8086 assembly language!  The
XNovell IPX/SPX and Microsoft XMS interfaces are CALLed, but with parms in
Xthe registers.  Sort of a cross between a normal function call and a DOS
X"int 21h" call.  Both IPX/SPX and XMS hook into "multiplex interrupt" 2fh
Xand return their main address for the API (damn all these TLAs!) in ES:DI
Xor ES:BX.  Then, Joe-Assembly-Programmer would just store the result 
Xsomeplace and make indirect jumps through it.  Here is an example from the
XXMS docs:
X
X         mov   ax,4310h                    ; XMS int 2fh signiture
X         int   2Fh
X         mov   word ptr [XMSControl],bx    ; XMSControl is a DWORD
X         mov   word ptr [XMSControl+2],es
X         ; We now have the XMS API entry point
X         ; then we'de call an XMS function like this:
X         mov   ah,00h      ; function code for "Get XMS version number"
X         call  [XMSControl]
X
X   Notice how weird that is.  It's neither a int86() call nor a normal
Xfunction call.  What I need is a general-purpose routine kind of like
Xint86x(), but I'm unable to write one.  e.g.
X    void farcall(void far *api_entry, 
X                 union REGS regstuff,
X                 struct SREGS sregstuff);
X   I hear some of the mega-optimizing compilers have ways of declaring
Xfunctions that take register parms, but I need something for MIX or MSC.
X
X      -- Rich Saunders
X
END_OF_FILE
if test 2144 -ne `wc -c <'REQUEST'`; then
    echo shar: \"'REQUEST'\" unpacked with wrong size!
fi
# end of 'REQUEST'
fi
if test -f 'build.bat' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'build.bat'\"
else
echo shar: Extracting \"'build.bat'\" \(50 characters\)
sed "s/^X//" >'build.bat' <<'END_OF_FILE'
Xmasm /Ml call86.asm;
Xcl -AL -Zi test.c call86.obj
END_OF_FILE
if test 50 -ne `wc -c <'build.bat'`; then
    echo shar: \"'build.bat'\" unpacked with wrong size!
fi
# end of 'build.bat'
fi
if test -f 'call86.asm' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'call86.asm'\"
else
echo shar: Extracting \"'call86.asm'\" \(2512 characters\)
sed "s/^X//" >'call86.asm' <<'END_OF_FILE'
X; Author: Paul A. Shields
X; Hand-coded from MSC 5.1 output of call86.c stub.
X; July 11, 1990
X
X	TITLE   call86.c
X	NAME    call86
X
XCALL86_TEXT	SEGMENT  WORD PUBLIC 'CODE'
XCALL86_TEXT	ENDS
X_DATA	SEGMENT  WORD PUBLIC 'DATA'
X_DATA	ENDS
XCONST	SEGMENT  WORD PUBLIC 'CONST'
XCONST	ENDS
X_BSS	SEGMENT  WORD PUBLIC 'BSS'
X_BSS	ENDS
XDGROUP	GROUP	CONST, _BSS, _DATA
X	ASSUME  CS: CALL86_TEXT, DS: DGROUP, SS: DGROUP
XEXTRN	__acrtused:ABS
XCALL86_TEXT      SEGMENT
X	ASSUME	CS: CALL86_TEXT
X; Line 24
X	PUBLIC	_call86
X_call86	PROC FAR
X	push	bp
X	mov	bp,sp
X	push	si
X;	addr = 6
X;	inreg = 10
X;	outreg = 14
X
X;inreg
X	les	bx,DWORD PTR [bp+10]
X	push	WORD PTR es:[bx]        ; ax
X	mov	ax,WORD PTR es:[bx+2]   ; bx
X	mov	cx,WORD PTR es:[bx+4]   ; cx
X	mov	dx,WORD PTR es:[bx+6]   ; dx
X	mov	si,WORD PTR es:[bx+8]   ; si
X	mov	di,WORD PTR es:[bx+10]  ; di
X        mov     bx,ax
X        pop     ax
X
X        call    DWORD PTR [bp+6]        ; addr
X        pushf
X; outreg
X        push    ax
X        mov     ax,bx
X	les	bx,DWORD PTR [bp+14]	;outreg
X	mov	WORD PTR es:[bx+10],di  ; di
X	mov	WORD PTR es:[bx+8],si   ; si
X	mov	WORD PTR es:[bx+6],dx   ; dx
X	mov	WORD PTR es:[bx+4],cx   ; cx
X	mov	WORD PTR es:[bx+2],ax   ; bx
X	pop	WORD PTR es:[bx]        ; ax
X	pop	WORD PTR es:[bx+12]     ; cflags
X; Line 33
X	pop	si
X	pop	bp
X	ret	
X	nop	
X
X_call86	ENDP
X; Line 39
X	PUBLIC	_call86x
X_call86x	PROC FAR
X	push	bp
X	mov	bp,sp
X	push	si
X;	addr = 6
X;	inreg = 10
X;	outreg = 14
X;	segreg = 18
X
X        push    ds                      ; save ds
X
X	les	bx,DWORD PTR [bp+18]	;segreg
X	mov	ds,WORD PTR es:[bx+6]   ; ds
X	push    WORD PTR es:[bx]        ; es
X
X	les	bx,DWORD PTR [bp+10]
X	push	ax,WORD PTR es:[bx]     ; ax
X	mov	ax,WORD PTR es:[bx+2]   ; bx
X	mov	cx,WORD PTR es:[bx+4]   ; cx
X	mov	dx,WORD PTR es:[bx+6]   ; dx
X	mov	si,WORD PTR es:[bx+8]   ; si
X	mov	di,WORD PTR es:[bx+10]  ; di
X        mov     bx,ax
X        pop     ax
X        pop     es
X
X        call    DWORD PTR [bp+6]        ; addr
X        pushf
X        push    ax
X        mov     ax,bx
X
X        push    es
X	les	bx,DWORD PTR [bp+18]	;segreg
X	mov	WORD PTR es:[bx+6],ds   ; ds
X	pop     WORD PTR es:[bx]        ; es
X
X	les	bx,DWORD PTR [bp+14]	;outreg
X	mov	WORD PTR es:[bx+10],di  ; di
X	mov	WORD PTR es:[bx+8],si   ; si
X	mov	WORD PTR es:[bx+6],dx   ; dx
X	mov	WORD PTR es:[bx+4],cx   ; cx
X	mov	WORD PTR es:[bx+2],ax   ; bx
X
X	pop	WORD PTR es:[bx]        ; ax
X	pop	WORD PTR es:[bx+12]     ; cflags
X
X        pop     ds                      ; restore ds
X        pop     si
X	pop	bp
X	ret	
X	nop	
X
X_call86x	ENDP
XCALL86_TEXT	ENDS
XEND
END_OF_FILE
if test 2512 -ne `wc -c <'call86.asm'`; then
    echo shar: \"'call86.asm'\" unpacked with wrong size!
fi
# end of 'call86.asm'
fi
if test -f 'call86.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'call86.c'\"
else
echo shar: Extracting \"'call86.c'\" \(1216 characters\)
sed "s/^X//" >'call86.c' <<'END_OF_FILE'
X/* call86.c - "stub" for calling an assembly language function from C.
X
X   Author: Paul A. Shields
X   Date: July 11, 1990
X   Features: Function calls were built to be analogous to
X             Microsoft C 5.x functions int86() and int86x().
X
X   **** NOTE! this file is provided for completeness only!
X      it is a stub which will not work as coded.
X      To make this work, I compiled as follows:
X
X         cl -AL -Ox -Fa call86.c -c 
X
X      then edited the assembly output file as needed to insert
X      the proper code into the stubs.
X */
X
X#include <dos.h>
X#include "call86.h"
X
X/* w/o setting up segment registers: */
Xint call86(void far *addr,union REGS *inreg,
X            union REGS *outreg)
X{
X	outreg->x.ax = inreg->x.ax;
X	outreg->x.bx = inreg->x.bx;
X	outreg->x.cx = inreg->x.cx;
X	outreg->x.dx = inreg->x.dx;
X	outreg->x.si = inreg->x.si;
X	outreg->x.di = inreg->x.di;
X	outreg->x.cflag = inreg->x.cflag;
X
X   return inreg->x.ax;
X}
X
X/* with setting up segment registers: */
Xint call86x(void far *addr,union REGS *inreg,
X            union REGS *outreg, struct SREGS *segreg)
X{
X	outreg->x.ax = segreg->es;
X	outreg->x.bx = segreg->cs;
X	outreg->x.cx = segreg->ss;
X	outreg->x.dx = segreg->ds;
X   return inreg->x.ax;
X}
END_OF_FILE
if test 1216 -ne `wc -c <'call86.c'`; then
    echo shar: \"'call86.c'\" unpacked with wrong size!
fi
# end of 'call86.c'
fi
if test -f 'call86.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'call86.h'\"
else
echo shar: Extracting \"'call86.h'\" \(277 characters\)
sed "s/^X//" >'call86.h' <<'END_OF_FILE'
X/* call86.h - protoype statements for call86.c
X   Author: Paul A. Shields
X
X   built to be analogous to Microsoft C 5.x functions int86() and
X   int86x(). 
X */
X
Xint call86(void far *,union REGS *,union REGS *);
Xint call86x(void far *,union REGS *,union REGS *, struct SREGS *);
END_OF_FILE
if test 277 -ne `wc -c <'call86.h'`; then
    echo shar: \"'call86.h'\" unpacked with wrong size!
fi
# end of 'call86.h'
fi
if test -f 'objects.z.uue' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'objects.z.uue'\"
else
echo shar: Extracting \"'objects.z.uue'\" \(6122 characters\)
sed "s/^X//" >'objects.z.uue' <<'END_OF_FILE'
Xbegin 600 objects.zip
XM4$L#!`H````&`-(;ZQ24+R0@)P$``&8!```*````0T%,3#@V+D]"2@\`$@,D
XM%38G.#EJ>TR=;A\)!@$3-.7VEO<!,P2H<&Q8MFQQVG09=F[;^)9I2&^0Z%&I
XM3ZM"'2ATZE2"1(-2#4IPZ%.B10E^<?:%0X,R99+^5ZI%L5(M^&5;"VSO="K5
XMU)@/`D3:&N#!@@&_)(O0(R08D$$RG3!A0`/)M,&!`1]J1@A0X/^!_PG^%VB5
XM<0.\__HU[%BY=.O.+4L6(%'(&L0/>/#+4A16CD"9Q*MD>=F("1`O.F!TT+'$
XM0[[J8O96B7M5:/+_39.+CPH8_BF!X:\:&/XN@N'_*ER,'>M_KP8Y0UT\;'R'
XM)A-!-QRV)P+W1.B>"-X?'Q#^*$.O79=#2EH]F"_1I..O!IPVJG7Q02A5`_6`
XMU:0!>&4$;T<7-B!_$%M9*A80UW102P,$"@````8`UAOK%)<-BO1+`P``Q`4`
XM``@```!415-4+D]"2@\`$@,D%38G.#EJ>TR=;A\)!@$3-.7VEO<!(P1HD&[9
XMN71=C@V)^,"S-YT*<JA;Q`F0_\R4:5*A0XN61&Q@^<XPV3Y5AZRA`PZU>M.R
XM%.0-$CTJ]6E5J`FI%IU*]0OQ6*D2'/J4:-&"7XD&I1J4`+$6>-Z)]@2_"ITZ
XM=<"P'R1)DFI6*.S=7U0(LB=P?FK6ID*?,H%FRAX>$]\C-0IP(,&`RY(%[`L:
XM#-@@F3YX,*""9!IAPH`'DATD68`,&P8<EJP%!RI<&'"DIB$O\/_`_P3_"[3*
XMN8'Y`P,*%!@@Z8$&+!H0...6`!5^_1IVK%RZ=>>6N1_AU[%AV;+%:1,/^5_-
XMUB'[KVW#IG53;=:C73.DUP(\#;G"_P&V.4#!=[QI!\GKC8B8`/2B`T8';6$^
XMY",&&/ZN@"#B!`6TGYV3]=3Z?B!,T!(!<'O5Q>QG`M?$K8O+=UW.A=N9&[1:
XM4"9H%OV(JE<0;/W46T^8=CW32`)WZT].19BZ1:L$KE;TH!]<O8.K%3=*`%AS
XM?E3K`:J/"9H'U:.XVA=0^T*"\O\G%%A@?[EESS(D2&[9#;ZM2X>98__/@#DA
XM?8;9R@?_OTSY9MW"T9X%7C3!EZ#0=,",`(\;!0^`V,41W]@H=HM0B"='K/*(
XMQQ6]+N&E0MF;#R8.\3LG-,U<I%6!R#MP-74-PR-'<.P#AE\)JO0N"$;I!<I#
XMEC>?HGU073B@$"3QOJ`Q3$\1`)MIG`#<7@B;T5^.0MF[F'^'3_E"$MS`DZQ(
XMX7D&[%;\2(`/Y-TPZ(0#%,<#%#V@8135YX5[<-`2'UQ0H&"$5Y]*)2JUZ-&I
XM:0.TX;^#"P,0!CF@"^P%"PR+%Y'F+U!,<?,+'%,\@>+)%&^@^+EI$2-8MN(5
XM"BXXUBS;L&<1,P!;@2(<?`#L$8#M0K/$=F#3&<!VP@"$@0T88VS.9FP-BQ9Q
XM@+2=3=HJ9OD!;SN;MZ5V1UP@;6=3MY)9#K6'<&0;>P7"+TB?@-CT`;%]`/0&
XM)/L%4'N`N32`>EX?(2HG.+A!]@[4+SAEG6[P9@BO!.LX/:%T[!R^=>X<,[/B
XM#?@):AGP?\,P;UCOG#VZ(-"!&`:`VZWK`@YT*P^*9)/&%4C[X,``J'EQ18;B
XM=%!+`P0*````!@#8&^L4&G"2D:4+``"$%```"````%1%4U0N15A%#P`2`R05
XM-B<X.6I[3)UN'PD&`1,TY?:6]YMJC0S0($",`$$"#`SP_W]%T"-D'YPBP(<`
XM/6Q[`.:*_<*P]QAV&\,>8M@5`G0+\$.X_QCV(\/^:-@I#7NF8;<U[+R&'=BP
XM5QMV;<,NZMWY!SC>KH#A%0T[M&'/-NPY"S[@`^#_@@$76'4Q^YG`-5MZ@B\N
XMWW59L^-&"<"9'S<*'@"QBR.^L5'L%J$03XY8Y1&/*WI=PDN%JADJ0((`!Q.'
XM<$]:)>Y5H<G_-TTN/BI@^*<$AK]J8/B["(;_JW`Q=JS_O1KD#'7QL/$=FDP$
XMW7#8G@C<$Z%[(GA_?$#XHPR](#VDI-6#^1)-.OYJP&FC6A<?A%(U4`]831J`
XM5T;P=G1A`_('L65(H&G#;!Z2I\"Y`IN#_*W&2-L4"'#E_<#^`4*4.]`7\?H=
XM7P],W'_`_7,I6ORHF<V5K$WE^1>ZX[C_,ZE_,'G_-A.;1`J`V(GD;SPVP>G@
XMD=H<+13@P/N)C';&PU=ZO[^=MI+S;3+VF!N@Q8/\?\L/<+S`E<^(?KZJIQTQ
XM@:/7#(YJUVP/M0SZF>W_V_1F&-OD-NS:AAW;L%OCWL%81O?!!M.'XP)KQ]AQ
XM#X#[XP:-`HBN30ZE*B85MQG8AUU;MU[W(%:H-O];%!A`K.QW@+R1,-.C=\TU
XMP!K')_9X*JL-I@;H\(/S)77_!A`=WB]VZ##@>)>.#7!5%K?)$F!Q@Q`#,M8^
XM<UO1>V08<&Z![]-?#6B#>@K4OFMOJY;IVFD'[8^WZ3CXS/\F`9':=%GF9@C0
XMMV:`\TW379C[_Y\R+]]UW8SKRQOT>"#L[_\6#I`UYLBL_0.G&Q"I:O'W@'Z7
XM[PWX%/6_C)K(4,M5:%\X8+H%`3^"'NC2O.=]8PSX2WCTJ`$@DY\!+C=NT!WL
XMOGZ`G-U7$4.BHU_$C0L&@&>2`)LG&$"<RJ;1B.-?PK0N,_D"OI=H[VBMNW"P
XM'UN^;@'0W@"91@?+47.Z!L:6M%]$/2W.-RKQ@[L.OS>KQ^(63_W)2UC_$;!/
XM=.33;>@1=#HT;5'=%IO6X3OOSW4X^#W!Q047%A5(5_[_CNO=#]M,Q<T?@.O1
XM@WW*HS>P]@@?@!5DFN66XO+Z]#C]9]6ZF/M*['(7[O2('Z#<@HO'2XVZ3/C0
XM])146!'Q]!C]_W>QO-69]G-E[C+)\V<M$[SX_8#I5Z4;0?<Y[@!.$\CN=?EC
XM@_HBX0;JKLT#Q&DA]J>;P@R,>!:S[^)XQS,U#X@-72$LO/_HT<0^1KTSU.SW
XMHR^._LM_7P-_1ZCCK'F"I+N?9T*Z]WDVI/M6@9Q>>]2)M**3=G+2SD7:L?(4
XM29<D3ZYT!PI=3WYF\J"LE%V?M!,<&'W]],7!HZ>?&!UUP+K*UP?`-_A7P/N)
XM;M<%3[.#![\-'BU]_27+BZID^X'7CT8_%YSQ0@&+][]2_&+BHQ0KP4RRFO4'
XM[C/,6O,?D/E5@8.'$RQN`\BS5N7U=?7IY3;VDMYOS*L",GS=@>D)`P#W@>O]
XM0KI'/)E;"W=I7KD8K]S+4G["*U7U9&B#L+F@QNNC%0=6Q\]I7@3SQ:3,7<R[
XM"G"_-4])&6:>SC9/6IK79E,9EC]^`!)-42*N\=>W>5KE+<&OSR].OSA_DMO4
XMA?;I0G1L+#'W`>MV=%:X2!G67_0R4)+^%_>/7B[X`:[[QZN_$P)H+/^Z^-GT
XM`_$G=LGM2B9K@>:.O7G>2<=?#,QSYU"Z"1/[J=[(F2].8$NT^/2)G0(07D#_
XM7617]E:K5^1?;-6@;Y`!6^\41O=`+=-E>(FL%H^EQNO76_[J)=V5"U#7J__M
XM&M1,L`!O<9"2%^LS)V3O))IEN(EHZ=,&@EA_L:<70Q]HH)*66S.G@=AY;HE]
XMAQH=>^R!T]$SSKYHSKYR^<#@CH<M?IFD6.5")`D?B2QYY<4NXK/4AL/^>'J3
XM^TXJZ*D@I=9UVY)JVK9E03)-*U9N6+EY0;8$.?0MW+QRTYY%@]4HQZ8$&3,G
XMSIPL039-.U;NV[EOS=+I=KEP(?1S<IL]0#4W&W`&9X7&OQI-RK3HUZ1.C3XY
XM!RQ-/7#@P`$#?`.1W%4^9!J<%PM.L%JF?06S>Y!Y\G0BI8_Z2#V7:A,F3)@-
XM%3#IN73#CET+\JW=LG+-LGU[)SJA;5MG;&M:MW3+GL$>)-FT=M.2">)B^)2\
XM`TP`SG.`J]LW;[H,\766V-'#.3KQS?`I:&MOB;N18_VU&Z5&;%@MQPA.QPCB
XM]'+&S>%$-)=!M-SM8;1W>Q8DW#=PV]0LVMZ>#+X',.<QUN9UV;(1IZ+RL'/G
XM`'YB8WAVIT+*CXZ`S+01-I,(J1:=2M7E4Z%*":Q8;T5-*AP:E"E3G#:L]8$9
XM/1R,9<,S),/[<PF\Z<)TD?5ML,-8UPV`33_`QLF,U3;52Y,$L`V^[=PSVS1D
XM@0:V2077:A:.-6U)'F4]VC5Q?(TUU8J;L(:MV\::TABCXAO&/;V7>];.-K4S
XMWL,WS+:UT<HF6G,QV[!NJG*T9.5LTV8+"MDF(4R--?&W8[BE2GI7X,"O9NO$
XM=-4KL.#7MF'(N`&3:,T?_#KFW-PTE&:.H)G$:\2R^,*O7\.6Q9N6[I<TMR(/
XM$*T,OT@[4:%S[\)YLOLC9]((T_\L)FE^(-H4X[5PD31S!,W4(R[$&:7YZR4[
XMQX$39R)T"GLBW2B.-YS5+6DZP3Y>]E<[>_8QG^=$DUKIU-JL"O9F<+:^MXL)
XM&L."UYW#N1.(BROPBC*R"H#F"Z!I.:3K<IU1S<PL2O0OX[H+SYC4P9:=56D_
XM*YH;_.)NN#,YEF3,LL[-L1E;TFG9D@76C+LUTWQ9>UGS`VZQ]*UMXU]0W\?J
XM#K"-%:WIMK$K&]C]33=HG@Q0#`VK6<Q]A6/2$>78EH:UR^L='-&]SRV)A&F0
XMPK"(A9>5]G)&MGW#N=]RQN9HDK%<!F-BSI;9X:7JV-%VV7C]6'#LZ+-MX=*5
XMJVD,Z#%99^??HGO&VHWQ#GOVU#=JRR:JONL;/0?+G-<S'%Y:&T`<"-1J\EYK
XM1W%>*2!-`NUCVF!BN*Y87^$XF26Q^5=!\P)OV5`'NR(OL`6>ZQJSLK,IFCM8
XMWJC1+YSD0H,Z=5I4*KRMT&3%GNE]\STZ@>]1SPZ)GB&)H?FP</$5'N6J+T4:
XM-2H]W,;#B#4=5C<W+]>2.^;KM"YG9K@VR2)=GEXK)#)1T@)87A;<.(O;DCP=
XMQ9<:(<_8K"L!!)C%6R30+ZH\5JHOHCF#:/*JU"34FY%F]-XVSZMS>7]@K6.-
XM[&$&8<Q*`/&<C,IS0,.HW#POW(.#"23T"PH4C/#J4ZE$I18].C4-R1K@W\&%
XM`0B#'-`%]H(%AL6+&$#Q8HJ;7^"8X@D43Z9X`\4I><0(EJUXA8(+CJE]1<P`
XM;`6*</`!L$<`M@O-8E9@TQG`MIJ4,+`!8XS-V8RM8=$B#I"VLTE;Q2P_X&UG
XM\[8<<<0%TG8V=2N9Y0\&A'!D&WL%PB](GX#8]`&Q?0#T!E;]!5![@+DT@'I>
XM'R$J)SBX0?8.U"\X99UN\&8(KP3KR\X12L?.X5L$;F9FQ1OP$]0RX/^&8=ZP
XMWCE[-!6RI@$G\-&O"S@P&<9?H`!IM`)I'T3`1\TC!D#80K!7$&R7Y0(@]@$%
XM3@SH0&([3@"\W\]6@@0TMA9H]A2Y.8$7\@0L.^?EB.09$B2W[`8.\G28.?;_
XM#)@SC<\P6_G@_Y<IWZP;4[.F"][`;O3KNQQ;(*(:0A*N9\"T%3_BX1O8KD"C
XMGE3HT*(NBIV#G.VI(HI6!."6[N#*`N,!R?ZS0*[X0`+)3L3;\KI`LJ-*]@[Q
XM+J#8DK\0;\E'#3!-/81I3'N&:4O>S;3GF[:&<9-IYS!MR9_9X)P:VV;U:::)
XMY'>X#*]Q;F5=Z&DB>3C3_F#:IC"G::(Q;=I?3)O?SYHFDG<U[22FK<LK>YI(
XM7MJT0YBV.6]NFDA>W#2YH-FFJ>3E37N)::O2'OKB`I+]PIL=Q9MZ]F)EMN=4
XM@LZ3>H!02P$""@`*````!@#2&^L4E"\D("<!``!F`0``"@```````````"``
XM````````0T%,3#@V+D]"2E!+`0(*``H````&`-8;ZQ27#8KT2P,``,0%```(
XM````````````(````$\!``!415-4+D]"2E!+`0(*``H````&`-@;ZQ0:<)*1
XMI0L``(04```(````````````(````,`$``!415-4+D5815!+!08``````P`#
X+`*0```"+$```````
X`
Xend
END_OF_FILE
if test 6122 -ne `wc -c <'objects.z.uue'`; then
    echo shar: \"'objects.z.uue'\" unpacked with wrong size!
fi
# end of 'objects.z.uue'
fi
if test -f 'test.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'test.c'\"
else
echo shar: Extracting \"'test.c'\" \(251 characters\)
sed "s/^X//" >'test.c' <<'END_OF_FILE'
X/* test.c - try to test call86() and call86x(). */
X
X#include <dos.h>
X#include "call86.h"
X
Xvoid far fu() {}
X
Xmain()
X{
X   union REGS inreg, outreg;
X   struct SREGS segreg;
X   void far *fnptr = (void *)fu;
X
X   call86x(fnptr, &inreg, &outreg, &segreg);
X}
END_OF_FILE
if test 251 -ne `wc -c <'test.c'`; then
    echo shar: \"'test.c'\" unpacked with wrong size!
fi
# end of 'test.c'
fi
echo shar: End of shell archive.
exit 0

broehl@watserv1.waterloo.edu (Bernie Roehl) (07/17/90)

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 <dos.h>
	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 <dos.h>
	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]