Mail Archives: djgpp/1996/07/11/13:13:56
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.
- Raw text -