Dec 192017
 
Turbo C source to write protected mode programs that can access megs of memory including virutal memory on any machine running windows 3.0 in 386 enhanced mode through the Dos Protected Mode Interface.
File DPMI_LIB.ZIP from The Programmer’s Corner in
Category C Source Code
Turbo C source to write protected mode programs that can access megs of memory including virutal memory on any machine running windows 3.0 in 386 enhanced mode through the Dos Protected Mode Interface.
File Name File Size Zip Size Zip Type
DPMI.H 1854 674 deflated
DPMI.TXT 10604 3302 deflated
DPMIUTIL.C 13677 3843 deflated
DPMIUTIL.OBJ 12302 6583 deflated
DPMI_V1.C 3461 1090 deflated
DPMI_V1.EXE 10734 6417 deflated
DPMI_V1.MAK 303 127 deflated
DPMI_V1.PIF 545 313 deflated
DPMI_V2.C 1645 688 deflated
DPMI_V2.EXE 15032 9274 deflated
DPMI_V2.MAK 303 130 deflated
DPMI_V2.PIF 545 313 deflated

Download File DPMI_LIB.ZIP Here

Contents of the DPMI.TXT file


The C-Library for DPMI-Specification 0.9 and Protected Mode

This is a short documentation for the interface functions. For details, read the
DPMI-specification 0.9 . Protected Mode is discribed in some special books like
Ray Duncan "Extended Dos".

This library allows DOS-programs to run in protected mode.The great advantage is
the big address space. You can use the DPMI Interface 0.9 functions only in
enhanced mode in Windows 3.0 . In standard mode the function real_to_protected
is not supported. So you can't use the other funtion using int 31H.
A 286 computer can only use DPMI-functions in a Window-program, but i don't know
if this is useful.I hope other programs will support the DPMI-Interface.

The most compiler run in 16-bit mode. The limit for the selectors should be
set to 64KB. The functions extmalloc for example creates a continue array of
selectors if you allocate more than 64KB. This is neccesary, because you can't
address the whole space with a 16-bit compiler pointer,if you have only one
descriptor(limit more than 64KB). The library can be modified to run 32-bit
programs.

There are some printf statements in the protected mode code. This is allowed,
because Windows provides a DOS-Extender.In other Environments this may be not
and you must write a protected mode handler for int 21h.

The library is not complete. Some of the DPMI 0.9 functions miss here.
In a next update i will complete it.
The c-code is for TurboC/Tasm but there are only few special TurboC statements.
Look in the files 'dpmiutil.c' and 'dpmi.h'.

Execute the files in the DosBox or from the File-manager. Be sure that the
PIF-files are there. This is neccessary because program memory must be locked.
Don't execute from the Turbo-Shell. This can cause a system-crash.

Files include in dpmi_lib.zip:

dpmi.txt : this file
dpmiutil.c : Main C-file include the Dpmi/PM -library
dpmiutil.obj : Object-file
dpmi.h : Header file for dpmi programs
dpmi_v1.exe : Demo 1 : shows the System-Tables used in Protected Mode
dpmi_v1.c : sources demo1
dpmi_v1.mak : Makefile demo1
dpmi_v1.pif : Windows 3.0 386/PIF-file for demo1
dpmi_v2.exe : Demo 2 : memory info and test program
dpmi_v2.c : sources demo2
dpmi_v2.mak : Makefile demo2
dpmi_v2.pif : Windows 3.0 386/PIF-file for demo2

If you already work with protected mode or you have some questions send mail to

Email Number : [email protected]

Home Address: Rainer Schnitker , Heeper Stasse 283 , 4800 Bielefeld , Germany



In "DPMI.H" you can find the following structures:

1. struct {
WORD lim_lo,base_lo;
BYTE base_mi,access;
BYTE lim_hi,base_hi;
} DESCRIPTOR ;
this is the main structure in protected mode

2. struct {
WORD limit,lo,hi ;
} GDTR ;
this structure is used to call the instruction sgdt
( save Global Descriptor Table )

3. struct {
WORD off_lo;
WORD sel;
BYTE count;
BYTE type;
WORD off_hi;
} GATE;
this structure is used in the IDT


The structure
struct { DWORD i1,i2,i3,i4,i5,i6,i7,i8,i9,r1,r2,r3 ;
} FREEMEMINFO;
is used in DPMI memory info (see below).

The line
#define DPMI(function) { _AX = function ; __int__(0x31) ; }
calls the DPMI Interface via int 31h


THE DPMI INTERFACE :

* CPU switching for DPMI 0.9

void real_to_protected(void);
- call this function switch the cpu in protected mode
- other funtions are not execute if this function fails
- cs,ds,es were set by the dpmi host

void protected_to_real(void);
- switch cpu back to real mode
- terminates the program ( like real mode int21,function 4c)

* LDT Descriptor management services DPMI 0.9

WORD AllocLDT(WORD n);
- this allocates n descriptors from the Local Descriptor Table
- return value of the first selector , 0 on error
- add the value returned from function SelInc() to get the next selector
- the descriptors will be set to present data type, base=0 , limit=0

int FreeLDT(WORD selector);
- this function is used to free descriptors that were allocated
by the function AllocLDT() ,
- return 0 : successful -1 : not successful

