Mail Archives: djgpp/1998/01/04/15:26:02

Date: Sun, 4 Jan 1998 15:23:56 -0500 (EST)
Message-Id: <>
From: DJ Delorie <dj AT delorie DOT com>
To: space AT gold DOT com DOT br
CC: djgpp AT delorie DOT com
In-reply-to: <> (
Subject: Re: dos_ds

> Somebody out there can tell-me how exactly dos_ds is defined and how
> it works?

dos_ds is a segment with a zero base and an appropriate limit, so when
you use it, you get the DOS memory instead of your program's memory.

> I took a look on the DJGPP sources but seems like dos_ds uses the
> fat DS method, is that correct?

Perhaps it did, but it shouldn't.  In the next release, the DOS
segment will only be 1M+64K long (0x110000 bytes), because that's all
DPMI lets you use anyway.  If you need to access physical memory above
that, you need to ask DPMI to map the physical memory into the logical
memory space and tell you where it put it, and then use other DPMI
calls to create a segment that refers to it (farptr) or locate it in
your memory space (nearptr).

> And another thing, can somebody tell-me how exactly fat DS works, I
> already understand what I need to do to use it, bu I don't
> understand why do this make it work, and how to calculate a real
> memory pointer using fat DS. What see in the mail-archives for
> screen access look pretty strange for me.

The 386 supports 4Gb of logical address space.  Your program occupies
a tiny fraction of it.  Normally, you segments are only big enough to
cover your tiny fraction, to protect the rest of memory from your

With a "fat" DS, the size of your segment is grown to 4Gb, so that
*all* of the 386's logical address space is available to you.  If you
know where your segment starts (logically), you can use that to
calculate what pointers end up pointing to specific logical addresses.

For example, If you wanted to access a device at physical address
0x15000000, you'd first ask DPMI to map it into the 386's logical
address space.  Let's say it ends up at 0x98000000.  Now, your memory
is mapped somewhere too (this is the __djgpp_base_address variable,
but you can ask DPMI for this also), let's say it's at 0x23000000.
Since virtual address 0x0 is the start of your segment (0x23000000),
if you want to get to 0x98000000 you'd have to subtract pointers:

	char *foo = 0x98000000 - 0x23000000;
	char *foo = 0x98000000 - __djgpp_base_address;

Now, let's say you want to point to something in conventional memory,
like the VGA (0x000a0000).  First, you have to figure out where
conventional memory *is*.  This is easy; it's at logical address zero!

	char *dos_mem = 0 - 0x23000000;

Note that this is what __djgpp_conventional_base is.  To find the VGA,
add 0x000a0000 to that:

	char *vga_mem = 0 - 0x23000000 + 0xa0000;
	char *vga_mem = __djgpp_conventional_base + 0xa0000;

The thing you have to remember is that DPMI may *move* your program's
memory (the 0x23000000 changes) whenever you call malloc().  The two
variables noted above are automatically changed whenever needed, but
you have to recompute any pointers you're keeping that point outside
of your own program space.

The manual page for __djgpp_nearptr_enable covers most of this

- Raw text -

  webmaster     delorie software   privacy  
  Copyright 2019   by DJ Delorie     Updated Jul 2019