DOS/4G and DOS/4GW FAQ: Pointer and Address Conversions
[Previous Section] *
[Index of FAQ] *
[Next Section]
-
What is a linear address?
-
What is a physical address?
-
How do I convert between pointers and linear addresses?
-
How do I convert between code and data pointers?
-
How do I convert between pointers and low memory addresses?
-
How do I convert between linear and physical addresses?
-
How do I convert between real and linear addresses?
-
Does DOS/4G provide null pointer checking?
1.
What is a linear address?
A linear address is an address that your program uses.
Under DOS/4G and DOS/4GW, all pointers are 32-bits and
are offsets from a selector that points to the first byte
of memory.
Another way of describing a linear address is that it is
the address the CPU feeds to the memory paging system.
2.
What is a physical address?
A physical address is an address that the CPU sends to
the memory bus to directly address the memory chips in
your system.
If your system is running with paging enabled,
for example, in a Windows DOS box or under DOS with
EMM386 running, a
physical address is the address that the paging hardware
passes to the memory hardware.
If your system is not running with paging turned -- for
example, under plain DOS without EMM386 or QEMM -- then
phsyical addresses and linear addresses are the same.
Another way of describing a phsyical address is that it is
the address that any I/O cards in your system will see
under DMA.
3.
How do I convert between pointers and linear addresses?
Because DOS/4G uses a zero-based flat memory model, converting between
pointers and linear addresses is trivial. A pointer value is always
relative to the current segment (the value in CS for a code pointer, or in
DS or SS for a data pointer). The segment bases for the default DS, SS,
and CS are all zero. Hence, a near pointer is exactly the same thing as a
linear address: a null pointer points to linear address 0, and a pointer
with a value 0x10000 points to linear address 0x10000.
4.
How do I convert between code and data pointers?
Because DS and CS have the same base address, they are natural aliases
for each other. To create a data alias for a code pointer, merely create
a data pointer and set it equal to the code pointer. It's not necessary
for you to create your own alias descriptor. Similarly, to create a code
alias for a data pointer, merely create a code pointer and set it equal to
the data pointer.
5.
How do I convert between pointers and low memory addresses?
Linear addresses under 1MB map directly to physical memory. Hence the
real mode interrupt vector table is at address 0, the BIOS data segment is
at address 0x400, the monochrome video memory is at address 0xB0000, and
the color video memory is at address 0xB8000. To read and write any of
these, you can just use a pointer set to the proper address. You don't
need to create a far pointer, using some magic segment value.
6.
How do I convert between linear and physical addresses?
Linear addresses at or above 1MB do not map directly to physical
memory, so you can not in general read or write extended memory directly,
nor can you tell how a particular block of extended memory has been used.
DOS/4G supports the DPMI call INT 31h/800h, which maps physical
addresses to linear addresses. In other words, if you have a peripheral
device in your machine that has memory at a physical address of 256MB, you
can issue this call to create a linear address that points to that
physical memory. The linear address is the same thing as a near pointer
to the memory and can be manipulated as such.
There is no way in a DPMI environment to determine the physical
address corresponding to a given linear address. This is part of the
design of DPMI. You must design your application accordingly.
7.
How do I convert between real and linear addresses?
If you're using DOS/4G you can simply call the address translation API
functions D32LinearToReal() to convert a linear memory address to a real
memory address, or D32RealToLinear() to convert a real memory address to a
linear memory address. (Remember that while any real address can be
converted to a linear address, only linear addresses below 1MB can be
converted to real addresses.) However, if you're using DOS/4GW
Professional or DOS/4GW you don't have the API library, so your program
must perform the address translation. It's easy to do. Here's how:
/* RealToLinear -- convert real address (passed as long) to */
/* linear address. */
void *RealToLinear(unsigned long realAddr)
{
return (void *) (((realAddr & ~0xFFFFL) >> 12) +
(realAddr & 0xFFFF));
}
/* LinearToReal -- convert linear address to real mode */
/* (returned as ulong), returns 0 if not in first megabyte */
unsigned long LinearToReal(void *linear)
{
if ((unsigned long) linear > 0x100000)
return 0; /* not in first megabyte */
return ((((unsigned long) linear >> 4) & 0xFFFF) << 16) +
((unsigned long) linear & 0xFL);
}
8.
Does DOS/4G provide null pointer checking?
DOS/4G will trap references to the first sixteen bytes
of physical memory if you set the NullPtrCheck option to ON.
As of release 1.95, DOS/4G traps both reads and writes.
Prior to this, it only trapped writes.
You may experience problems if you set NullPtrCheck ON and use some
versions of the WATCOM WVIDEO debugger with a 1.95 or later extender.
Note that DOS/4G also provides a paged null-pointer checking feature.
|