[Back to MEMORY SWAG index] [Back to Main SWAG index] [Original]
{
XDR> I'm currently developing an application that I would gladly spread in
XDR> protected mode... But could someone explain to me what can I NOT do in
XDR> DPMI pascal
This is actually explained quite clearly in Ch. 17 of the BP7 Language Guide.
The main difference is that memory is no longer yours to do with as you
please; you can only "touch" memory that has been allocated to your program.
This is where the "protected" in "protected mode" stems from.
The following is a rather simplified view of things, but it does illustrate
the general priciple:
In pmode a pointer such as ptr($B800, 0) does NOT point to memory location
$B800:0000. The segment part (called the "selector" in pmode), $B800,
is treated as an index into a system maintained table, which *does* contain
the actual physical memory location (called the "base"), and the number of
bytes allocated to that base (called the "limit"). This table is unavailable
to your program.
At the start of your program, all entries in this table are marked "not in
use" and therefore illegal.
During program execution, whenever you attempt to read or write Mem[S:O],
the CPU checks (in that table) to see if S is a legal index (i.e., if S is
a valid base), and if so, whether O is within the limit of that base.
If at least one of these checks fail, the memory access is invalid, and you
will be presented with run time error 216 a.k.a. the dreaded General
Protection Failure (GPF) a.k.a. Exception $0D.
XDR> Ag: I can no more acces the screen at an Obsolute $b800:000 but at
XDR> absolute Segb800:000, why?
Btw: ABSOLUTE SegB800:0 won't compile.
Use "mem[SegB800:0]" instead, or use a pointer, like so:
VAR VidMemStart: pointer;
BEGIN VidMemStart:=ptr(SegB800, 0) END;
and manipulate video memory using VidMemStart^.
The reason should now be clear: $B800 is almost certainly *not* a valid
selector. Since no one has asked the DPMI server to associate selector $B800
with a physical memory location, it is illegal.
You *can* use SegB800, as your program startup code asks the DPMI server to
associate SegB800 with video memory.
You should not pass pmode pointers to real mode routines nor the other way
around (they are invalid in the "receiving" mode).
It can be done, but you'll need the cooperation of the DPMI server.
Find a DPMI unit (I can't post mine, as it is commercial). Below you'll
find such a unit - I've never used it, so no guarantees.
Notes: - if you attempt to write to code segments, or read from invalid
pointers, a GPF will result.
- if you attempt to read an invalid stack element, you will receive
an Exception $0C (Stack Fault), which BP will convert to run time
error 202.
- Exception 6 (Invalid Opcode) is not related to memory accesses.
It means the CPU has received a couple of bytes which it cannot
interpret as a valid instruction.
- prior to distribution, be sure to read file DPMIUSER.DOC.
You can find that file in archive DOC.ZIP on your BP7 distribution
disks.
The above three exceptions are likely the only ones you'll see.
Happy programming,
Peter. }
===== Start of includefile FDEFINE.DEF =====
{ Include file FDEFINE.DEF - general include file for the unit systems
conditional defines }
(***************************************************************************
RELEASE 1.04 - as contained in the file PRUS100.LZH
by Orazio Czerwenka, 2:2450/540.55, GERMANY
--------------------------------------------
organized for Fido's PASCAL related echoes
--------------------------------------------
06/21/1994 to --/--/---- by Orazio Czerwenka, 2:2450/540.55, GERMANY
***************************************************************************)
{ ==========================================================================
WHICH VERSION OF TURBO PASCAL DO YOU COMPILE WITH ?
THE DEFAULT IS TURBO PASCAL 6.0x !
========================================================================== }
{ The following conditional defines do not yet have any effect, ... }
{.$define ver30} { Turbo Pascal 3.0x }
{.$define ver40} { Turbo Pascal 4.0x }
{.$define ver50} { Turbo Pascal 5.0x }
{.$define ver55} { Turbo Pascal 5.5x }
{$define ver60} { Turbo Pascal 6.0x }
{.$define ver70} { Turbo/Borland Pascal 7.0x }
{ ... these commenting lines will be deleted once that should be changed. }
{ ==========================================================================
WHAT LANGUAGE DO YOU WANT YOUR PROGRAMS TO DISPLAY MESSAGES IN BY DEFAULT?
========================================================================== }
{$define English}
{.$define German}
{ ==========================================================================
ACTIVATE THE FOLLOWING DISABLED COMPILER DIRECTIVE IF YOU WANT TO BE ABLE
TO USE THE UNIT SYSTEM FROM WITHIN OVERLAYS !
========================================================================== }
{.$O+} { This tells your compiler - if activated - to produce a unit
that will be allowed to be used from within overlays. }
{$IFOPT O+}
{$DEFINE Overlays} { easier to read }
{$ENDIF}
{ ==========================================================================
WHAT KIND OF PROCESSOR ARE YOU COMPILING FOR ? SOME CPU DEPENDEND DEFINES.
========================================================================== }
(* Some of the units use inline assembler designed to work on machines
with at least 80286 processor, so generally you can tell your compiler
to produce 80286 code anyway.
*)
{$G+} { This tells - if activated - your compiler to produce 80286
code. }
(* In addition you might want to specify one of the following higher
processors, if you want your programmes ONLY to run on THESE and
higher machines.
*)
{ The following conditional defines do not yet have any effect, ... }
{.$define cpu386} { Use specific code for 80386 machines }
{.$define cpu486} { Use specific code for 80486 machines }
{ ... these commenting lines will be deleted once that should be changed. }
{ -------------------------------------------------------------------------- }
(* Define one of the following CRT replacements (or CRT) for use by the
units FTMODE and FSPEAKER, depending on what you've got.
If you don't have a replacement, take the CRT, it is a bit slower but
it should work as well.
-----------------------------------------------------------------------
NOTICE THAT THE UNIT FCRT SHOULD ALSO BE INCLUDED IN THIS FILE PACKAGE!
-----------------------------------------------------------------------
Note that at least one of those units shoul be defined to be used !
By default this should be the unit FCRT.
In case you should also want to use TP CRT's screen handling related
functions in addition to the routines provided by FCONDRV and FCRT
you probably will have to define the usage of TP's CRT here.
By default the usage of TP's CRT is *NOT* defined in order to avoid
smaller drawbacks in speed and unnecessarilly 'blown up' code.
*)
{$define FCRT}
{.$define CRT}
{.$define CRT2}
{ -------------------------------------------------------------------------- }
(* The following conditional define will specify wether the unit(s) FTMODE
will use the BIOS for the 80x25 mode or try programming it by hand. You
should leave it inactivated, since who would want to force the user to
use 80x25 ? I (MM) implemented it, since on my system, mode 3 corresponds
to 90x28 through a TSR, and a small program would have helped here :-)
Note that forcing will only take place if FTMODE's SetVideoMode(3) does
not result in an 80 column mode.
*)
{.$define UseBIOS}
{ -------------------------------------------------------------------------- }
===== End of includefile FDEFINE.DEF =====
===== Start of unit FDPMI =====
Unit FDPMI; { routines for DOS/DPMI communication }
(***************************************************************************
RELEASE 1.00 - as contained in the file PRUS100.LZH
by Max Maischein, 2:244/1106.17, GERMANY
--------------------------------------------
organized for Fido's PASCAL related echoes
--------------------------------------------
06/15/1994 to --/--/---- by Max Maischein, 2:244/1106.17, GERMANY
As far as third party copyrights are not violated this
source code is hereby placed to the public domain. Use
it whatever way you want, but use AT YOUR OWN RISK.
In case you should modify the source rather send your
modifications to the unit's current organizer (see above for
NM address) than to spread it on your own. This will help to
keep the unit updated and grant a certain standard to all
other users as well.
The unit is currently still under work. So it might greatly
benefit of your participation.
Those who contributed to the following piece of source,
listed in alphabethical order:
================================================================
Jochen Magnus (SEGDEMO.PAS), Max Maischein (collecting,
documenting, testing etc.), Raphael Vanney (program CHARSET
.PAS)
================================================================
YOUR NAME WILL APPEAR HERE IF YOU CONTRIBUTE USEFUL SOURCE.
***************************************************************************)
{$I FDEFINE.DEF}
Interface
Type TRealModeRegs =
Record
Case Integer Of
0: ( EDI, ESI, EBP, EXX, EBX, EDX, ECX, EAX: Longint;
Flags, ES, DS, FS, GS, IP, CS, SP, SS: Word) ;
1: ( DI,DIH, SI, SIH, BP, BPH, XX, XXH: Word;
Case Integer of
0: (BX, BXH, DX, DXH, CX, CXH, AX, AXH: Word);
1: (BL, BH, BLH, BHH, DL, DH, DLH, DHH,
CL, CH, CLH, CHH, AL, AH, ALH, AHH: Byte));
End;
(* Use these and RealModeInt() instead of Registers and Intr() under DPMI *)
Type TLongRec = Record
Case Byte of
0 : ( L : LongInt );
1 : ( wLo : Word;
wHi : Word; );
2 : ( iLo : Integer;
iHi : Integer );
End;
Function RealModeInt( IntNo : Byte; Var RealRegs : TRealModeRegs) : Boolean;
(* Replacement for Intr(), returns False on error *)
Function NewSelector( Base, Limit : Longint) : Word;
(* Returns a new selector for the range [Base - (Base+Limit)] *)
(* Base is the linear address of the memory location you want to use *)
(* You must free this selector after use with FreeSelector() *)
Function AllocateLowMem( Size : Word; var PMPointer : Pointer ) : Word;
(* Allocates some memory in the first MB *)
(* Returns a pointer to it and a segment to pass to the real mode routine *)
Procedure FreeLowMem(Var PMPointer : Pointer );
(* Frees memory allocated with AllocateLowMem() *)
Implementation
Uses WinAPI;
Function RealModeInt( IntNo : Byte; Var RealRegs : TRealModeRegs) : Boolean;
Assembler;
{ This function switches to real mode and issues the specified interrupt,
after filling the registers with values stored in RealRegs.
If SS/SP as specified in RealRegs are Nil, the DPMI server provides a
small stack. For more discution of this, see Ralf Brown's INTERxx.ZIP }
Asm
mov ax, 0300h { DPMI function "simulate real
mode int" }
mov bl, [IntNo]
xor bh, bh { 0 as requested by DPMI v1.0
} xor cx, cx { bytes to copy onto "remote"
stack }
les di, [RealRegs]
int 31h { Returns CF set on error }
mov ax, 1 { assume everything went OK }
sbb ax, 0 { if carry set, decrement ax }
{ to signal an error }
End;
Function NewSelector(Base,Limit:longint) : Word;
Var Sel : Word;
Begin
Sel := AllocSelector(0);
If (sel<>0) and (setSelectorBase(sel,base)=sel) and (setSelectorLimit(sel,
limit)=0)
then newSelector:=sel
else newSelector:=0;
End;
Function AllocateLowMem( Size : Word; var PMPointer : Pointer ) : Word;
{ This procedure allocates memory in the first megabyte, and returns two
ways of accessing it : a pointer valid in protected mode, and the
segment part of a pointer valid in real mode ; offset part is always 0 }
Var Adr : LongInt ;
Begin
Adr:=GlobalDOSAlloc(Size) ;
If Adr=0 then RunError( 0 );
PMPointer := Ptr( TLongRec(Adr).wLo, 0);
AllocateLowMem := TLongRec(Adr).wHi;
End ;
Procedure FreeLowMem(Var PMPointer : Pointer ) ;
{ Frees memory allocated with AllocateLowMem }
Begin
GlobalDOSFree(Seg( PMPointer^ ));
PMPointer := nil;
End ;
{$IFnDEF DPMI}
{$IFnDEF Windows}
You are compiling WHAT ??
{$ENDIF}
{$ENDIF}
End.
===== End of unit FDPMI =====
[Back to MEMORY SWAG index] [Back to Main SWAG index] [Original]