DOS/4G

Tenberry Home

Consulting Services

Order DOS/4G

DOS/4G FAQ

Release Notes

DPMI Spec

* * *

DOS/4GW

DOS/4GW Pro

DOS/4G
for Watcom

DOS/16M

DOS/4G and DOS/4GW FAQ:
Pointer and Address Conversions


[Previous Section] * [Index of FAQ] * [Next Section]
  1. What is a linear address?
  2. What is a physical address?
  3. How do I convert between pointers and linear addresses?
  4. How do I convert between code and data pointers?
  5. How do I convert between pointers and low memory addresses?
  6. How do I convert between linear and physical addresses?
  7. How do I convert between real and linear addresses?
  8. 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.


[Previous Section] * [Index of FAQ] * [Next Section]
Last modified 2003.02.06. Your questions, comments, and feedback are welcome.