home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Der Mediaplex Sampler - Die 6 von Plex
/
6_v_plex.zip
/
6_v_plex
/
DISK5
/
DOS_42
/
XLIB30.ZIP
/
EASYX.DOC
< prev
next >
Wrap
Text File
|
1993-12-20
|
22KB
|
722 lines
EASYX PROGRAMMER'S MANUAL
VERSION 1.0
(DOS Extender Library)
TechniLib Company
Copyright 1993, by TechniLib (TM) Company
All Rights Reserved
TABLE OF CONTENTS
CHAPTERS
Page
1. Introduction 1
2. Initialization of EASYX 2
3. Memory Management 3
4. Memory-Mapped Input/Output 5
5. File Management 6
EXAMPLES
Page
1. EASYX Memory Management 4
2. EASYX File Management 9
1. Introduction
EASYX is a DOS extender library intended for programmers who are
unfamiliar with assembly language. EASYX allows real-mode high-level
languages to perform transfers between extended memory and conventional memory
or between extended memory and disk files. Many programmers need a DOS
extender merely to afford real-mode languages access to extended memory. In
such cases, EASYX is a simple and powerful alternative.
EASYX is actually little more than a real-mode interface to XLIB. The
source code for EASYX is supplied in the XLIB archive (EASYX.ASM). Assembly
language programmers may be interested in examining this code to learn more
about working with XLIB. This code has been assembled and then linked with
XLIB to create EASYX.LIB.
The EASYX library is provided in two formats - one for Microsoft
languages and the other for Borland languages. Microsoft programmers should
use EASYX.LIB. Borland programmers should use EASYXB.LIB. The respective C
header files are EASYX.H and EASYXB.H. Programmers using other languages will
have to write their own prototypes for EASYX procedures. These prototypes
should declare all EASYX procedures as far procedures conforming to the PASCAL
calling and naming convention.
Most EASYX procedures can return error codes. These are always XLIB
error codes. The codes are explained in the XLIB documentation.
1
2. Initialization of EASYX
EASYX requires no initialization; however, the XLIB library which has
been linked with EASYX must be initialized before any EASYX procedures are
called. XLIB is initialized by calling INITXLIB. INITXLIB returns an error
code in DX:AX; therefore, it should be implemented as a long integer function.
The following code demonstrates initialization in Microsoft C:
extern long __far __pascal INITXLIB(void);
void main(void)
{
long errcode;
errcode = INITXLIB();
if(errcode != 0)
{
printf("Initialization error: %lX",errcode);
return;
}
.
.
.
An explanation of possible error codes is explained in the XLIB
documentation. The most common error is caused by insufficient conventional
memory. INITXLIB will attempt to allocate a small amount of conventional
memory through DOS; however, many high-level languages automatically claim all
available DOS memory, even though only a small percentage of this memory may
actually be used. The programmer must therefore release a portion of this
memory back to DOS before calling INITXLIB. This process is illustrated for
the Borland Turbo Assembler in the file EXAMP1B.ASM, and for Microsoft BASIC
in the XLIB documentation. C and C++ programmers need not be concerned with
this matter because these languages allocate DOS memory dynamically.
2
3. Memory Management
High-level languages confined to real mode are incapable of addressing
extended memory; consequently, such languages must communicate with extended
memory through buffers in conventional memory. EASYX provides several
procedures to facilitate this process.
Extended memory should always be allocated with the procedure XMALLOC
before it is addressed. Attempted transfers to or from unallocated memory may
lead to page faults (exception 14), or to corruption of resident software.
XMALLOC returns a long integer error code; therefore, it should be implemented
as a long integer function. The following Microsoft C prototype shows the
structure of XMALLOC:
extern long __far __pascal XMALLOC(long nobytes, long __far *address,
long __far *size, long __far *handle);
where:
nobytes = The requested size for the extended memory block.
*address = A far pointer to a long integer variable which will receive the
linear address of the allocated block.
*size = A far pointer to a long integer variable which will receive the
actual size of the allocated extended memory block. The actual
size will always be at least as large as the requested size.
*handle = A far pointer to a long integer variable which will receive a
handle for the allocated extended memory block. The handle must
be used to release the block.
An extended memory block can be released with the XFREE procedure. XFREE
is also a long integer function which returns an error code. The C prototype
of this procedure is:
extern long __far __pascal XFREE(long handle);
where: handle = The handle assigned to the block by XMALLOC.
All extended memory is automatically released upon program termination;
consequently, XFREE will not be necessary for most programs.
Transfers between conventional memory and extended memory can be
accomplished with the MOVMEM procedure. The prototype for MOVMEM is:
extern void __far __pascal MOVMEM(long destadr, long sourceadr,long nobytes);
where:
destadr = The linear address of the destination memory.
sourceadr = The linear address of the source memory.
nobytes = The number of bytes to be transferred.
3
MOVMEM may actually be used to transfer memory between any source and
destination. The destination block and source block may also be overlapped.
MOVMEM transfers are faster than XMS or INT 15H because MOVMEM uses 32-
bit instructions. MOVMEM also exposes to less risk of losing an interrupt.
Real-mode programs use segment addresses instead of linear addresses.
EASYX includes a procedure called LINADR which computes linear addresses from
segment addresses. The prototype for LINADR is:
extern long __far __pascal LINADR(void __far *ptr);
The following program illustrates the usage of the procedures presented
in this section:
Example 1: EASYX Memory Management
_____________________________________________________________________________
#include <stdio.h>
#include <easyx.h>
void main(void)
{
long errcode, nobytes, xaddress, xsize, xhandle, bufferaddress;
long buffer[1024]; /*4k buffer*/
errcode = INITXLIB(); /*Initialize XLIB*/
if(errcode != 0)
{
printf("Library initialization error: %lX\n",errcode);
return;
}
nobytes = 0x10000; /*Allocate 64k of extended memory*/
errcode = XMALLOC(nobytes, &xaddress, &xsize, &xhandle);
if(errcode != 0)
{
printf("Memory allocation error: %lX\n",errcode);
return;
}
bufferaddress = LINADR(buffer); /*Get linear address of buffer*/
MOVMEM(xaddress, bufferaddress, 4096); /*Transfer buffer to extended*/
MOVMEM(bufferaddress, xaddress, 4096); /*Transfer extended to buffer*/
errcode = XFREE(xhandle); /*Release the extended memory*/
if(errcode != 0)
printf("Memory release error: %lX\n",errcode);
}
_____________________________________________________________________________
4
4. Memory-Mapped Input/Output
On 386 and higher machines, memory reads and writes may undergo address
translation so that the address which is physically accessed may be different
from the address specified in the read/write instruction. The physically
accessed address is the "physical address." The address specified by the
read/write instruction is the "logical address." Normally programmers need
not be concerned with the difference; however, this is not the case if the
program must access an IO device which maps to a fixed physical address. In
such cases, the programmer must obtain a logical address which corresponds to
the physical address of the IO device. EASYX contains a procedure called
MAPIOMEM which will map a specified physical address into a logical address
space. MAPIOMEM is a long integer function which returns an error code. The
prototype for MAPIOMEM is:
extern long __far __pascal MAPIOMEM(long physaddress, long size,
long __far *logaddress);
where:
physaddress = The beginning physical address for the IO device.
size = The size of the physical address block in bytes.
*logaddress = A far pointer to a long integer which is to receive the assigned
logical address. Access the IO device at this address.
MAPIOMEM will sometimes return errors upon attempts to map physical
addresses in the first megabyte.
5
5. File Management
EASYX includes procedures which can transfer data between extended memory
and files. These procedures can load files to extended memory or save
extended memory to files. They can read and write files either sequentially
or randomly.
All EASYX file management routines will receive and return values in a
contiguous block of memory called a "file control block" (not to be confused
with DOS file control blocks). The file control block must be located in
conventional memory and must have the following form:
Field Name Field Type Field Description
---------- ---------- -----------------
CONDCODE DWORD Condition code from file operation
FNAME BYTE[68] File path and name (zero terminated string)
FHANDLE WORD File handle assigned by DOS
FPTRMODE WORD File pointer mode
FPTR DWORD File pointer
BLKADR DWORD Memory source/destination address
BLKSIZE DWORD Size of source/destination block in bytes
BUFADR DWORD Buffer address (conventional memory)
BUFSIZE WORD Buffer size in bytes
CONTROL WORD Control word
CONDCODE is used to return error codes. CONDCODE should be situated at
the starting address of the control block.
FNAME is a zero-terminated ASCII string defining the file path and name.
There cannot be more than 68 characters in this string, including the
termination character.
BLKADR and BLKSIZE define the source/destination memory block for the
transfer. This block may be in either conventional or extended memory.
BLKADR is a linear address.
XLIB uses DOS to access the disk. DOS cannot read or write to extended
memory; consequently, a conventional memory buffer must be set up for the DOS
transfers. File management routines shift to protected mode to perform
transfers between the buffer and the source/destination memory. BUFADR and
BUFSIZE define the conventional memory buffer. BUFADR is a linear address.
For fastest transfers, the memory block and the buffer should be DWORD
aligned and should have sizes equal to an integer multiple of four.
FPTR and FPTRMODE specify the file pointer setting to be used before
intrafile transfers to or from the disk. FPTRMODE specifies how FPTR is to be
interpreted. The following values are valid for FPTRMODE:
FPTRMODE FPTR Interpretation
-------- -------------------
0 Unsigned offset from the beginning of the file
1 Signed offset from the current file pointer
2 Signed offset from the end of the file
3 FPTR is ignored. Use current file pointer (sequential mode)
6
CONTROL is not used in the present version of EASYX. All bits in control
should be set to zero.
Since these routines perform disk operations, special precautions should
be taken to ensure that parameters in the file control block are properly
defined before performing calls. In particular, one should always make sure
that the source/destination memory block and the conventional memory buffer
are properly defined. A safe rule is to simply set the buffer size to zero
because this forces EASYX to supply a buffer when opening or creating the
file.
All EASYX file routines recieve a single argument; namely, the far
address of the control block. Prototypes for the file routines are:
extern void __far __pascal XFCREATE(void __far *controlblock);
extern void __far __pascal XFOPEN(void __far *controlblock);
extern void __far __pascal XFCLOSE(void __far *controlblock);
extern void __far __pascal XFLOAD(void __far *controlblock);
extern void __far __pascal XFSAVE(void __far *controlblock);
extern void __far __pascal XFREAD(void __far *controlblock);
extern void __far __pascal XFWRITE(void __far *controlblock);
The following is a detailed explanation of each of these procedures:
XFCREATE (Create File)
Purpose: Create and open a new file of specified name in specified directory.
Control Block at Call: FNAME = file path and name.
Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
FHANDLE = file handle assigned by DOS. If the procedure is called with
BUFSIZE = 0, then EASYX will set BUFADR and BUFSIZE to its own internal
buffer.
Details:
If the file already exists, then it will be truncated to zero length.
Files created by this routine will be given both read and write access.
XFOPEN (Open File)
Purpose: Open existing file of specified name in specified directory.
Control Block at Call: FNAME = file path and name.
Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
FHANDLE = file handle assigned by DOS. If the procedure is called with
BUFSIZE = 0, then EASYX will set BUFADR and BUFSIZE to its own internal
buffer.
Details: The file is opened for both read and write access.
XFCLOSE (Close File)
Purpose: Close previously opened file.
Control Block at Call: FHANDLE = file handle.
Control Block at Return: CONDCODE = error code.
7
XFSAVE (Save File)
Purpose: Create file with contents equal to specified memory block.
Control Block at Call: FNAME = file path and name. BLKADR/BLKSIZE = address
and size of memory block to provide file contents. BUFADR/BUFSIZE = address
and size of conventional memory buffer.
Control Block at Return: CONDCODE = error code.
Details:
The file cannot already be open. The file is both created and closed by
this routine.
This routine will replace any previously existing file named FNAME.
BLKADR/BLKSIZE may define a conventional memory block provided that this
block is not overlapped by BUFADR/BUFSIZE.
If this routine is called with BUFSIZE = 0, then EASYX will automatically
supply a buffer.
XFLOAD (Load File)
Purpose: Load file contents to specified memory block.
Control Block at Call: FNAME = file path and name. BLKADR/BLKSIZE = address
and size of memory block to receive file contents. BUFADR/BUFSIZE = address
and size of conventional memory buffer.
Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
BLKSIZE = actual number of bytes transferred.
Details:
The file cannot already be open. The file is both opened and closed by
this routine.
The value of BLKSIZE as of call is interpreted as an upper limit on the
number of bytes to transfer. The entire file is loaded provided that it does
not contain more than BLKSIZE bytes.
BLKADR/BLKSIZE may define a conventional memory block provided that this
block is not overlapped by BUFADR/BUFSIZE.
If this routine is called with BUFSIZE = 0, then EASYX will automatically
supply a buffer.
XFWRITE (Write to File)
Purpose: Write specified memory block to specified location in open file.
Control Block at Call: FHANDLE = file handle. FPTR/FPTRMODE = file pointer
setting for beginning of transfer. BLKADR/BLKSIZE = address and size of
memory block to provide file contents. BUFADR/BUFSIZE = address and size of
conventional memory buffer.
Control Block at Return: CONDCODE = error code.
Details:
The file must be opened with XFOPEN or XFCREATE before using this routine.
BLKADR/BLKSIZE may define a conventional memory block provided that this
block is not overlapped by BUFADR/BUFSIZE.
Sequential transfers should set FPTRMODE = 3 for fastest execution.
XFREAD (Read From File)
Purpose: Load specified memory block from specified location in open file.
Control Block at Call: FHANDLE = file handle. FPTR/FPTRMODE = file pointer
setting for beginning of transfer. BLKADR/BLKSIZE = address and size of
memory block to receive file contents. BUFADR/BUFSIZE = address and size of
conventional memory buffer.
Control Block at Return: CONDCODE = error code. If CONDCODE = 0, then
BLKSIZE = the actual number of bytes transferred.
8
Details:
The file must be opened with XFOPEN or XFCREATE before using this routine.
BLKADR/BLKSIZE may define a conventional memory block provided that this
block is not overlapped by BUFADR/BUFSIZE.
Sequential transfers should set FPTRMODE = 3 for fastest execution.
The following C program illustrates the usage of some of the above
procedures:
Example 2: EASYX File Management
_____________________________________________________________________________
#include <stdio.h>
#include <string.h>
#include <easyx.h>
void main (void)
{
int i;
long errcode, nobytes, xaddress, xsize, handle, arrayaddress;
int array[100];
struct xfile fb; /*Declare file control block*/
errcode = INITXLIB(); /*Initialize XLIB*/
if(errcode != 0)
{
printf("Library initialization error: %lX\n",errcode);
return;
}
nobytes = 0x10000; /*Allocate 64k of extended memory*/
errcode = XMALLOC(nobytes,&xaddress,&xsize,&handle);
if(errcode != 0)
{
printf("Extended memory allocation error: %lX\n",errcode);
return;
}
for(i = 0; i < 100; i++) /*Put something in array[]*/
array[i] = i;
arrayaddress = LINADR(array); /*Compute linear address of array[]*/
9
fb.condcode = 0; /*Set control block to create file*/
strcpy(fb.fname,"junk.dat"); /*Specify file name*/
fb.blkadr = arrayaddress; /*Will transfer array[] to the file*/
fb.blksize = 200; /*There are 200 bytes in array[]*/
fb.bufsize = 0; /*Force XLIB to use its internal buffer*/
XFSAVE(&fb); /*Create file and save array[] to it*/
if(fb.condcode != 0)
{
printf("File save error: %lX\n",fb.condcode);
return;
}
XFOPEN(&fb); /*Reopen the file*/
if(fb.condcode != 0)
{
printf("File open error: %lX\n",fb.condcode);
return;
}
fb.blkadr = xaddress; /*Prepare to transfer the file to extended*/
fb.blksize = 100; /*Will transfer only 100 bytes*/
fb.fptrmode = 0; /*File pointer is relative to start of file*/
fb.fptr = 100; /*Set file pointer to 50th element*/
XFREAD(&fb); /*Read last 50 elements to extended*/
if(fb.condcode != 0)
{
printf("File read error: %lX\n",fb.condcode);
return;
}
MOVMEM(arrayaddress,xaddress,100); /*Transfer file contents back to array[]
XFCLOSE(&fb); /*Close the file*/
if(fb.condcode != 0)
{
printf("File close error: %lX\n",fb.condcode);
return;
}
errcode = XFREE(handle); /*Release extended memory*/
if(errcode != 0)
{
printf("Memory release error: %lX\n",errcode);
return;
}
}
_____________________________________________________________________________
10