1. 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.
2. 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 pinter. 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.
3. 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.
4. 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.
5. 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 you must perform the address translation. It's trivial 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); }
6. 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.