home *** CD-ROM | disk | FTP | other *** search
- {$R-} {Range checking off}
- {$B+} {Boolean complete evaluation on}
- {$S+} {Stack checking on}
- {$I+} {I/O checking on}
- {$N-} {No numeric coprocessor}
- {$M 65500,16384,655360} {Turbo 3 default stack and heap}
-
- { $p256}
- {!^ 1. Directives A,B,C,D,F,G,P,U,W,X are obsolete or changed in meaning}
- Program ems_demo;
- { This program is a demo of the use of EMS procedures in Turbo Pascal. }
- { Public Domain by Peter Handsman. GEnie Mail: P.Handsman }
- { Any problems or damage this program does is NOT my fault! }
- { I therefore take no responsibility whatsoever. }
- { Keeping that in mind I welcome and comments or questions or bug reports}
- { }
- { The program start's out by checking if you have EMS installed... }
- { Moves on to a short demo of allocating memory and what happens to }
- { free EMS memory. Then Runs the Sieve of Erat(who knows?) with the }
- { data array in an allocated part of EMS memory. }
- { }
- { EMS memory is the specification by Lotus/Intel/Microsoft for a banked }
- { memory scheme. The PD file Limspec.arc defines the spec. }
- { This program was written on a IBM PC with a AST Rampage! board }
- { (But it does not use the extended spec's) and the source is in }
- { Turbo Pascal 3.01a. }
-
-
- Uses
- Dos; {Unit found in TURBO.TPL}
-
- const
- SIZE = 8190; { Used by the prime sieve.}
-
- type
- registers= record { 8088 regester type. }
- ax,bx,cx,dx,bp,si,di,ds,es,flags:integer;
- {! 2. Instead use the Registers type from the^ Turbo 5.0 DOS unit.}
- end;
- handle_rec=record { Handle map record type. }
- handle: integer;
- numpages:integer;
- end;
- pages= array[0..255] of handle_rec;
- pages_ptr= ^pages;
- arr = record { the following types are }
- flag: array[0..8191] of byte; { used by the prime sieve. }
- end;
- parr = ^arr;
-
- var
- han: integer; { Holds the handle returned by alloc}
- regs: registers; { Holds the 8088 regester set. }
- handles: integer; { Holds number of used handles. }
- map: pages_ptr; { Ptr to ems page map. }
- segm: integer; { Holds segment of ems window. }
- f: parr; { Ptr to prime data array. }
- j,k,count: integer; { Misc var's for prime sieve. }
- prime: integer; { Holds prime number. }
-
- procedure error_handler(error_num:integer);
- { This is a lame error handler... all it does is print out a }
- { message and halt, setting ERRORLEVEL to the error number. }
- { Since some errors are not fatel, i.e. not enough free pages }
- { You should include more code here to trap specific errors. }
- { A listing of what the error numbers mean is in the }
- { Limspec.arc public domain file... }
- begin
- writeln('EMS Error number: ',error_num,' has occured...');
- halt(error_num)
- end;
-
- function cnvt_bcd_bytes(i:integer):real;
- { This function takes a bcd number then converts it to bytes. }
- { The bcd number is of the format xxxxyyyy in binary where }
- { the number is the number of pages (16k to a page) }
- begin
- cnvt_bcd_bytes:=(256.0*hi(i)+lo(i))*1024.0*16.0;
- end;
-
- function ems_installed:boolean;
- { This function checks to see if a ems board is installed... }
- { If you have a ems board and haven't installed the device }
- { which controls it, (the EMM manager) then it will respond }
- { as if you don't have such a board. }
- var
- f:file;
- begin
- assign(f, 'EMMXXXX0');
- {$I-} reset(f) {$I+} ;
- ems_installed:=(ioresult=0)
- {! 3. IOResult now re^turns different values corresponding to DOS error codes.}
- end;
-
- procedure emm_call(var regs:registers; ah:integer);
- { This procedure makes a call to the emm device and executes }
- { the function specified in the ah parameter... also it calls }
- { the error_handler if the emm manager returns an error msg. }
- begin
- regs.ax:=ah*$100;
- intr($67,Dos.Registers(regs));
- {! 4. Paramete^r to Intr must be of the type Registers defined in DOS unit.}
- if hi(regs.ax)<>0 then error_handler(hi(regs.ax));
- end;
-
- procedure print_map(var page_map:pages; handles:integer);
- { This procedure obtains the page_map from the EMM device and }
- { prints it out in a readable form. }
- var
- h:integer;
- begin
- regs.es:=seg(page_map); { call with the address where }
- regs.di:=ofs(page_map); { you want the map to be placed.}
- regs.bx:=0;
- emm_call(regs,$4d);
- writeln;
- writeln('Handle bytes');
- writeln('------ ------');
- for h:=0 to handles-1 do
- writeln(h:5, ' ',cnvt_bcd_bytes(page_map[h].numpages):8:0)
- end;
-
- procedure show_info;
- { This procedure prints out some information on the current }
- { state of the ems memory and the memory handler. }
- begin
- emm_call(regs,$4b); { Get the total number of handles }
- handles:=regs.bx; { in use. }
- getmem(map,4*handles);
- print_map(map^,handles);{ Get the free and total space. }
- emm_call(regs,$42);
- writeln(' free: ',cnvt_bcd_bytes(regs.bx):8:0);
- writeln('total: ',cnvt_bcd_bytes(regs.dx):8:0);
- emm_call(regs,$46);
- writeln('The EMM version is: ',lo(regs.ax)/16:2:0,'.',lo(regs.ax) mod 16:1)
- end;
-
- procedure alloc(num:integer;var handle:integer);
- { This procedure allocates num pages(16k) of ems memory which }
- { can be refered to by the map handle. }
- { WARNING: if you allocate memory and don't deallocate it the }
- { memory will be lost till power off. }
- begin
- regs.bx:=num;
- emm_call(regs,$43);
- handle:=regs.dx
- end;
-
- procedure unalloc(handle:integer);
- { This procedure unallocates ems memory. You MUST have the }
- { handle number or you can't unallocate anything! }
- begin
- regs.dx:=handle;
- emm_call(regs,$45);
- end;
-
- procedure get_page_frame(var address:integer);
- { This procedure gets the segment address of the start of where}
- { the ems memory will be maped onto the normal 8088 memory }
- { address space... }
- begin
- emm_call(regs,$41);
- address:=regs.bx
- end;
-
- procedure set_page(logical_page,physical_page,handle:integer);
- { This procedure sets the logical page onto one of the four }
- { physical pages which the normal lim spec's provide for. }
- { }
- { Logical_Page is from 0 to the number of pages allocated }
- { for that handle-1. }
- { Physical_Page is one of the four(0-3) pages. This will over- }
- { write any previous calls so use differnt ones }
- { until you don't need the old logical page for }
- { a while. }
- { }
- { Offsets from the page_frame segment are: }
- { page:offset 0:0000 1:4000 2:8000 3:C0000 in hex. }
- begin
- regs.ax:=($44*$100)+physical_page;
- regs.bx:=logical_page;
- regs.dx:=handle;
- intr($67,Dos.Registers(regs));
- if hi(regs.ax)<>0 then error_handler(hi(regs.ax))
- end;
-
- procedure sieve(f:parr);
- { This is a sieve demo... using a array in EMS memory. }
- begin
- writeln(' interations: 1 ') ;
- count:=0;
- for j:=0 to SIZE do f^.flag[j]:=1;
- for j:=0 to SIZE do
- if f^.flag[j]=1 then begin
- prime:= j + j + 3 ;
- write(prime,' '); { Comment out this line to drop prime printing}
- k:=j+prime;
- while (k<=size) do begin
- f^.flag[k]:=0;
- k:=k+prime
- end;
- count:=count+1
- end;
- writeln('Primes found.=', count )
- end;
-
- begin
- if ems_installed then begin { Otherwise just print out msg.}
- show_info; { Trivial show of just what }
- alloc(2,han); { happens to free ems memory...}
- show_info; { . }
- unalloc(han); { . }
- show_info; { . }
- alloc(1,han);
- get_page_frame(segm); { Setup for ems memory usage. }
- set_page(0,0,han); { Set logical page to physical.}
- f:=ptr(segm,$0000); { Set ptr to absolute address. }
- sieve(f); { For above see p207 in tpas manual}
- unalloc(han);
- end else writeln('No EMS manager installed.')
- end.