The associated file (LIMEMS41.DOC) is a complete transcription of
the Lotus/Intel/Microsoft (LIM) Expanded Memory Specification
(EMS) Version 4.0, updated October 1987. It can be printed by
"COPY LIMEMS41.DOC PRN:"
I created this transcription because of the difficulty I origin-
ally had finding a copy of the document, because of the number of
people who have subsequently expressed an interest in having
access to a machine-readable copy of the specification, and,
finally, because of the annoying number of typographical errors
contained in the original and updated documents.
This transcription is not an exact letter-for-letter duplicate of
the original document. Some minor changes were necessitated by
the simple fact that the document's proportionally-spaced, multi-
fonted typography and line drawings did not lend themselves to
the generic fixed-spacing, single-fonted, non-graphical ASCII
transcription I wanted to produce for general dissemination.
Other minor changes were made to correct obvious typographical
and grammatical errors, or to simply improve the visual aes-
thetics of the presented material.
In one area, however, I simply trashed their original material
and substituted my own. This area is the Index. The original
document contains an Index that is little more than a reformatt-
ing of the Table of Contents. As anyone who has ever indexed a
large document knows, it is very difficult to produce an Index
that is both complete AND easy to use. I didn't have time to
produce one that was both, so I aimed for the former. In fact,
the Index I have provided is more of an alphabetical listing of
key words and phrases and the pages where they are referenced,
than it is a more typical Index with its multi-level headings and
subheadings.
You should be able obtain a printed, 3-hole-punched, 5.5 x 8.5"
copy of the original (and uncorrected) document directly from
Intel by calling their "Information Department" at 1-800-538-3373
and asking for a copy of the "LIM EMS 4.0 Developer's Kit." It
is available free of charge and mine arrived in about two weeks.
(European availability, however, is reported to be from poor to
non-existent.)
It is my intent to provide this transcription as a public
service. I am, therefore, releasing it into the public domain.
The original document has also been released into the public
domain by Lotus, Intel, and Microsoft, though it remains their
copyrighted property (I'm not quite sure how they manage to do
that).
I have tried as best I can to provide an accurate and corrected
transcription of the original document. It is inevitable,
however, that some typographical errors have slipped through in
spite of my hours of bleary-eyed proof reading. For these errors
I apologize and plead simple human frailty.
THIS TRANSCRIPTION IS PROVIDED WITHOUT ANY GUARANTEES
OR WARRANTIES OF ANY KIND, AND I ASSUME ABSOLUTELY NO
LIABILITY FOR ITS ACCURACY, CONTENT, OR SUBSEQUENT USE.
Dick Flanagan, W6OLD, Ben Lomond, California November 1987
LOTUS(R)/INTEL(R)/MICROSOFT(R)
EXPANDED MEMORY SPECIFICATION [1]
Version 4.0
300275-005
October, 1987
Copyright (C) 1987
Lotus Development Corporation
55 Cambridge Parkway
Cambridge, MA 02142
Intel Corporation
5200 NE Elam Young Parkway
Hillsboro, OR 97124
Microsoft Corporation
16011 NE 35th Way
Box 97017
Redmond, WA 98073
[1] Transcribed into machine-readable form by Dick Flanagan,
Ben Lomond, California. This transcription is released into the
public domain without warranty or assumption of liability.
This specification was jointly developed by Lotus Develop-
ment Corporation, Intel Corporation, and Microsoft Corpora-
tion. Although it has been released into the public domain
and is not confidential or proprietary, the specification is
still the copyright and property of Lotus Development
Corporation, Intel Corporation, and Microsoft Corporation.
DISCLAIMER OF WARRANTY
LOTUS DEVELOPMENT CORPORATION, INTEL CORPORATION, AND MICRO-
SOFT CORPORATION EXCLUDE ANY AND ALL IMPLIED WARRANTIES,
INCLUDING WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. NEITHER LOTUS NOR INTEL NOR MICROSOFT
MAKE ANY WARRANTY OF REPRESENTATION, EITHER EXPRESS OR
IMPLIED, WITH RESPECT TO THIS SPECIFICATION, ITS QUALITY,
PERFORMANCE, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR
PURPOSE. NEITHER LOTUS NOR INTEL NOR MICROSOFT SHALL HAVE
ANY LIABILITY FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES ARISING OUT OF OR RESULTING FROM THE USE OR MODIF-
ICATION OF THIS SPECIFICATION.
This specification uses the following trademarks:
Intel is a trademark of Intel Corporation
Lotus is a trademark of Lotus Development Corporation
Microsoft is a trademark of Microsoft Corporation
ii
CONTENTS
Chapter 1
INTRODUCTION
What is Expanded Memory? . . . . . . . . . . . . . . . . . 1
How Expanded Memory Works . . . . . . . . . . . . . . . . 1
Chapter 2
WRITING PROGRAMS THAT USE EXPANDED MEMORY
What Every Program Must Do . . . . . . . . . . . . . . . . 4
Advanced Programming . . . . . . . . . . . . . . . . . . . 5
Saving The State of Mapping Hardware . . . . . . . . . . 6
Retrieving Handle and Page Counts . . . . . . . . . . . 6
Mapping and Unmapping Multiple Pages . . . . . . . . . . 6
Reallocating Pages . . . . . . . . . . . . . . . . . . . 6
Using Handles and Assigning Names to Handles . . . . . . 6
Using Handle Attributes . . . . . . . . . . . . . . . . 7
Altering Page Maps and Jumping/Calling . . . . . . . . . 7
Moving or Exchanging Memory Regions . . . . . . . . . . 7
Getting the Amount of Mappable Memory . . . . . . . . . 8
Operating System Functions . . . . . . . . . . . . . . . 8
Programming Guidelines . . . . . . . . . . . . . . . . . . 12
Examples . . . . . . . . . . . . . . . . . . . . . . . . . 14
Example 1 . . . . . . . . . . . . . . . . . . . . . . . 14
Example 2 . . . . . . . . . . . . . . . . . . . . . . . 19
Example 3 . . . . . . . . . . . . . . . . . . . . . . . 30
Example 4 . . . . . . . . . . . . . . . . . . . . . . . 32
Chapter 3
EMM FUNCTIONS
Function 1. Get Status . . . . . . . . . . . . . . . . . . 37
Function 2. Get Page Frame Address . . . . . . . . . . . . 38
Function 3. Get Unallocated Page Count . . . . . . . . . . 40
Function 4. Allocate Pages . . . . . . . . . . . . . . . . 42
Function 5. Map/Unmap Handle Pages . . . . . . . . . . . . 46
Function 6. Deallocate Pages . . . . . . . . . . . . . . . 49
Function 7. Get Version . . . . . . . . . . . . . . . . . 51
Function 8. Save Page Map . . . . . . . . . . . . . . . . 53
Function 9. Restore Page Map . . . . . . . . . . . . . . . 55
Function 10. Reserved . . . . . . . . . . . . . . . . . . 57
Function 11. Reserved . . . . . . . . . . . . . . . . . . 58
Function 12. Get Handle Count . . . . . . . . . . . . . . 59
Function 13. Get Handle Pages . . . . . . . . . . . . . . 61
Function 14. Get All Handle Pages . . . . . . . . . . . . 63
Function 15. Get/Set Page Map . . . . . . . . . . . . . . 65
Get Page Map subfunction . . . . . . . . . . . . . . . . 65
Set Page Map subfunction . . . . . . . . . . . . . . . . 67
Get & Set Page Map subfunction . . . . . . . . . . . . . 69
Get Size of Page Map Save Array subfunction . . . . . . 71
iii
Function 16. Get/Set Partial Page Map . . . . . . . . . . 73
Get Partial Page Map subfunction . . . . . . . . . . . . 73
Set Partial Page Map subfunction . . . . . . . . . . . . 76
Get Size of Partial Page Map Save Array subfunction . . 78
Function 17. Map/Unmap Multiple Handle Pages . . . . . . . 80
Mapping Multiple Pages . . . . . . . . . . . . . . . . . 80
Unmapping Multiple Pages . . . . . . . . . . . . . . . . 80
Mapping and Unmapping Multiple Pages Simultaneously . . 80
Alternate Mapping and Unmapping Methods . . . . . . . . 81
Logical Page/Physical Page Method . .OF THE EXPANDED MEMORY MANAGER
Which method should your program use? . . . . . . . . . . 199
The "open handle" technique . . . . . . . . . . . . . . . 199
The "get interrupt vector" technique . . . . . . . . . . . 204
Appendix C
EXPANDED MEMORY MANAGER IMPLEMENTATION GUIDELINES
The amount of expanded memory supported . . . . . . . . . 206
The number of handles supported . . . . . . . . . . . . . 206
Handle Numbering . . . . . . . . . . . . . . . . . . . . . 206
New handle type: Handles versus Raw Handles . . . . . . . 206
The system Raw Handle (Raw Handle = 0000h) . . . . . . . . 207
Terminate and Stay Resident (TSR) Program Cooperation . . 208
Accelerator Cards . . . . . . . . . . . . . . . . . . . . 208
Appendix D
OPERATING SYSTEM/ENVIRONMENT USE OF FUNCTION 28
Examples . . . . . . . . . . . . . . . . . . . . . . . . . 209
Example 1 . . . . . . . . . . . . . . . . . . . . . . . 209
Example 2 . . . . . . . . . . . . . . . . . . . . . . . 210
Example 3 . . . . . . . . . . . . . . . . . . . . . . . 211
GLOSSARY
INDEX
v
Chapter 1
INTRODUCTION
Because even the maximum amount (640K bytes) of conventional
memory isn't always enough for large application programs,
Lotus Development Corporation, Intel Corporation, and Micro-
soft Corporation created the Lotus/Intel/Microsoft (LIM)
Expanded Memory Specification.
The LIM Expanded Memory Specification defines the software
interface between the Expanded Memory Manager (EMM) -- a
device driver that controls and manages expanded memory --
and application programs that use expanded memory.
What is Expanded Memory?
Expanded memory is memory beyond DOS's 640K-byte limit. The
LIM specification supports up to 32M bytes of expanded
memory. Because the 8086, 8088, and 80286 (in real mode)
microprocessors can physically address only 1M bytes of
memory, they access expanded memory through a window in
their physical address range. The next section explains how
this is done.
How Expanded Memory Works
Expanded memory is divided into segments called logical
pages. These pages are typically 16K bytes of memory. Your
computer accesses logical pages through a physical block of
memory called a page frame. The page frame contains
multiple physical pages, pages that the microprocessor can
address directly. Physical pages are also typically 16K
bytes of memory.
This page frame serves as a window into expanded memory.
Just as your computer screen is a window into a large
spreadsheet, so the page frame is a window into expanded
memory.
A logical page of expanded memory can be mapped into (made
to appear in) any one of the physical pages in the page
frame. Thus, a read or write to the physical page actually
becomes a read or write to the associated logical page. One
logical page can be mapped into the page frame for each
physical page.
Figure 1-1 shows the relationship among the page frame,
physical pages, and logical pages.
Introduction 1
32M +--------------+
/| |
| |
/ | |
| |
/ | |
| |
/ | |
| Expanded |
/ | Memory |
1024K +--------------+ | |
| / / / / / / | / | |
960K +--------------+ | |
| Page Frame | | |
| | | |
| 12 16K-Byte | | |
| Physical | | |
| Pages | | |
768K +--------------+ | Divided into |
| / / / / / / | \ | logical |
640K +--------------+ | pages |
| | \ | |
| | | |
| | \ | |
| | | |
| 24 16K-Byte | \ | |
| Physical | | |
| Pages* | \ | |
| | | |
| | \ | |
| | | |
| | \ | |
256K +--------------+ | |
| | \ | |
| / / / / / / | | |
| | \ | |
| / / / / / / | | |
| | \ | |
| / / / / / / | | |
| | \ | |
0 +--------------+ | |
\ | |
| |
*Intended for operating \ | |
system/environment use only 0 +--------------+
Figure 1-1. Expanded Memory
Introduction 2
The page frame is located above 640K bytes. Normally, only
video adapters, network cards, and similar devices exist
between 640K and 1024K.
This specification also defines methods for operating
systems and environments to access expanded memory through
physical pages below 640K bytes. These methods are intended
for operating system/environment developers only.
Introduction 3
Chapter 2
WRITING PROGRAMS THAT USE EXPANDED MEMORY
This chapter describes what every program must do to use
expanded memory and describes more advanced techniques of
using expanded memory.
This chapter also lists programming guidelines you should
follow when writing programs that use expanded memory and
provides the listings of some example programs.
What Every Program Must Do
This section describes the steps every program must take to
use expanded memory.
In order to use expanded memory, applications must perform
these steps in the following order:
1. Determine if EMM is installed.
2. Determine if enough expanded memory pages exist for your
application. (Function 3)
3. Allocate expanded memory pages. (Function 4, 18, or 27)
4. Get the page frame base address. (Function 2)
5. Map in expanded memory pages. (Function 5 or 17)
6. Read/write/execute data in expanded memory, just as if
it were conventional memory.
7. Return expanded memory pages to expand memory pool
before exiting. (Function 6 or 18)
Table 2-1 overviews the functions while Chapter 3 describes
each of these functions in detail. Example programs at the
end of this chapter illustrate using expanded memory.
Writing Programs That Use Expanded Memory 4
Table 2-1. The Basic Functions
----------------------------------------------------------------
Function Description
----------------------------------------------------------------
1 The Get Status Function returns a status code
indicating whether the memory manager hardware is
working correctly.
2 The Get Page Frame Address function returns the
address where the 64K-byte page frame is located.
3 The Get Unallocated Page Count function returns the
number of unallocated pages (pages available to your
program) and the total number of pages in expanded
memory.
4 The Allocate Pages function allocates the number of
pages requested and assigns a unique EMM handle to
these pages.
5 The Map/Unmap Handle Page function maps a logical
page to a specific physical page anywhere in the
mappable regions of system memory.
6 The Deallocate Pages deallocates the logical pages
currently allocated to an EMM handle.
7 The Get Version function returns the version number
of the memory manager software.
----------------------------------------------------------------
Advanced Programming
In addition to the basic functions, the Lotus/Intel/Micro-
soft Expanded Memory Specification provides several advanced
functions which enhance the capabilities of software that
uses expanded memory.
The following sections describe the advanced programming
capabilities and list the advanced EMM functions.
Note............................................................
Before using the advanced functions, programs should first
call Function 7 (Get Version) to determine whether the
installed version of EMM supports these functions.
Writing Programs That Use Expanded Memory 5
Saving The State of Mapping Hardware
Some software (such as interrupt service routines, device
drivers, and resident software) must save the current state
of the mapping hardware, switch mapping contexts, manipulate
sections of expanded memory, and restore the original
context of the memory mapping hardware. Use Functions 8 and
9 or 15 and 16 to save the state of the hardware.
Retrieving Handle and Page Counts
Some utility programs need to keep track of how expanded
memory is being used; use Functions 12 through 14 to do
this.
Mapping and Unmapping Multiple Pages
Mapping multiple pages reduces the overhead an application
must perform during mapping. Function 17 lets a program map
(or unmap) multiple pages at one time.
In addition, you can map pages using segment addresses
instead of physical pages. For example, if the page frame
base address is set to D000, you can map to either physical
page 0 or segment D000. Function 25 (Get Mappable Physical
Address Array) returns a cross reference between all
expanded memory physical pages and their corresponding
segment values.
Reallocating Pages
Reallocating pages (Function 18) lets applications dynami-
cally allocate expanded memory pages without acquiring
another handle or obtain a handle without allocating pages.
Reallocating pages is an efficient means for applications to
obtain and release expanded memory pages.
Using Handles and Assigning Names to Handles
This specification lets you associate a name with a handle,
so a family of applications can share information in
expanded memory. For example, a software package consisting
of a word processor, spreadsheet, and print spooler can
share the same data among the different applications. The
print spooler could use a handle name to reference data that
either the spreadsheet or word processor put in expanded
memory and could check for data in a particular handle
name's expanded memory pages.
Writing Programs That Use Expanded Memory 6
Use Function 20 (Set Handle Name subfunction) to assign a
handle name to an EMM handle or Function 21 (Search for
Named Handle subfunction) to obtain the EMM handle as-
sociated with the handle name. In addition, you can use
Function 14 (Get Handle Pages) to determine the number of
expanded memory pages allocated to an EMM handle.
Using Handle Attributes
In addition to naming a handle, you can use Function 19 to
associate an attribute (volatile or non-volatile) with a
handle name. A non-volatile attribute enables expanded
memory pages to preserve their data through a warmboot.
With a volatile attribute, the data is not preserved. The
default attribute for handles is volatile.
Because using this function depends on the capabilities of
the expanded memory hardware installed in the system, you
should use the Get Attribute Capability subfunction before
attempting to assign an attribute to a handle's pages.
Altering Page Maps and Jumping/Calling
You can use Functions 22 (Alter Page Map & Jump) and 23
(Alter Page Map & Call) to map a new set of values into the
map registers and transfer program control to a specified
address within expanded memory. These functions can be used
to load and execute code in expanded memory. An application
using this feature can significantly reduce the amount of
conventional memory it requires. Programs can load needed
modules into expanded memory at run time and use Functions
22 and 23 to transfer control to these modules.
Using expanded memory to store code can improve program
execution in many ways. For example, sometimes programs
need to be divided into small overlays because of conven-
tional memory size limitations. Overlays targeted for
expanded memory can be very large because LIM EMS 4.0
supports up to 32M bytes of expanded memory. This method of
loading overlays improves overall system performance by
conserving conventional memory and eliminating conventional
memory allocation errors.
Moving or Exchanging Memory Regions
Using Function 24 (Move/Exchange Memory Region), you can
easily move and exchange data between conventional and
expanded memory. Function 24 can manipulate up to one
megabyte of data with one function call. Although applica-
Writing Programs That Use Expanded Memory 7
tions can perform this operation without this function,
having the expanded memory manager do it reduces the amount
of overhead for the application.
In addition, this function checks for overlapping regions
and performs all the necessary mapping, preserving the
mapping context from before the exchange/move call.
Getting the Amount of Mappable Memory
Function 25 enables applications to determine the total
amount of mappable memory the hardware/system currently
supports. Not all expanded memory boards supply the same
number of physical pages (map registers).
The Get Mappable Physical Address Array Entries subfunction
returns the total number of physical pages the expanded
memory hardware/system is capable of supporting. The Get
Mappable Physical Array subfunction returns a cross refer-
ence between physical page numbers and the actual segment
address for each of the physical pages.
Operating System Functions
In addition to the functions for application programs, this
specification defines functions for operating systems/en-
vironments. These functions can be disabled at any time by
the operating system/environment, so programs should not
depend on their presence. Applications that avoid this
warning and use these functions run a great risk of being
incompatible with other programs, including the operating
system.
Writing Programs That Use Expanded Memory 8
Table 2-2. The Advanced Functions
----------------------------------------------------------------
Function Description
----------------------------------------------------------------
8 The Save Page Map saves the contents of the page
mapping registers from all expanded memory boards in
an internal save area.
9 The Restore Page Map function restores (from an
internal save area) the page mapping register
contents on the expanded memory boards for a
particular EMM handle.
10 Reserved.
11 Reserved.
12 The Get Handle Count function returns the number of
open EMM handles in the system.
13 The Get Handle Pages function returns the number of
pages allocated to a specific EMM handle.
14 The Get All Handle Pages function returns an array
of the active EMM handles and the number of pages
allocated to each one.
15 The Get/Set Page Map subfunction saves or restores
the mapping context for all mappable memory regions
(conventional and expanded) in a destination array
which the application supplies.
16 The Get/Set Partial Page Map subfunction provides a
mechanism for saving a partial mapping context for
specific mappable memory regions in a system.
17 The Map/Unmap Multiple Handle Pages function can, in
a single invocation, map (or unmap) logical pages
into as many physical pages as the system supports.
18 The Reallocate Pages function can increase or
decrease the amount of expanded memory allocated to
a handle.
19 The Get/Set Handle Attribute function allows an
application program to determine and set the
attribute associated with a handle.
Writing Programs That Use Expanded Memory 9
Table 2-2. The Advanced Functions (continued)
----------------------------------------------------------------
Function Description
----------------------------------------------------------------
20 The Get/Set Handle Name function gets the eight
character name currently assigned to a handle and
can assign an eight character name to a handle.
21 The Get Handle Directory function returns informa-
tion about active handles and the names assigned to
each.
22 The Alter Page Map & Jump function alters the memory
mapping context and transfers control to the
specified address.
23 The Alter Page Map & Call function alters the speci-
fied mapping context and transfers control to the
specified address. A return can then restore the
context and return control to the caller.
24 The Move/Exchange Memory Region function copies or
exchanges a region of memory from conventional to
conventional memory, conventional to expanded
memory, expanded to conventional memory, or expanded
to expanded memory.
25 The Get Mappable Physical Address Array function
returns an array containing the segment address and
physical page number for each mappable physical page
in a system.
26 The Get Expanded Memory Hardware Information
function returns an array containing the hardware
capabilities of the expanded memory system.
27 The Allocate Standard/Raw Pages function allocates
the number of standard or non-standard size pages
that the operating system requests and assigns a
unique EMM handle to these pages.
28 The Alternate Map Register Set function enables an
application to simulate alternate sets of hardware
mapping registers.
29 The Prepare Expanded Memory Hardware for Warm Boot
function prepares the expanded memory hardware for
an "impending" warm boot.
Writing Programs That Use Expanded Memory 10
Table 2-2. The Advanced Functions (continued)
----------------------------------------------------------------
Function Description
----------------------------------------------------------------
30 The Enable/Disable OS/E function enables operating
systems developers to enable and disable functions
designed for operating system use.
----------------------------------------------------------------
Writing Programs That Use Expanded Memory 11
Programming Guidelines
The following section contains guidelines for programmers
writing applications that use EMM.
o Do not put a program's stack in expanded memory.
o Do not replace interrupt 67h. This is the interrupt
vector the EMM uses. Replacing interrupt 67h could
result in disabling the Expanded Memory Manager.
o Do not map into conventional memory address space your
application doesn't own. Applications that use the EMM
to swap into conventional memory space, must first
allocate this space from the operating system. If the
operating system is not aware that a region of memory it
manages is in use, it will think it is available. This
could have disastrous results. EMM should not be used
to "allocate" conventional memory. DOS is the proper
manager of conventional memory space. EMM should only
be used to swap data in conventional memory space
previously allocated from DOS.
o Applications that plan on using data aliasing in
expanded memory must check for the presence of expanded
memory hardware. Data aliasing occurs when mapping one
logical page into two or more mappable segments. This
makes one 16K-byte expanded memory page appear to be in
more than one 16K-byte memory address space. Data
aliasing is legal and sometimes useful for applications.
Software-only expanded memory emulators cannot perform
data aliasing. A simple way to distinguish software
emulators from actual expanded memory hardware is to
attempt data aliasing and check the results. For
example, map one logical page into four physical pages.
Write to physical page 0. Read physical pages 1-3 to
see if the data is there as well. If the data appears
in all four physical pages, then expanded memory
hardware is installed in the system, and data aliasing
is supported.
o Applications should always return expanded memory pages
to the expanded memory manager upon termination. These
pages will be made available for other applications. If
unneeded pages are not returned to the expanded memory
manager, the system could "run out" of expanded memory
pages or expanded memory handles.
o Terminate and stay resident programs (TSR's) should
ALWAYS save the state of the map registers before
changing them. Since TSR's may interrupt other programs
Writing Programs That Use Expanded Memory 12
which may be using expanded memory, they must not change
the state of the page mapping registers without first
saving them. Before exiting, TSR's must restore the
state of the map registers.
The following sections describe the three ways to save
and restore the state of the map registers.
1. Save Page Map and Restore Page Map (Functions 8 and
9). This is the simplest of the three methods. The
EMM saves the map register contents in its own data
structures -- the application does not need to
provide extra storage locations for the mapping
context. The last mapping context to be saved,
under a particular handle, will be restored when a
call to Restore Page Map is issued with the same
handle. This method is limited to one mapping
context for each handle and saves the context for
only LIM standard 64K-byte page frames.
2. Get/Set Page Map (Function 15). This method
requires the application to allocate space for the
storage array. The EMM saves the mapping context in
an array whose address is passed to the EMM. When
restoring the mapping context with this method, an
application passes the address of an array which
contains a previously stored mapping context.
This method is preferable if an application needs to
do more than one save before a restore. It provides
a mechanism for switching between more than one
mapping context.
3. Get/Set Partial Page Map (Function 16). This method
provides a way for saving a partial mapping context.
It should be used when the application does not need
to save the context of all mappable memory. This
function also requires that the storage array be
part of the application's data.
o All functions using pointers to data structures must
have those data structures in memory which will not be
mapped out. Functions 22 and 23 (Alter Map & Call and
Alter Map & Jump) are the only exceptions.
Writing Programs That Use Expanded Memory 13
Examples
This section lists four example programs that demonstrate
the use of expanded memory.
Example 1
This program was written using the Microsoft C compiler
Version 3.0. EMM function calls are made with the int86
function found in the dos.h library. To create an ex-
ecutable program use the following compile command line:
msc /Gs /Oat /Ml program,,program;
#include
#include
#define EMM_INT 0x67 /* EMM interrupt number */
#define GET_PAGE_FRAME 0x41 /* EMM get page frame */
/* function number */
#define GET_UNALLOC_PAGE_COUNT 0x42 /* EMM get unallocated */
/* page count */
/* function number */
#define ALLOCATE_PAGES 0x43 /* EMM allocate pages */
/* function number */
#define MAP_PAGES 0x44 /* EMM map pages */
/* function number */
#define DEALLOCATE_PAGES 0x45 /* EMM deallocate pages */
/* function number */
#define DEVICE_NAME_LENGTH 8 /* length of a device */
/* name string */
#define TRUE 1
#define FALSE 0
union REGS input_regs, output_regs;
struct SREGS segment_regs;
int pf_addr;
/*------------------------------------------------------------*/
/* Routine to convert a segment:offset pair to a far ptr. */
/*------------------------------------------------------------*/
char *build_ptr (segment, offset)
unsigned int segment;
unsigned int offset;
{
char *ptr;
ptr = (char *)(((unsigned long)segment << 16) + offset);
return (ptr);
}
Writing Programs That Use Expanded Memory 14
/*------------------------------------------------------------*/
/* Function which determines whether EMM device driver */
/* is installed. */
/*------------------------------------------------------------*/
char emm_installed()
{
char *EMM_device_name = "EMMXXXX0";
char *int_67_device_name_ptr;
/*--------------------------------------------------------*/
/* AH = DOS get interrupt vector function. */
/*--------------------------------------------------------*/
input_regs.h.ah = 0x35;
/*--------------------------------------------------------*/
/* AL = EMM interrupt vector number. */
/*--------------------------------------------------------*/
input_regs.h.al = EMM_INT;
intdosx (&input_regs, &output_regs, &segment_regs);
/*--------------------------------------------------------*/
/* Upon return ES:0Ah points to location where */
/* device name should be. */
/*--------------------------------------------------------*/
int_67_device_name_ptr = build_ptr (segment_regs.es, 0x0A);
/*--------------------------------------------------------*/
/* Compare memory with EMM device name. */
/*--------------------------------------------------------*/
if (memcmp (EMM_device_name, int_67_device_name_ptr,
DEVICE_NAME_LENGTH) == 0)
return (TRUE);
else
return (FALSE);
}
/*------------------------------------------------------------*/
/* Function which determines if there are enough unallocated */
/* expanded memory pages for the application. */
/*------------------------------------------------------------*/
char enough_unallocated_pages (pages_needed)
int pages_needed;
{
input_regs.h.ah = GET_UNALLOCATED_PAGE_COUNT;
int86 (EMM_INT, &input_regs, &output_regs);
if (output_regs.h.ah != 0 || pages_needed > output_regs.x.bx)
return (FALSE);
else
return (TRUE);
}
Writing Programs That Use Expanded Memory 15
/*------------------------------------------------------------*/
/* Function which allocates expanded memory pages and passes */
/* back to the main EMM handle. */
/*------------------------------------------------------------*/
char allocate_expanded_memory_pages (pages_needed,emm_handle_ptr)
int pages_needed;
unsigned int *emm_handle_ptr;
{
input_regs.h.ah = ALLOCATE_PAGES;
input_regs.x.bx = pages_needed;
int86 (EMM_INT, &input_regs, &output_regs);
if (output_regs.h.ah == 0) {
*emm_handle_ptr = output_regs.x.dx;
return (TRUE);
}
else
return (FALSE);
}
/*------------------------------------------------------------*/
/* Routine to map a logical page to a physical page. */
/*------------------------------------------------------------*/
char map_expanded_memory_pages (emm_handle, physical_page,
logical_page)
unsigned int emm_handle;
int physical_page;
int logical_page;
{
input_regs.h.ah = MAP_PAGES;
input_regs.h.al = physical_page;
input_regs.x.bx = logical_page;
input_regs.x.dx = emm_handle;
int86 (EMM_INT, &input_regs, &output_regs);
if (output_regs.h.ah == 0)
return (TRUE);
else
return (FALSE);
}
Writing Programs That Use Expanded Memory 16
/*------------------------------------------------------------*/
/* Routine which gets the page frame base address from EMM. */
/*------------------------------------------------------------*/
char get_page_frame_address (pf_ptr)
char **pf_ptr;
{
input_regs.h.ah = GET_PAGE_FRAME;
int86 (EMM_INT, &input_regs, &output_regs);
if (output_regs.h.ah != 0) /* check EMM status */
return (FALSE);
else
*pf_ptr = build_ptr (output_regs.x.bx, 0);
return (TRUE);
}
/*------------------------------------------------------------*/
/* Routine to release all expanded memory pages allocated */
/* by an EMM handle. */
/*------------------------------------------------------------*/
char deallocate_expanded_memory_pages (emm_handle)
unsigned int emm_handle;
{
input_regs.h.ah = DEALLOCATE_PAGES;
input_regs.x.dx = emm_handle;
int86 (EMM_INT, &input_regs, &output_regs);
if (output_regs.h.ah == 0)
return (TRUE);
else
return (FALSE);
}
main()
{
unsigned int emm_handle;
char *pf_addr;
int pages_needed;
int physical_page;
int logical_page;
int index;
/*--------------------------------------------------------*/
/* Determine if EMM is installed. */
/*--------------------------------------------------------*/
if (!emm_installed())
exit(1);
Writing Programs That Use Expanded Memory 17
/*--------------------------------------------------------*/
/* Determine if enough expanded memory pages exist for */
/* application. */
/*--------------------------------------------------------*/
pages_needed = 1;
if (!enough_unallocated_pages (pages_needed))
exit(1);
/*--------------------------------------------------------*/
/* Allocate expanded memory pages. */
/*--------------------------------------------------------*/
if (!allocate_expanded_memory_pages (pages_needed,
&emm_handle))
exit(1);
/*--------------------------------------------------------*/
/* Map in the required pages. */
/*--------------------------------------------------------*/
physical_page = 0;
logical_page = 0;
if (!map_expanded_memory_pages (emm_handle, physical_page,
logical_page))
exit(1);
/*--------------------------------------------------------*/
/* Get expanded memory page frame address. */
/*--------------------------------------------------------*/
if (!get_page_frame_address (&pf_addr))
exit(1);
/*--------------------------------------------------------*/
/* Write to expanded memory. */
/*--------------------------------------------------------*/
for (index = 0; index < 0x3fff; index++)
pf_addr[index] = index;
/*--------------------------------------------------------*/
/* Return expanded memory pages before exiting. */
/*--------------------------------------------------------*/
if (!deallocate_expanded_memory_pages (emm_handle))
exit(1);
}
Writing Programs That Use Expanded Memory 18
Example 2
This program shows you how to use the basic functions of the LIM
Expanded Memory Specification with Turbo Pascal. The program
does the following:
1. Makes sure the LIM Expanded Memory Manager (EMM) has
been installed.
2. Displays the version number of the EMM.
3. Determines if there are enough pages of memory for the
program. It then displays the total number of EMM pages
present in the system and the number available for use.
4. Requests the desired number of pages from the EMM.
5. Maps a logical page into one of the physical pages.
6. Displays the base address of our EMM memory page frame.
Performs a simple read/write test on the EMM memory.
7. Returns the EMM memory given to us back to the EMM.
8. Exits.
All the calls are structured to return the result or error code
of the Expanded Memory function performed as an integer. If the
error code is not zero, an error has occurred, a simple error
procedure is called, and the program terminates.
Type
ST3 = string[3];
ST80 = string[80];
ST5 = string[5];
Registers = record
case integer of
1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: Integer);
2: (AL,AH,BL,BH,CL,CH,DL,DH : Byte);
end;
Const
EMM_INT = $67;
DOS_Int = $21;
GET_PAGE_FRAME = $41;
GET_UNALLOCATED_PAGE_COUNT = $42;
ALLOCATE_PAGES = $43;
MAP_PAGES = $44;
DEALLOCATE_PAGES = $45;
GET_VERSION = $46;
STATUS_OK = 0;
Writing Programs That Use Expanded Memory 19
{------------------------------------------------------------}
{ Assume the application needs one EMM page. }
{------------------------------------------------------------}
APPLICATION_PAGE_COUNT = 1;
Var
Regs: Registers;
Emm_handle,
Page_Frame_Base_Address,
Pages_Needed,
Physical_Page,
Logical_Page,
Offset,
Error_Code,
Pages_EMM_Available,
Total_EMM_Pages,
Available_EMM_Pages: Integer;
Version_Number,
Pages_Number_String: ST3;
Verify: Boolean;
{------------------------------------------------------------}
{ The function Hex_String converts an integer into a four }
{ character hexadecimal number (string) with leading zeros. }
{------------------------------------------------------------}
Function Hex_String (Number: Integer): ST5;
Function Hex_Char (Number: Integer): Char;
Begin
If Number < 10 then
Hex_Char := Char (Number + 48)
else
Hex_Char := Char (Number + 55);
end; { Function Hex_char }
Var
S: ST5;
Begin
S := '';
S := Hex_Char ((Number shr 1) div 2048);
Number := (((Number shr 1) mod 2048) shl 1) + (Number and 1);
S := S + Hex_Char (Number div 256);
Number := Number mod 256;
S := S + Hex_Char (Number div 16);
Number := Number mod 16;
S := S + Hex_Char (Number);
Hex_String := S + 'h';
end; { Function Hex_String }
Writing Programs That Use Expanded Memory 20
{------------------------------------------------------------}
{ The function Emm_Installed checks to see if the }
{ EMM is loaded in memory. It does this by looking }
{ for the string 'EMMXXXX0', which should be located }
{ at 10 bytes from the beginning of the code segment the }
{ EMM interrupt, 67h, points to. }
{------------------------------------------------------------}
Function Emm_Installed: Boolean;
Var
Emm_Device_Name : string[8];
Int_67_Device_Name: string[8];
Position : integer;
Regs : registers;
Begin
Int_67_Device_Name := '';
Emm_Device_Name := 'EMMXXXX0';
with Regs do
Begin
{----------------------------------------------------}
{ Get the code segment interrupt 67h points to }
{ the EMM interrupt by using DOS function 35h. }
{ (get interrupt vector) }
{----------------------------------------------------}
AH := $35;
AL := EMM_INT;
Intr (DOS_Int, Regs);
{----------------------------------------------------}
{ The ES pseudo-register contains the segment }
{ address pointed to by interrupt 67h. Create an }
{ eight character string from the eight successive }
{ bytes at address ES:$000A (10 bytes from ES) }
{----------------------------------------------------}
For Position := 0 to 7 do
Int_67_Device_Name :=
Int_67_Device_Name + Chr (mem[ES:Position + $0A]);
Emm_Installed := True;
{----------------------------------------------------}
{ If the string is the EMM manager signature, }
{ 'EMMXXXX0', then EMM is installed and ready for }
{ use. If not, then EMM is not present. }
{----------------------------------------------------}
If Int_67_Device_Name <> Emm_Device_Name
then Emm_Installed := False;
end; { with Regs do }
end; { Function Emm_Installed }
Writing Programs That Use Expanded Memory 21
{------------------------------------------------------------}
{ This function returns the total number of EMM pages }
{ present in the system, and the number of EMM pages that }
{ are available. }
{------------------------------------------------------------}
Function EMM_Pages_Available
(Var Total_EMM_Pages, Pages_Available: Integer): Integer;
Var
Regs: Registers;
Begin
with Regs do
Begin
{----------------------------------------------------}
{ Get the number of currently unallocated pages and }
{ the total number of pages in the system from EMM. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = get unallocated page count function }
{----------------------------------------------------}
AH := GET_UNALLOCATED_PAGE_COUNT;
Intr (EMM_INT, Regs);
{----------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ BX = currently unallocated pages }
{ DX = total pages in the system }
{ AH = status }
{----------------------------------------------------}
Pages_Available := BX;
Total_EMM_Pages := DX;
EMM_Pages_Available := AH;
end;
end; { Function EMM_Pages_Available }
{------------------------------------------------------------}
{ This function requests the specified number of pages }
{ from the EMM. }
{------------------------------------------------------------}
Function Allocate_Expanded_Memory_Pages
(Pages_Needed: Integer; Var Handle: Integer): Integer;
Var
Regs: Registers;
Writing Programs That Use Expanded Memory 22
Begin
with Regs do
Begin
{----------------------------------------------------}
{ Allocate the specified number of pages from EMM. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = allocate pages function. }
{ BX = number of pages to allocate. }
{----------------------------------------------------}
AH := ALLOCATE_PAGES;
BX := Pages_Needed;
Intr (EMM_INT, Regs);
{----------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ DX = EMM handle }
{ AH = status }
{----------------------------------------------------}
Handle := DX;
Allocate_Expanded_Memory_Pages := AH;
end;
end; { Function Allocate_Expanded_Memory_Pages }
{------------------------------------------------------------}
{ This function maps a logical page allocated by the }
{ Allocate_Expanded_Memory_Pages function into one of the }
{ four physical pages. }
{------------------------------------------------------------}
Function Map_Expanded_Memory_Pages
(Handle, Logical_Page, Physical_Page: Integer): Integer;
Var
Regs: Registers;
Begin
with Regs do
Begin
{----------------------------------------------------}
{ Map a logical page at a physical page. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = map page function }
{ DX = handle }
{ BX = logical page number }
{ AL = physical page number }
{----------------------------------------------------}
AH := MAP_PAGES;
DX := Handle;
BX := Logical_Page;
AL := Physical_Page;
Intr (EMM_INT, Regs);
Writing Programs That Use Expanded Memory 23
{----------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ AH = status }
{----------------------------------------------------}
Map_Expanded_Memory_Pages := AH;
end; { with Regs do }
end; { Function Map_Expanded_Memory_Pages }
{------------------------------------------------------------}
{ This function gets the physical address of the EMM page }
{ frame we are using. The address returned is the segment }
{ of the page frame. }
{------------------------------------------------------------}
Function Get_Page_Frame_Base_Address
(Var Page_Frame_Address: Integer): Integer;
Var
Regs: Registers;
Begin
with Regs do
Begin
{----------------------------------------------------}
{ Get the page frame segment address from EMM. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = get page frame segment function }
{----------------------------------------------------}
AH := GET_PAGE_FRAME;
Intr (EMM_INT, Regs);
{----------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ BX = page frame segment address }
{ AH = status }
{----------------------------------------------------}
Page_Frame_Address := BX;
Get_Page_Frame_Base_Address := AH;
end; { with Regs do }
end; { Function Get_Page_Frame_Base_Address }
{------------------------------------------------------------}
{ This function releases the EMM memory pages allocated to }
{ us, back to the EMM memory pool. }
{------------------------------------------------------------}
Function Deallocate_Expanded_Memory_Pages
(Handle: Integer): Integer;
Var
Regs: Registers;
Writing Programs That Use Expanded Memory 24
Begin
with Regs do
Begin
{----------------------------------------------------}
{ Deallocate the pages allocated to an EMM handle. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = deallocate pages function }
{ DX = EMM handle }
{----------------------------------------------------}
AH := DEALLOCATE_PAGES;
DX := Handle;
Intr (EMM_INT, Regs);
{----------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ AH = status }
{----------------------------------------------------}
Deallocate_Expanded_Memory_Pages := AH;
end; { with Regs do }
end; { Function Deallocate_Expanded_Memory_Pages }
{------------------------------------------------------------}
{ This function returns the version number of the EMM as }
{ a three-character string. }
{------------------------------------------------------------}
Function Get_Version_Number (Var Version_String: ST3): Integer;
Var
Regs: Registers;
Integer_Part, Fractional_Part: Char;
Begin
with Regs do
Begin
{----------------------------------------------------}
{ Get the version of EMM. }
{ Load pseudo-registers prior to invoking EMM. }
{ AH = get EMM version function }
{----------------------------------------------------}
AH := GET_VERSION;
Intr (EMM_INT, Regs);
Writing Programs That Use Expanded Memory 25
{----------------------------------------------------}
{ If the version number returned was OK, then }
{ convert it to a three-character string. }
{----------------------------------------------------}
If AH=STATUS_OK then
Begin
{------------------------------------------------}
{ The upper four bits of AH are the integer }
{ portion of the version number, the lower four }
{ bits are the fractional portion. Convert the }
{ integer value to ASCII by adding 48. }
{------------------------------------------------}
Integer_Part := Char (AL shr 4 + 48);
Fractional_Part := Char (AL and $F + 48);
Version_String := Integer_Part + '.' +
Fractional_Part;
end; { If AH=STATUS_OK }
{----------------------------------------------------}
{ Unload the pseudo-registers after invoking EMM. }
{ AH = status }
{----------------------------------------------------}
Get_Version_Number := AH;
end; { with Regs do }
end; { Function Get_Version_Number }
{------------------------------------------------------------}
{ This procedure prints an error message passed by the }
{ caller, prints the error code passed by the caller in hex, }
{ and then terminates the program with an error level of 1. }
{------------------------------------------------------------}
Procedure Error (Error_Message: ST80; Error_Number: Integer);
Begin
Writeln (Error_Message);
Writeln (' Error_Number = ', Hex_String (Error_Number));
Writeln ('EMM test program aborting.');
Halt (1);
end; { Procedure Error }
{--------------------------------------------------------------}
{ This program is an example of the basic EMM functions that }
{ you need in order to use EMM memory with Turbo Pascal. }
{--------------------------------------------------------------}
Begin
ClrScr;
Window (5,2,77,22);
Writing Programs That Use Expanded Memory 26
{------------------------------------------------------------}
{ Determine if the Expanded Memory Manager is installed. If }
{ not, then terminate 'main' with an ErrorLevel code of 1. }
{------------------------------------------------------------}
If not (Emm_Installed) then
Begin
Writeln ('The LIM EMM is not installed.');
Halt (1);
end
else
Begin
{ Get the version number and display it }
Error_Code := Get_Version_Number (Version_Number);
If Error_Code <> STATUS_OK then
Error ('Error getting EMM version number.', Error_Code)
else
Writeln ('LIM Expanded Memory Manager, version ',
Version_Number, ' is ready for use.');
end;
Writeln;
{------------------------------------------------------------}
{ Determine if there are enough expanded memory pages for }
{ this application. }
{------------------------------------------------------------}
Pages_Needed := APPLICATION_PAGE_COUNT;
Error_Code := EMM_Pages_Available (Total_EMM_Pages,
Available_EMM_Pages);
If Error_Code <> STATUS_OK then
Error ('Error determining number of EMM pages available.',
Error_Code);
Writeln ('There are a total of ', Total_EMM_Pages,
' expanded memory pages present in this system.');
Writeln (' ', Available_EMM_Pages,
' of those pages are available for use.');
Writeln;
{------------------------------------------------------------}
{ If there is an insufficient number of pages for the }
{ application, then report the error and terminate the EMM }
{ example program. }
{------------------------------------------------------------}
If Pages_Needed > Available_EMM_Pages then
Begin
Str (Pages_Needed, Pages_Number_String);
Error ('We need ' + Pages_Number_String +
' EMM pages. There are not that many available.',
Error_Code);
end; { Pages_Needed > Available_EMM_Pages }
Writing Programs That Use Expanded Memory 27
{------------------------------------------------------------}
{ Allocate expanded memory pages for our use. }
{------------------------------------------------------------}
Error_Code :=
Allocate_Expanded_Memory_Pages (Pages_Needed, Emm_Handle);
Str (Pages_Needed, Pages_Number_String);
If Error_Code <> STATUS_OK then
Error ('EMM test program failed trying to allocate '
+ Pages_Number_String
+ ' pages for usage.', Error_Code);
Writeln (APPLICATION_PAGE_COUNT,
' EMM page(s) allocated for the EMM test program.');
Writeln;
{------------------------------------------------------------}
{ Map in the required logical pages to the physical pages }
{ given to us, in this case just one page. }
{------------------------------------------------------------}
Logical_Page := 0;
Physical_Page := 0;
Error_Code := Map_Expanded_Memory_Pages (Emm_Handle,
Logical_Page,
Physical_Page);
If Error_Code <> STATUS_OK then
Error ('EMM test program failed trying to map '
+ 'logical pages into physical pages.',
Error_Code);
Writeln ('Logical Page ',
Logical_Page,
' successfully mapped into Physical Page ',
Physical_Page);
Writeln;
{------------------------------------------------------------}
{ Get the expanded memory page frame address. }
{------------------------------------------------------------}
Error_Code := Get_Page_Frame_Base_Address
(Page_Frame_Base_Address);
If Error_Code <> STATUS_OK then
Error ('EMM test program unable to get the base Page'
+ ' Frame Address.',
Error_Code);
Writeln ('The base address of the EMM page frame is = '
+ Hex_String (Page_Frame_Base_Address));
Writeln;
Writing Programs That Use Expanded Memory 28
{------------------------------------------------------------}
{ Write a test pattern to expanded memory. }
{------------------------------------------------------------}
For Offset := 0 to 16382 do
Begin
Mem[Page_Frame_Base_Address:Offset] := Offset mod 256;
end;
{------------------------------------------------------------}
{ Make sure that what is in EMM memory is what was just }
{ written. }
{------------------------------------------------------------}
Writeln ('Testing EMM memory.');
Offset := 1;
Verify := True;
while (Offset <= 16382) and (Verify = True) do
Begin
If Mem[Page_Frame_Base_Address:Offset] <> Offset mod 256
then Verify := False;
Offset := Succ (Offset);
end; { while (Offset <= 16382) and (Verify = True) }
{------------------------------------------------------------}
{ If what is read does not match what was written, }
{ an error occurred. }
{------------------------------------------------------------}
If not Verify then
Error ('What was written to EMM memory was not found during'
+ ' memory verification test.',
0);
Writeln ('EMM memory test successful.');
Writeln;
{------------------------------------------------------------}
{ Return the expanded memory pages given to us back to the }
{ EMM memory pool before terminating our test program. }
{------------------------------------------------------------}
Error_Code := Deallocate_Expanded_Memory_Pages (Emm_Handle);
If Error_Code <> STATUS_OK then
Error ('EMM test program was unable to deallocate '
+ 'the EMM pages in use.',
Error_Code);
Writeln (APPLICATION_PAGE_COUNT,
' pages(s) deallocated.');
Writeln;
Writeln ('EMM test program completed.');
end.
Writing Programs That Use Expanded Memory 29
Example 3
This program is written in Microsoft's macro assembler.
CODE SEGMENT
ASSUME CS:CODE, DS:CODE
MOV AX,CS
MOV DX,AX
.
.
.
check_emm_installed:
MOV AH,35h ; AH = DOS get interrupt vector
; function
MOV AL,67h ; AL = EMM interrupt vector number
INT 21h
MOV DI,0Ah ; ES:DI points to where device
; name should be
LEA SI,EMM_device_name ; DS:SI points to ASCII string
; containing EMM device name
MOV CX,device_name_length ; set up loop counter for string op
CLD ; set up direction flag for forward
REPE CMPSB ; Compare the strings
JNE exit ; IF strings not equal THEN exit
; ELSE
check_enough_unallocated_pages:
MOV AH,41h ; AH = EMM get unallocated page
; count function code
INT 67h
OR AH,AH ; Check EMM status
JNZ emm_error_handler ; IF error THEN goto error handler
; ELSE
allocate_expanded_memory_pages:
MOV AH,43h ; AH = EMM allocate pages
; function code
MOV BX,2 ; BX = number of pages needed
INT 67h
OR AH,AH ; Check EMM status
JNZ emm_error_handler ; IF error THEN goto error handler
; ELSE
MOV emm_handle,DX ; save EMM handle
map_expanded_memory_pages:
MOV AH,44h ; AH = EMM map pages function
MOV DX,emm_handle ; DX = application's handle
Writing Programs That Use Expanded Memory 30
map_0_to_0:
MOV BX,0 ; BX = logical page 0
MOV AL,0 ; AL = physical page 0
INT 67h
OR AH,AH ; Check EMM status
JNZ emm_error_handler ; If error THEN goto error handler
; ELSE
get_page_frame_address:
MOV AH,41h ; AH = EMM get page frame base
; address function
INT 67h
OR AH,AH ; Check EMM status
JNZ emm_error_handler ; IF error THEN goto error handler
MOV pf_addr,BX ; ELSE save pf_addr
write_to_expanded_memory: ; Write zeros to memory mapped at
; physical page 0
MOV AX,pf_addr
MOV ES,AX ; ES points to physical page 0
MOV DI,0 ; DI indexes into physical page 0
MOV AL,0 ; Initialize AL for string STOSB
MOV CX,4000h ; Initialize loop counter to length
; of expanded memory page size
CLD ; set up direction flag for forward
REP STOSB
deallocate_pages:
MOV AH,45h ; AH = EMM deallocate pages
; function
MOV DX,emm_handle
INT 67h ; return handle's pages to EMM
OR AH,AH ; Check EMM status
JNZ emm_error_handler ; IF error THEN goto error handler
exit:
MOV AH,4Ch ; AH = DOS exit function
INT 21h ; return to DOS
EMM_device_name DB 'EMMXXXX0' ; ASCII EMM device name string
device_name_length EQU 8
CODE ENDS
END
Writing Programs That Use Expanded Memory 31
Example 4
This program is an example of how to exchange a 256K-byte
block of data from conventional memory to expanded memory.
CODE SEGMENT
ASSUME CS:CODE, DS:CODE
.
.
.
xchg_packet_set_up:
;DS:SI = xchg_packet
MOV AX,SEG xchg_packet
MOV DS,AX
MOV SI,OFFSET xchg_packet
;Moving 256K of data from conventional memory to expanded memory
MOV WORD PTR [SI].region_length[0],0
MOV WORD PTR [SI].region_length[2],4
MOV [SI].src_mem_type,0
MOV [SI].dest_mem_type,1
;starting at segment: 4000h, offset: 0
MOV [SI].src_init_seg_page,4000h
MOV [SI].src_init_offset,0
;Move data into expanded memory logical page 0, offset 0.
MOV [SI].dest_init_seg_page,0
MOV [SI].dest_init_offset,0
;Initialize for future compatibility
MOV [SI].src_handle,0
;Need handle for expanded memory destination.
MOV DX,emm_handle
MOV [SI].dest_handle,DX
;AX = EMM Exchange Memory function
MOV AX,5701h
INT 67h
OR AH,AH
JNZ emm_error_handler
Writing Programs That Use Expanded Memory 32
xchg_struct STRUC
region_length DD ?
src_mem_type DB ?
src_handle DW ?
src_init_offset DW ?
src_init_seg_page DW ?
dest_mem_type DB ?
dest_handle DW ?
dest_init_offset DW ?
dest_init_seg_page DW ?
xchg_struct ENDS
xchg_packet xchg_struct
CODE ENDS
END
Writing Programs That Use Expanded Memory 33
Chapter 3
EMM FUNCTIONS
This chapter provides you with a standardized set of
expanded memory functions. Because they are standardized,
you avoid potential compatibility problems with other
expanded memory programs that also adhere to the memory
manager specification. Programs that deal directly with the
hardware or that don't adhere to this specification will be
incompatible.
Table 3-1 presents a sequential list of the EMM functions.
The remainder of this chapter provides detailed descriptions
of each function.
Table 3-1. List of EMM Functions
----------------------------------------------------------------
Number Function Name Hex Value Page
----------------------------------------------------------------
1 Get Status 40h 37
2 Get Page Frame Address 41h 38
3 Get Unallocated Page Count 42h 40
4 Allocate Pages 43h 42
5 Map/Unmap Handle Page 44h 46
6 Deallocate Pages 45h 49
7 Get Version 46h 51
8 Save Page Map 47h 53
9 Restore Page Map 48h 55
10 Reserved 49h 57
11 Reserved 4Ah 58
12 Get Handle Count 4Bh 59
13 Get Handle Pages 4Ch 61
14 Get All Handle Pages 4Dh 63
EMM Functions 34
Table 3-1. List of EMM Functions (continued)
----------------------------------------------------------------
Number Function Name Hex Value Page
----------------------------------------------------------------
15 Get Page Map 4E00h 65
Set Page Map 4E01h 67
Get & Set Page Map 4E02h 69
Get Size of Page Map Save Array 4E03h 71
16 Get Partial Page Map 4F00h 73
Set Partial Page Map 4F01h 76
Get Size of Partial Page Map
Save Array 4F02h 78
17 Map/Unmap Multiple Handle Pages
(Physical page number mode) 5000h 82
Map/Unmap Multiple Handle Pages
(Segment address mode) 5001h 85
18 Reallocate Pages 51h 88
19 Get Handle Attribute 5200h 92
Set Handle Attribute 5201h 94
Get Handle Attribute Capability 5202h 96
20 Get Handle Name 5300h 98
Set Handle Name 5301h 100
21 Get Handle Directory 5400h 102
Search for Named Handle 5401h 105
Get Total Handles 5402h 107
22 Alter Page Map & Jump
(Physical page number mode) 5500h 109
Alter Page Map & Jump
(Segment address mode) 5501h 109
23 Alter Page Map & Call
(Physical page number mode) 5600h 113
Alter Page Map & Call
(Segment address mode) 5601h 113
Get Page Map Stack Space Size 5602h 118
24 Move Memory Region 5700h 120
Exchange Memory Region 5701h 126
25 Get Mappable Physical Address Array 5800h 132
Get Mappable Physical Address Array
Entries 5801h 136
EMM Functions 35
Table 3-1. List of EMM Functions (continued)
----------------------------------------------------------------
Number Function Name Hex Value Page
----------------------------------------------------------------
26 Get Hardware Configuration Array 5900h 138
Get Unallocated Raw Page Count 5901h 142
27 Allocate Standard Pages 5A00h 144
Allocate Raw Pages 5A01h 147
28 Get Alternate Map Register Set 5B00h 153
Set Alternate Map Register Set 5B01h 157
Get Alternate Map Save Array Size 5B02h 161
Allocate Alternate Map Register Set 5B03h 163
Deallocate Alternate Map Register Set 5B04h 166
Allocate DMA Register Set 5B05h 168
Enable DMA on Alternate Map
Register Set 5B06h 170
Disable DMA on Alternate Map
Register Set 5B07h 173
Deallocate DMA Register Set 5B08h 175
29 Prepare Expanded Memory Hardware
for Warmboot 5Ch 177
30 Enable OS/E Function Set 5D00h 179
Disable OS/E Function Set 5D01h 182
Return OS/E Access Key 5D02h 185
----------------------------------------------------------------
EMM Functions 36
Function 1. Get Status
PURPOSE
The Get Status function returns a status code indicating
whether the memory manager is present and the hardware is
working correctly.
CALLING PARAMETERS
AH = 40h
Contains the Get Status Function.
REGISTERS MODIFIED
AX
STATUS
AH = 0 SUCCESSFUL.
The manager is present in the system, and the hardware
is working correctly.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager is not
defined.
EXAMPLE
MOV AH,40h ; load function code
INT 67h ; call the memory manager
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on error
EMM Functions 37
Function 2. Get Page Frame Address
PURPOSE
The Get Page Frame Address function returns the segment
address where the page frame is located.
CALLING PARAMETERS
AH = 41h
Contains the Get Page Frame Address function.
RESULTS
These results are valid only if the status returned is zero.
BX = page frame segment address
Contains the segment address of the page frame.
REGISTERS MODIFIED
AX, BX
STATUS
AH = 0 SUCCESSFUL.
The manager has returned the page frame address in the
BX register.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager is not
defined.
EMM Functions 38
Function 2. Get Page Frame Address
EXAMPLE
page_frame_segment DW ?
MOV AH,41h ; load function code
INT 67h ; call the memory manager
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on error
MOV page_frame_segment,BX ; save page frame address
EMM Functions 39
Function 3. Get Unallocated Page Count
PURPOSE
The Get Unallocated Page Count function returns the number
of unallocated pages and the total number of expanded memory
pages.
CALLING PARAMETERS
AH = 42h
Contains the Get Unallocated Page Count function.
RESULTS
These results are valid only if the status returned is zero.
BX = unallocated pages
The number of expanded memory pages that are currently
available for use (unallocated).
DX = total pages
The total number of expanded memory pages.
REGISTERS MODIFIED
AX, BX, DX
STATUS
AH = 0 SUCCESSFUL.
The manager has returned the number of unallocated pages
and the number of total pages in expanded memory.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager is not
defined.
EMM Functions 40
Function 3. Get Unallocated Page Count
EXAMPLE
un_alloc_pages DW ?
total_pages DW ?
MOV AH,42h ; load function code
INT 67h ; call the memory manager
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on error
MOV un_alloc_pages,BX ; save unallocated page count
MOV total_pages,DX ; save total page count
EMM Functions 41
Function 4. Allocate Pages
The Allocate Pages function allocates the number of pages
requested and assigns a unique EMM handle to these pages.
The EMM handle owns these pages until the application
deallocates them.
Handles which are assigned using this function will have
16K-byte pages, the size of a standard expanded memory page.
If the expanded memory board hardware isn't able to supply
16K-byte pages, it will emulate them by combining multiple
non-standard size pages to form a single 16K-byte page. All
application programs and functions that use the handles this
function returns will deal with 16K-byte pages.
The numeric value of the handles the EMM returns are in the
range of 1 to 254 decimal (0001h to 00FEh). The OS handle
(handle value 0) is never returned by the Allocate Pages
function. Also, the uppermost byte of the handle will be
zero and cannot be used by the application. A memory
manager should be able to supply up to 255 handles, includ-
ing the OS handle. An application can use Function 21 to
find out how many handles an EMM supports.
Allocating zero pages to a handle is not valid. If an
application needs to allocate 0 pages to a handle it should
use Function 27 (Allocate Standard Pages subfunction)
provided for this purpose.
Note............................................................
This note affects expanded memory manager implementors and
operating system developers only. Applications should not
use the following characteristics of the memory manager. An
application violating this rule will be incompatible with
future versions of Microsoft's operating systems and
environments.
To be compatible with this specification, an expanded memory
manager will provide a special handle which is available to
the operating system only. This handle will have a value of
0000h and will have a set of pages allocated to it when the
expanded memory manager driver installs. The pages that the
memory manager will automatically allocate to handle 0000h
are those that backfill conventional memory. Typically,
this backfill occurs between addresses 40000h (256K) and
9FFFFh (640K). However, the range can extend below and
above this limit if the hardware and memory manager have the
capability.
EMM Functions 42
Function 4. Allocate Pages
An operating system won't have to invoke Function 4 to
obtain this handle because it can assume the handle already
exists and is available for use immediately after the
expanded memory device driver installs. When an operating
system wants to use this handle, it uses the special handle
value of 0000h. The operating system will be able to invoke
any EMM function using this special handle value. To
allocate pages to this handle, the operating system need
only invoke Function 18 (Reallocate Pages).
There are two special cases for this handle:
1. Function 4 (Allocate Pages). This function must never
return zero as a handle value. Applications must always
invoke Function 4 to allocate pages and obtain a handle
which identifies the pages which belong to it. Since
Function 4 never returns a handle value of zero, an
application will never gain access to this special
handle.
2. Function 6 (Deallocate Pages). If the operating system
uses it to deallocate the pages which are allocated to
this special handle, the pages the handle owns will be
returned to the manager for use. But the handle will
not be available for reassignment. The manager should
treat a deallocate pages function request for this
handle the same as a reallocate pages function request,
where the number of pages to reallocate to this handle
is zero.
CALLING PARAMETERS
AH = 43h
Contains the Allocate Pages function.
BX = num_of_pages_to_alloc
Contains the number of pages you want your program to
allocate.
EMM Functions 43
Function 4. Allocate Pages
RESULTS
These results are valid only if the status returned is zero.
DX = handle
Contains a unique EMM handle. Your program must use
this EMM handle (as a parameter) in any function that
requires it. You can use up to 255 handles. The
uppermost byte of the handle will be zero and cannot be
used by the application.
REGISTERS MODIFIED
AX, DX
STATUS
AH = 0 SUCCESSFUL.
The manager has allocated the requested pages to the
assigned EMM handle.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager is not
defined.
AH = 85h RECOVERABLE.
All EMM handles are being used.
AH = 87h RECOVERABLE.
There aren't enough expanded memory pages present in the
system to satisfy your program's request.
AH = 88h RECOVERABLE.
There aren't enough unallocated pages to satisfy your
program's request.
AH = 89h RECOVERABLE.
Your program attempted to allocate zero pages.
EMM Functions 44
Function 4. Allocate Pages
EXAMPLE
num_of_pages_to_alloc DW ?
emm_handle DW ?
MOV BX,num_of_pages_to_alloc ; load number of pages
MOV AH,43h ; load function code
INT 67h ; call the memory manager
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on error
MOV emm_handle,DX ; save EMM handle
EMM Functions 45
Function 5. Map/Unmap Handle Pages
PURPOSE
The Map/Unmap Handle Page function maps a logical page at a
specific physical page anywhere in the mappable regions of
system memory. The lowest valued physical page numbers are
associated with regions of memory outside the conventional
memory range. Use Function 25 (Get Mappable Physical
Address Array) to determine which physical pages within a
system are mappable and determine the segment addresses
which correspond to a specific physical page number.
Function 25 provides a cross reference between physical page
numbers and segment addresses.
This function can also unmap physical pages, making them
inaccessible for reading or writing. You unmap a physical
page by setting its associated logical page to FFFFh.
You might unmap an entire set of mapped pages, for example,
before loading and executing a program. Doing so ensures
the loaded program, if it accesses expanded memory, won't
access the pages your program has mapped. However, you must
save the mapped context before you unmap the physical pages.
This enables you to restore it later so you can access the
memory you mapped there. To save the mapping context, use
Function 8, 15, or 16. To restore the mapping context, use
Function 9, 15, or 16.
The handle determines what type of pages are being mapped.
Logical pages allocated by Function 4 and Function 27
(Allocate Standard Pages subfunction) are referred to as
pages and are 16K bytes long. Logical pages allocated by
Function 27 (Allocate Raw Pages subfunction) are referred to
as raw pages and might not be the same size as logical
pages.
CALLING PARAMETERS
AH = 44h
Contains the Map Handle Page function.
AL = physical_page_number
Contains the number of the physical page into which the
logical page number is to be mapped. Physical pages are
numbered zero-relative.
EMM Functions 46
Function 5. Map/Unmap Handle Pages
BX = logical_page_number
Contains the number of the logical page to be mapped at
the physical page within the page frame. Logical pages
are numbered zero-relative. The logical page must be in
the range zero through (number of pages allocated to the
EMM handle - 1). However, if BX contains logical page
number FFFFh, the physical page specified in AL will be
unmapped (be made inaccessible for reading or writing).
DX = emm_handle
Contains the EMM handle your program received from
Function 4 (Allocate Pages).
REGISTERS MODIFIED
AX
STATUS
AH = 0 SUCCESSFUL.
The manager has mapped the page. The page is ready to
be accessed.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 83h NON-RECOVERABLE.
The memory manager couldn't find the EMM handle your
program specified.
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager isn't
defined.
AH = 8Ah RECOVERABLE.
The logical page is out of the range of logical pages
which are allocated to the EMM handle. This status is
also returned if a program attempts to map a logical
page when no logical pages are allocated to the handle.
EMM Functions 47
Function 5. Map/Unmap Handle Pages
AH = 8Bh RECOVERABLE.
The physical page number is out of the range of allow-
able physical pages. The program can recover by
attempting to map into memory at a physical page which
is within the range of allowable physical pages.
EXAMPLE
emm_handle DW ?
logical_page_number DW ?
physical_page_number DB ?
MOV DX,emm_handle ; load EMM handle
MOV BX,logical_page_number ; load logical page number
MOV AL,physical_page_number ; load physical page number
MOV AH,44h ; load function code
INT 67h ; call the memory manager
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on error
EMM Functions 48
Function 6. Deallocate Pages
PURPOSE
Deallocate Pages deallocates the logical pages currently
allocated to an EMM handle. Only after the application
deallocates these pages can other applications use them.
When a handle is deallocated, its name is set to all ASCII
nulls (binary zeros).
Note............................................................
A program must perform this function before it exits to DOS.
If it doesn't, no other programs can use these pages or the
EMM handle. This means that a program using expanded memory
should trap critical errors and control-break if there is a
chance that the program will have allocated pages when
either of these events occur.
CALLING PARAMETERS
AH = 45h
Contains the Deallocate Pages function.
DX = handle
Contains the EMM handle returned by Function 4 (Allocate
Pages).
REGISTERS MODIFIED
AX
STATUS
AH = 0 SUCCESSFUL.
The manager has deallocated the pages previously allo-
cated to the EMM handle.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 83h NON-RECOVERABLE.
The manager couldn't find the specified EMM handle.
EMM Functions 49
Function 6. Deallocate Pages
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager is not
defined.
AH = 86h RECOVERABLE.
The memory manager detected a save or restore page
mapping context error (Function 8 or 9). There is a
page mapping register state in the save area for the
specified EMM handle. Save Page Map (Function 8) placed
it there and a subsequent Restore Page Map (Function 9)
has not removed it.
If you have saved the mapping context, you must restore
it before you deallocate the EMM handle's pages.
EXAMPLE
emm_handle DW ?
MOV DX,emm_handle ; load EMM handle
MOV AH,45h ; load function code
INT 67h ; call the memory manager
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on error
EMM Functions 50
Function 7. Get Version
PURPOSE
The Get Version function returns the version number of the
memory manager software.
CALLING PARAMETERS
AH = 46h
Contains the Get Version function.
RESULTS
These results are valid only if the status returned is zero.
AL = version number
Contains the memory manager's version number in binary
coded decimal (BCD) format. The upper four bits contain
the integer digit of the version number. The lower four
bits contain the fractional digit of version number.
For example, version 4.0 is represented like this:
0100 0000
/ \
4 . 0
When checking for a version number, an application
should check for a version number or greater. Vendors
may use the fractional digit to indicate enhancements or
corrections to their memory managers. Therefore, to
allow for future versions of memory managers, an
application shouldn't depend on an exact version number.
REGISTERS MODIFIED
AX
STATUS
AH = 0 SUCCESSFUL.
The manager is present in the system and the hardware is
working correctly.
EMM Functions 51
Function 7. Get Version
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager is not
defined.
EXAMPLE
emm_version DB ?
MOV AH,46h ; load function code
INT 67h ; call the memory manager
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on error
MOV emm_version,AL ; save version number
EMM Functions 52
Function 8. Save Page Map
PURPOSE
Save Page Map saves the contents of the page mapping
registers on all expanded memory boards in an internal save
area. The function is typically used to save the memory
mapping context of the EMM handle that was active when a
software or hardware interrupt occurred. (See Function 9,
Restore Page Map, for the restore operation.)
If you're writing a resident program, an interrupt service
routine, or a device driver that uses expanded memory, you
must save the state of the mapping hardware. You must save
this state because application software using expanded
memory may be running when your program is invoked by a
hardware interrupt, a software interrupt, or DOS.
The Save Page Map function requires the EMM handle that was
assigned to your resident program, interrupt service
routine, or device driver at the time it was initialized.
This is not the EMM handle that the application software was
using when your software interrupted it.
The Save Page Map function saves the state of the map
registers for only the 64K-byte page frame defined in
versions 3.x of this specification. Since all applications
written to LIM versions 3.x require saving the map register
state of only this 64K-byte page frame, saving the entire
mapping state for a large number of mappable pages would be
inefficient use of memory. Applications that use a mappable
memory region outside the LIM 3.x page frame should use
Function 15 or 16 to save and restore the state of the map
registers.
CALLING PARAMETERS
AH = 47h
Contains the Save Page Map function.
DX = handle
Contains the EMM handle assigned to the interrupt
service routine that's servicing the software or
hardware interrupt. The interrupt service routine needs
to save the state of the page mapping hardware before
mapping any pages.
EMM Functions 53
Function 8. Save Page Map
REGISTERS MODIFIED
AX
STATUS
AH = 0 SUCCESSFUL.
The manager has saved the state of the page mapping
hardware.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 83h NON-RECOVERABLE.
The memory manager couldn't find the EMM handle your
program specified.
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager is not
defined.
AH = 8Ch NON-RECOVERABLE.
There is no room in the save area to store the state of
the page mapping registers. The state of the map
registers has not been saved.
AH = 8Dh CONDITIONALLY-RECOVERABLE.
The save area already contains the page mapping register
state for the EMM handle your program specified.
EXAMPLE
emm_handle DW ?
MOV DX,emm_handle ; load EMM handle
MOV AH,47h ; load function code
INT 67h ; call the memory manager
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on error
EMM Functions 54
Function 9. Restore Page Map
PURPOSE
The Restore Page Map function restores the page mapping
register contents on the expanded memory boards for a
particular EMM handle. This function lets your program
restore the contents of the mapping registers its EMM handle
saved. (See Function 8, Save Page Map for the save opera-
tion.)
If you're writing a resident program, an interrupt service
routine, or a device driver that uses expanded memory, you
must restore the mapping hardware to the state it was in
before your program took over. You must save this state
because application software using expanded memory might
have been running when your program was invoked.
The Restore Page Map function requires the EMM handle that
was assigned to your resident program, interrupt service
routine, or device driver at the time it was initialized.
This is not the EMM handle that the application software was
using when your software interrupted it.
The Restore Page Map function restores the state of the map
registers for only the 64K-byte page frame defined in
versions 3.x of this specification. Since all applications
written to LIM versions 3.x require restoring the map
register state of only this 64K-byte page frame, restoring
the entire mapping state for a large number of mappable
pages would be inefficient use of memory. Applications that
use a mappable memory region outside the LIM 3.x page frame
should use Function 15 or 16 to save and restore the state
of the map registers.
CALLING PARAMETERS
AH = 48h
Contains the Restore Page Map function.
DX = emm_handle
Contains the EMM handle assigned to the interrupt
service routine that's servicing the software or
hardware interrupt. The interrupt service routine needs
to restore the state of the page mapping hardware.
EMM Functions 55
Function 9. Restore Page Map
REGISTERS MODIFIED
AX
STATUS
AH = 0 SUCCESSFUL.
The manager has restored the state of the page mapping
registers.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 83h NON-RECOVERABLE.
The memory manager couldn't find the EMM handle your
program specified.
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager is not
defined.
AH = 8Eh CONDITIONALLY-RECOVERABLE.
There is no page mapping register state in the save area
for the specified EMM handle. Your program didn't save
the contents of the page mapping hardware, so Restore
Page can't restore it.
EXAMPLE
emm_handle DW ?
MOV DX,emm_handle ; load EMM handle
MOV AH,48h ; load function code
INT 67h ; call the memory manager
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on error
EMM Functions 56
Function 10. Reserved
In earlier versions of the Lotus/Intel/Microsoft Expanded
Memory Specification, Function 10 returned the page mapping
register I/O array. This function is now reserved and new
programs should not use it.
Existing programs that use this function may still work
correctly if the hardware is capable of supporting them.
However, programs that use Functions 16 through 30 in
Version 4.0 of this specification must not use Functions 10
and 11. These functions won't work correctly if your
program attempts to mix the use of the new functions
(Functions 16 through 30) and Functions 10 and 11. Func-
tions 10 and 11 are specific to the hardware on Intel
expanded memory boards and will not work correctly on all
vendors' expanded memory boards.
EMM Functions 57
Function 11. Reserved
In earlier versions of the Lotus/Intel/Microsoft Expanded
Memory Specification, Function 11 returned a page transla-
tion array. This function is now reserved and new programs
should not use it.
Existing programs that use this function may still work
correctly if the hardware is capable of supporting them.
However, programs that use Functions 16 through 30 in
Version 4.0 of this specification must not use Functions 10
and 11. These functions won't work correctly if your
program attempts to mix the use of the new functions
(Functions 16 through 30) and Functions 10 and 11. Func-
tions 10 and 11 are specific to the hardware on Intel
expanded memory boards and will not work correctly on all
vendors' expanded memory boards.
EMM Functions 58
Function 12. Get Handle Count
PURPOSE
The Get Handle Count function returns the number of open EMM
handles (including the operating system handle 0) in the
system.
CALLING PARAMETERS
AH = 4Bh
Contains the Get Handle Count function.
RESULTS
These results are valid only if the status returned is zero.
BX = total_open_emm_handles
Contains the number of open EMM handles [including the
operating system handle (0)]. This number will not
exceed 255.
REGISTERS MODIFIED
AX, BX
STATUS
AH = 0 SUCCESSFUL.
The manager has returned the number of active EMM
handles.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfunction in the expanded
memory hardware.
AH = 84h NON-RECOVERABLE.
The function code passed to the memory manager is not
defined.
EMM Functions 59
Function 12. Get Handle Count
EXAMPLE
total_open_emm_handles DW ?
MOV AH,4Bh ; load function code
INT 67h ; call the memory manger
OR AH,AH ; check EMM status
JNZ emm_err_handler ; jump to error handler on
; error
MOV total_open_emm_handles,BX ; save total active handle
; count
EMM Functions 60
Function 13. Get Handle Pages
PURPOSE
The Get Handle Pages function returns the number of pages
allocated to a specific EMM handle.
CALLING PARAMETERS
AH = 4Ch
Contains the Get Handle Pages function.
DX = emm_handle
Contains the EMM handle.
RESULTS
These results are valid only if the status returned is zero.
BX = num_pages_alloc_to_emm_handle
Contains the number of logical pages allocated to the
specified EMM handle. This number never exceeds 2048
because the memory manager allows a maximum of 2048
pages (32M bytes) of expanded memory.
REGISTERS MODIFIED
AX, BX
STATUS
AH = 0 SUCCESSFUL.
The manager has returned the number of pages allocated
to the EMM handle.
AH = 80h NON-RECOVERABLE.
The manager detected a malfunction in the memory manager
software.
AH = 81h NON-RECOVERABLE.
The manager detected a malfu