EMS Memory Specification


Plasma357 posted a link to this document on the forum:



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;


EmsMemorySpecification - page last edited 2003-08-25 17:01:07 by 81.203.197.39 (home) (edit)
Blast WIKI - by RoboticBoy - edited and tweaked for our evil purposes by Hexadecimal Disaster