Skip to content

global_dos_alloc

Allocate DOS real mode memory

Declaration

Source position: go32.pp line 109

  function global_dos_alloc(bytes: LongInt) : LongInt;

Description

Allocates a block of dos real mode memory.

Parameters:

bytes
size of requested real mode memory.

Return values: The low word of the returned value contains the selector to the allocated dos memory block, the high word the corresponding real mode segment value. The offset value is always zero. This function allocates memory from dos memory pool, i.e. memory below the 1 MB boundary that is controlled by dos. Such memory blocks are typically used to exchange data with real mode programs, TSRs, or device drivers. The function returns both the real mode segment base address of the block and one descriptor that can be used by protected mode applications to access the block. This function should only used for temporary buffers to get real mode information (e.g. interrupts that need a data structure in ES:(E)DI), because every single block needs an unique selector. The returned selector should only be freed by a global_dos_free call.

Errors

Check the int31error variable.

See also

Name Description
global_dos_free Free DOS memory block

Example

{ This program demonstrates the usage of DOS real mode memory by
executing a software interrupt which needs a buffer to store data
into. Because these interrupts are real mode funcs, the buffer must
be located in real mode memory space (first MB of memory). Such
memory can only be allocated by the global_dos_alloc() and
global_dos_free() functions of the GO32 unit.
In more detail this program tries to detect a VESA 2.0 BIOS
extension of your graphics card and outputs its version.
Here's the necessary interrupt call description:
  Int 10h 4f00h : VESA BIOS extension installation check
  Input : AX = 4F00h
          ES:DI = pointer to 512 byte information buffer
  Output : AX = 004Fh if successful
           ES:DI = pointer to filled buffer
  Buffer structure : (relevant to this example)
           must be 'VESA' in the first 4 chars of the buffer to be
           valid VBE version in the next word
  Note : to request VBE 2.0 information, the first 4 bytes of the
        buffer must contain 'VBE2' prior to the interrupt call.
        (this makes the problem a bit tougher; we first have to copy the
        buffer with the 'VBE2' id to dos memory...)
}
uses
        go32;
{The following 2 functions are wrappers to the GO32
global_dos_alloc() and global_dos_free() functions to simplify their
usage }
{ Function : dosalloc }
{ Input    : size of a real mode location }
{ Output   : selector and segment of a real mode location }
procedure dosalloc(var selector : word;
        var segment : word; size : longint);
var
        res : longint;
begin
        { try to allocate real mode memory  }
        res := global_dos_alloc(size);
        { the lower 16 bits of the result contain the selector to the
        allocated memory block }
        selector := word(res);
        { the upper 16 bits contain the real mode segment address of
        this block; the offset is always 0, so we don't need to return
        this }
        segment := word(res shr 16);
end;
{ Function    : dosfree }
{ Input       : selector of a real mode block }
{ Output      : none }
{ Description : de-allocates a previously allocated real mode
memory}
procedure dosfree(selector : word);
begin
        { call the GO32 function with the selector }
        global_dos_free(selector);
end;
type
        VBEInfoBuf = packed record
                { contains 'VESA' if successful }
                Signature : array[0..3] of char;
                Version : Word;
                { pad to 512 bytes length }
                reserved : array[0..505] of byte;
        end;
var
        { selector to our real mode buffer }
        selector,
        { real mode segment address of buffer }
        segment : Word;
        { register structure to issue a software interrupt }
        r : trealregs;
        infobuf : VBEInfoBuf;
begin
        { first we reset the registers and infobuf variable }
        fillchar(r, sizeof(r), 0);
        fillchar(infobuf, sizeof(VBEInfoBuf), 0);
        { allocate real mode memory }
        dosalloc(selector, segment, sizeof(VBEInfoBuf));
        { check if an error occurred during allocation }
        if (int31error<>0) then begin
                Writeln('Error while allocating real mode memory, halting');
                halt;
        end;
        { request VBE 2.0 information, fill out information buffer }
        infobuf.Signature := 'VBE2';
        { copy buffer to the allocated real mode memory }
        dosmemput(segment, 0, infobuf, sizeof(infobuf));
        { issue the interrupt; remember : DI = 0 }
        r.ax := $4f00; r.es := segment;
        realintr($10, r);
        { copy buffer to our infobuf variable again }
        dosmemget(segment, 0, infobuf, sizeof(infobuf));
        { free allocated real mode memory, because we don't need it
        anymore }
        dosfree(selector);
        { check if interrupt call was successful }
        if (r.ax <> $4f) then begin
                { write message and exit, because the infobuf doesn't contain
                any useful data we could tell the user }
                Writeln('VBE BIOS extension not available, function call ',
                        'failed');
                halt;
        end;
        { check if buffer is valid }
        if (infobuf.signature[0] = 'V') and
                (infobuf.signature[1] = 'E') and
                (infobuf.signature[2] = 'S') and
                (infobuf.signature[3] = 'A') then begin
                Writeln('VBE version ', hi(infobuf.version), '.',
                        lo(infobuf.version), ' detected');
        end;
end.