Allocate DOS real mode memory.
Source position: go32.pp line 111
function global_dos_alloc( |
bytes: LongInt |
):LongInt; |
Allocates a block of dos real mode memory.
Parameters:
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.
Check the int31error variable.
|
Free DOS memory block. |
{ 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.