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 : rainer@math5.uni-bielefeld.de 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()