ID Number: Q66127
6.00 6.00a 6.00ax 7.00
MS-DOS
Summary:
In Microsoft C versions 6.0, 6.0a, 6.0ax, and C/C++ version 7.0, in
order to implement a pointer checking routine for your MS-DOS
application, you must first determine the beginning address of your
program in memory. The PSP (program segment prefix) is set up in the
lowest segment of available memory. However, when dynamically
allocating memory using malloc(), it is possible to receive memory
located below the address marked by _psp. This can break many pointer
checking routines that aren't aware of such behavior.
More Information:
When MS-DOS loads an .EXE or .COM file, the PSP is set up in the
lowest segment of the largest contiguous block of available memory.
There may be other blocks of available memory below the location of
the PSP; these blocks of memory are usually fairly small. If MS-DOS
returns one of these segments, when pointer checking is implemented
with the /Zr option (available only with the /qc compiler option), the
segment is simply discarded and MS-DOS is called again. This process
is repeated until a segment value greater than _psp is returned.
You can implement a similar routine in any C program by making calls
to a function, as demonstrated below, rather than making calls
directly to malloc(). However, the start-up code still will make calls
to malloc() directly for environment and argument space. Thus, the
pointer segments for the environment and arguments may still be less
than _psp. Further, it should be noted that this routine does not
implement pointer checking; it only enables programmers to implement
their own pointer checking by comparing segment values against _psp.
Another method of getting only pointer segments greater than _psp is
to modify the start-up code so that the value of _psp is stored at
_aseglo. This is the actual location used to store the lower segment
limit when pointer checking is implemented. The code to check the
segment returned by MS-DOS against this location, and to call MS-DOS
again if necessary, is already implemented. If it is necessary to have
pointer segments for the environment and argument variables greater
than _psp, a similar assignment can be used to modify the start-up
code. If this assignment is done before the space for these variables
is allocated in the start-up code, they will have segment values
greater than _psp. However, you should be aware that Microsoft can
make no guarantees about the implementation of this feature in any
future releases.
If a call to malloc() requires a new segment to be allocated from the
operating system, the call to MS-DOS will be made requesting only the
amount of memory required by the malloc(). In subsequent calls,
requests are made for 8K blocks of memory until no more memory is
available from that segment. Because the blocks of memory below the
PSP are small, they may not be allocated during the first calls to
malloc(). Thus, you cannot be sure exactly when these blocks of memory
will be allocated.
Sample Code
-----------
void * _new_malloc (size_t size)
{
void * temp_ptr;
temp_ptr= malloc (size);
while ((temp_ptr != NULL) && (FP_SEG(temp_ptr) < _psp))
temp_ptr= malloc (size);
return temp_ptr;
}
Additional reference words: S_QUICKC R6013 illegal far-pointer use
6.00 6.00a 6.00ax 7.00