Date: Thu, 11 Jul 1996 20:09:07 +0200 (IST) From: Eli Zaretskii To: Alf Stockton Cc: djgpp AT delorie DOT com Subject: Re: int86x help needed In-Reply-To: <199607110956.LAA20242@ohm.fast.co.za> Message-Id: Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII On Thu, 11 Jul 1996, Alf Stockton wrote: > int main(int argc, char *argv[]) > { > union REGS b_regs; /* define registers */ > struct SREGS b_sregs; /* define segment registers */ > > b_regs.x.ax = 0x3000; /* check dos version */ > printf("Checking DOS version.\n"); > int86x (0x21, &b_regs, &b_regs, &b_sregs); > printf("after int86x call.\n"); > return(0); > } > > It is compiled with :- > gcc -Wall -g -O fubar.c -o bin\fubar.exe > under CWSDPMI(ie raw DOS) > > and it produces :- > Checking DOS version. > Exiting due to signal SIGSEGV Your program doesn't set the segment registers in `b_sregs' to any value, thus they contain garbage. `int86x' is meant for functions that pass parameters there, so it sets DS, ES, FS and GS to those garbled values before it issues INT 21h. While Int 21h/AX=3000h doesn't access these registers, you should never forget that in protected mode you generally can't set the segment registers to arbitrary values and hope to get away with that. If you do this, you are at the mercy of the specific implementation of the DPMI server (in this case, only CWSDPMI and only in raw XMS mode crashes; under QDPMI and under CWSDPMI with a memory manager the program runs for me just fine). So to be on the safe side, you should always set the unused fields of `b_sregs' to the current values of the registers, like this: b_sregs.ds = __tb / 16; /* sets DS to the segment of transfer buffer */ Better still, use `int86' for those functions that don't use segment registers. > I do know that there are other ways of checking DOS version but I particularly > want to use int86x as I am attempting to convert a function that uses multiple > int86x calls to DJGPP, if possible. I won't recommend such ``blind ports'', even if it seems to you that it works. A 16-bit program that uses `int86x' probably calls services that need pointers to buffers (otherwise, it would have called `int86'). However, `int86x' doesn't support such services transparently, because you will need to move the data to and from the transfer buffer (since the real-mode services cannot access data in your program's address space: your data is above 1MB mark, and the real-mode 20-bit addressing cannot get there). Therefore, I think that in the long run you will run into all kinds of trouble if you assume that `int86x' will work as it does in the original 16-bit program. I suggest you rewrite the relevant fragments to make them call `__dpmi_int' from the DJGPP library. This might seem like a pain in the neck, but I think in the long run it's a better solution, since you will need to think carefully about each service you call while rewriting the code, and thus avoid some subtle bugs.