WORD SegtoSel(WORD realsegment);
- this converts real mode segments into descriptors
- return selector with limit 64 KB , or 0 on error

WORD SelInc(void);
- return the increment value to get the next selector (typical 8).
- function can't fail

int LockSel(WORD selector);
- undocumented function ("should not be called")
- this locks the address area of the selector
- return 0 : successful -1 : not successful

int UnlockSel(WORD selector);
- undocumented function ("should not be called")
- this function is used to unlock the memory area
- return 0 : successful -1 : not successful

DWORD GetBaseAddress(WORD selector);
- return the 32-bit-address of the selector , 0 on error

int SetBaseAddress(WORD selector ,DWORD 32bitaddress);
- set the base address of the specified selector
- return 0 : successful -1 : not successful

int SetLimit(WORD sel,DWORD limit);
- set the limit for the selector
- if limit>1MB low 12 bits must be set
then the granular bit will be set
- return 0 : successful -1 : not successful
- to get the limit use the function lsl()

int SetAccess(WORD,BYTE accessbyte,BYTE 386extendedbyte);
- set access rights for the selector
- return 0 : successful -1 : not successful
- to get the access right use the function lar()

WORD CreatAlias(WORD codeselector);
- this creates a data descriptor with the same address and limit as
the code descriptor
- return 0 if the function was not successful

int AllocSpecialLDT(WORD selector);
- this allocates a specific LDT descriptor
- return 0 : successful -1 : not successful

int GetDescriptor(WORD selector,DESCRIPTOR *buffer);
- this copies the 8 bytes descriptor table into the buffer
- return 0 : successful -1 : not successful

int SetDescriptor(WORD selector,DESCRIPTOR *buffer);
- this function is used to set a descriptor
- return 0 : successful -1 : not successful

* Interrupt Services DPMI 0.9

int GetExceptionVektor(BYTE intnumber,WORD *selector,WORD *offset);
- give the current protected mode exception handler
- return 0 : successful -1 : not successful

int SetExceptionVektor(BYTE intnumber,WORD selector,WORD offset);
- set new protected mode exception handler
- read DPMI-specification 0.9 for some details
- return 0 : successful -1 : not successful

int GetPMinterruptVector(BYTE,WORD *selector,WORD *offset);
- get the current protected mode interrupt handler
- return 0 : successful -1 : not successful

int SetPMinterruptVektor(BYTE,WORD selector,WORD offset);
- set new protected mode interrupt handler
- return 0 : successful -1 : not successful

* Memory management services DPMI 0.9

void getfreeinfo(FREEMEMINFO *);
- get struct contains free mem info

void printfreeinfo(FREEMEMINFO *);
- this prints a free memory info

DWORD GlobalAlloc(DWORD bytes,DWORD *memhandle);
- allocate memory block , size = bytes
- in Windows you get memory page granular. This means that allocation
of 534 bytes allocate 4096 = 4 KB.
- return linear address of allocated block , 0 on error
- memhandle is used to free memory blocks

int GlobalFree(DWORD memhandle);
- frees a memory block that was allocate though GlobalAlloc()
- return 0 : successful -1 : not successful

* Page locking services DPMI 0.9

int LockLinRegion(DWORD size,DWORD linaddress);
- locks linear address range , size = region to lock
- return 0 : successful -1 : not successful

int UnlockLinRegion(DWORD size,DWORD linaddress);
- unlock linear address range
- return 0 : successful -1 : not successful

* other int 2F

void Yield(void);
- call int 2F function 1680h
- useful in a program loop in a multitasking environment like Windows
( like GetMassage )


The Protected Mode Interface:

DWORD lsl(WORD selector);
- load selector limit
- uses 32-bit commands , only for >386
- 286 must use lsl16()

WORD lsl16(WORD selector);
- load selector limit on 286 machines

WORD lar(WORD selector);
- load selector access rights

WORD verr(WORD selector);
- verify if read flags is set
- return 1 : read 0 : not

WORD verw(WORD selector);
- verify if write flag is set
- return 1 : write 0 : not

void sgdt(GDTR *gdtregister);
- save GDT base address and limit

void sidt(GDTR *idtregister);
- save IDT base address and limit

WORD sldt(void);
- save LDT selector
- return LDTselector

WORD str(void);
- save task register
- return TASKselector

* protected mode pointer

void far * incfp(void far *);
- increment descriptor to the next

void far * decfp(void far *);
- decrement descriptor to the next

void printdescriptor(DESCRIPTOR);
- print the 8 bytes from the descriptor table

void farcopy(void far *dest,void far *source,DWORD bytes)
- copy memory block from far pointer to far pointer
- bytes must min(limit-dest,limit-source) , ( -> GP-fault)
- useful to copy pointers given by extmalloc(more then 64KB)

* high level memory functions in the DPMI-Enviroment:

void far *extmalloc(DWORD nbytes);
- allocates n bytes
- if n is greater than 64 KB then continues descriptors will be
allocated. To access the next descriptor add the value return by
function IncSel() to the base selector
- return base selector , NULL if insufficient memory available

void extfree(void far *filepointer);
- frees memory that was allocated by extmalloc()


 December 19, 2017  Add comments

Leave a Reply