home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
FOXPRO
/
XMS
/
XMS.TXT
Wrap
Text File
|
1993-01-29
|
8KB
|
241 lines
FORCE FAQ (Frequently Asked Questions) (xms.faq 1.1) 1
------------------------------------------------------------------
Advanced Topic: Interfacing with an XMS driver
Author: David Holmes
Examples: Xstat.exe, Show.exe
General discussion:
-----------------------------------------------------------------
Q: How do I access XMS memory from a FORCE program?
A: Through the driver. Unfortunately, the driver is meant
to be called by assembler functions, not by higher level
languages such as FORCE. However, it's easy to get around that,
because FORCE takes to assembly language like a duck to water.
Q: I don't know assembler, so what can a guy do?
A: Well, you could learn it, but for most people, that's
just not a viable option, since it does take a while. But, you
won't have to, because provided here in this special chapter of
the FAQ is a function called (very cleverly):
call_driver()
Call_driver() is an assembly language "wrapper" function, just
like the undocumented function Interrupt(). In order to use it,
you should know something about assembly language, mainly; what
registers are, and what they do. If you don't, don't bother,
because I've also provided FORCE wrapper functions around the
Call_Driver() function, which allow you to access XMS memory in
a more readable, higher-level interface. But, let's take a look
at the Call_Driver() function just for reference. It's prototype
looks like this:
FUNCTION LOGICAL call_driver PROTOTYPE
PARAMETERS VALUE LONG drv_address,;
UINT ax, UINT bx,;
UINT cx, UINT dx,;
UINT si, UINT di,;
UINT bp, UINT ds,;
UINT es
If you know assembler, you'll see that all the 8086 registers
(with the exceptions SS, SP, CS, and IP) are passed in as
parameters. Of course, they're not really the registers, but
their values are loaded into the corresponding registers before
the driver is called. If you load up the registers like so:
VARDEF
UINT ax,bx,cx,dx,si,di,bp,ds,es
ENDDEF
ax = 0x0800 && Service for querying available XMS
--------------------------------------------------------------------
1
FORCE FAQ (Frequently Asked Questions) 2
--------------------------------------------------------------------
You can call the driver with the register AX being 0x0800.
call_driver( xms_get_driver(), ax, bx, cx, dx, si, di,;
bp, ds, es )
The specifications for the XMS driver are such that for this
function, "return available extended memory in Kilobytes," the
available XMS will come back in DX.
So, after the call to Call_driver(), you can look at your DX
variable to see how much XMS memory there is.
Simple as that. You'll find that the call_driver() function
mimics the Interrupt() function finally documented in UNDOC.FAQ.
------------------------------------------------------------------
Q: Hm. Still looks suspiciouly like assembler to me. What
do you have the I can USE?
A: As promised, I've provided several wrapper functions
that hide the Call_driver() function from you, so that you
don't have to worry about it if you don't want to. Let me
introduce them.
FUNCTION LOGICAL xms_installed
FUNCTION LONG xms_get_driver
FUNCTION UINT xms_get_version
FUNCTION INT xms_avail
FUNCTION LOGICAL xms_alloc
PROCEDURE xms_free
FUNCTION LOGICAL xms_copy
FUNCTION LONG xms_lock
FUNCTION INT xms_unlock
* Plus two wrapper functions around xms_copy()
FUNCTION LOGICAL xms_insert
FUNCTION LOGICAL xms_retrieve
To use these functions, you'll need a little background on the
Extended Memory Specification. First, the basics:
XMS is the memory area defined as "anything above 1M," and blocks
of memory that reside in the XMS are referred to as Extended
Memory Blocks (EMB's). Memory that resides between DOS 640K and
the 1M mark are called Upper Memory Blocks (UMB's), and may or
may not be supported by the XMS driver (Himem.sys does NOT support
them).
Because EMB's are above the 1M mark, you cannot access them as
you would with normal memory. This is because DOS pointers are
20 bits in length, giving you an address space of 1,048,576 bytes,
or roughly 1 Megabyte. This is why the driver gives you a
``handle'' instead of a pointer when you allocate an EMB. With
this handle, you can ask the driver to copy memory below the
640K mark into the EMB, and vice versa.
--------------------------------------------------------------------
2
FORCE FAQ (Frequently Asked Questions) 3
--------------------------------------------------------------------
So, that's what all this is about, now let's see how you can do
it with the functions provided with this chapter.
There are four functions that you'll use heavily when working with
XMS in FORCE. They are xms_alloc(), xms_free(), xms_insert(),
and xms_retrieve(). The last two are just wrappers around the
xms_copy() function, and the first two you'll need to get and
free the XMS memory. The rest of the functions are used internally
by these four functions. For example, you don't need to worry
about the xms_get_driver() function, since it just returns the
address of the driver, and that's taken care of by all of the
functions in the XMS library.
Let's suppose you wanted a slick way to save entire screens to
some convenient place, and bring them back at will. You could
do something like this:
VARDEF
INT temp_handle
LONG video_mem = 0xb8000000
ENDDEF
PROCEDURE screen_to_xms
xms_alloc( temp_handle, 4 ) && screens are 4K
xms_copy( &NULL, video_mem, temp_handle, 0, 4000 )
ENDPRO
Then, when you want your screen back:
PROCEDURE xms_to_screen
xms_copy( temp_handle, 0, &NULL, video_mem, 4000 )
xms_free( temp_handle )
ENDPRO
Or, suppose that you wanted a way to read a "screen" from disk,
copy it into XMS, and then call it up whenever you want. You
could do something like this:
VARDEF
BYTE one_screen[4000]
INT help_handle
ENDDEF
PROCEDURE read_help_screen
PARAMETERS CONST CHAR filename
VARDEF
UINT file_handle
ENDDEF
--------------------------------------------------------------------
3
FORCE FAQ (Frequently Asked Questions) 4
--------------------------------------------------------------------
fb_open( file_handle, filename, &B_READ )
fb_read( file_handle, one_screen, 4000 )
fb_close( file_handle )
xms_alloc( help_handle, 4 )
xms_insert( one_screen, help_handle, 0, 4000 )
ENDPRO
In fact, there's a sample program that shows you exactly how
you might want to implement this in the SAMPLE directory.
Well, that's all for now. I am of course, always available
on the BBS and CIS, so if you have any questions or comments,
feel free to contact me.
--------------------------------------------------------------------
4