home *** CD-ROM | disk | FTP | other *** search
- Type
- Str = String[128];
-
- Procedure Shrink; Forward
-
- Function Shell(es,ds,dx,bx : Integer) : Integer; Forward;
-
- Function Load(pgm_name,parm : Str) : Integer; Forward;
-
- Function Dos(pgm_name,parm : Str) : Integer; Forward;
-
- {
- These functions and procedures allow one to "shrink" the size of one's
- Turbo Pascal program so that you can later invoke the DOS load function.
- Function Shell is primarily intended to be called internally by the
- Load function. ES:BX point to the parameter block as defined in the
- Dos manual, and DS:DX point to the ASCIIZ string containing the program
- name. It returns either a positive integer containing the program's
- return code as obtained from Dos function $4D, or a negative integer,
- with the low order byte being the Dos return code on why the program
- couldn't be loaded. Function Load is passed the program name and
- the parameter to be passed to the program, each specified as a Turbo
- string. The program name is converted in to an ASCIIZ string and the
- parameter string is appended with a CR and a Blank at the start. The
- Dos Parse function is also invoked to parse the parameter string into
- FCB1 and FCB2. The addresses of the current environment, the command
- line and the FCB's are filled into the parameter block and Shell is
- invoked. The integer return code is the same as passed back from
- Shell. Function Dos is similar to Load, except that a secondary
- command processor is invoked. The current environment is searced
- for the name specified in COMSPEC and is used as the program name.
- The command string is made up of a "/C ", the Dos command, and
- the parameter string to pass to the Dos command. Function Load
- is invoked to do the rest. The integer return code is the same as
- passed back from the shell command, however assuming Command.Com was
- loaded successfully, the return code will always be 0, no matter how
- the actual command performed. Procedure Shrink will shrink the Turbo
- appplication down to $1000 pages (64K bytes). It must be invoked before
- calling any of the other routines. The $1000 page figure may have to be
- tinkered with. When compiling your Turbo program, it must be compiled to
- a COM file, with the Maximum Stack/Heap Option set such that the Stack +
- Code + Data < 64K (or what ever figure you reserve for your program).
- Initially I tried using the formula
- Pages to reserve := (Dseg - Cseg) + Memavail + 1;
- but, consistently got errors with it, so I took the more conservative
- approach.
- }
-
- {; }
- {; Copyright (c) 1984 David R. Brandman }
- {; All Rights Reserved }
- {; }
- {; Permission is granted to freely distribute this code, but not for }
- {; profit and provided that the following address and disclaimer are }
- {; included. }
- {; }
- {; Portions of this program may be used freely, in other works, provided }
- {; that credit to the author and this work appear with the portions used. }
- {; }
- {; The author's address: }
- {; }
- {; David R. Brandman }
- {; 805 Rotherham Drive }
- {; Manchester, Mo. 63011 }
- {; (314) 527-8667 }
- {; }
- {; Disclaimer: }
- {; }
- {; This program is provided "as-is" without warranty of any kind, either }
- {; expressed or implied, including, but not limited to the implied }
- {; warranties of merchantability and fitness for a particular purpose. }
- {; }
-
- function shell;
-
- {Perform DOS Exec function ($4B)}
- begin
- inline(
- $1E/ {PUSH DS}
- $8B/$5E/$04/ {MOV BX,[BP+4]}
- $8B/$56/$06/ {MOV DX,[BP+6]}
- $8E/$46/$0A/ {MOV ES,[BP+10]}
- $8E/$5E/$08/ {MOV DS,[BP+8]}
- $2E/$8C/$16/$FC/$00/ {MOV CS:0FCH,SS}
- $2E/$89/$26/$FE/$00/ {MOV CS:0FEH,SP}
- $B8/$00/$4B/ {MOV AX,4B00H}
- $CD/$21/ {INT 21H}
- $2E/$8E/$16/$FC/$00/ {MOV SS,CS:0FCH}
- $2E/$8B/$26/$FE/$00/ {MOV SP,CS:0FEH}
- $72/$08/ {JC BAD}
- $B4/$4D/ {MOV AH,4DH}
- $CD/$21/ {INT 21}
- $B4/$00/ {MOV AH,0}
- $73/$03/ {JNC EXIT}
- $80/$CC/$80/ {BAD: OR AH,80H}
- $1F {EXIT: POP DS}
- )
- end;
-
- procedure shrink;
-
- {Reserve 64K of memory for Turbo application}
-
- var
- regs : record ax,bx,cx,dx,bp,si,di,ds,es,flags : integer; end;
-
- begin
- regs.es := cseg; {reserve memory beginning at CSEG}
- regs.bx := $1000; {reserve $1000 pages (64K bytes) }
- regs.ax := $4A00; {Dos function $4A }
- msdos(regs); {let Dos do the work }
- if ((regs.flags and 1) = 1) then {check the return condition }
- writeln('Shrink failed. RC(',regs.ax and $FF,')');
- end;
-
- function load;
-
- {Setup to load Pgm_Name with parameter Parm
- Returns >= 0 Return code from application
- < 0 Dos error code
- code and $7FFFF is Dos Error Code }
-
- type
- parameter_block = record
- environment : integer;
- cmd_line_ofs : integer;
- cmd_line_seg : integer;
- fcb1_ofs : integer;
- fcb1_seg : integer;
- fcb2_ofs : integer;
- fcb2_seg : integer;
- end;
- regpack = record
- ax,bx,cx,dx,bp,si,di,ds,es,flags : integer;
- end;
-
- var
- bx,dx,ds,es : integer;
- fcb1,fcb2 : string[16];
- param : parameter_block;
- command_string : str;
- regs : regpack;
-
- begin
- fcb1 := #0 + ' ' + #0 + #0 + #0 + #0; {Initialize two FCB's}
- fcb2 := fcb1;
- regs.es := seg(fcb1); regs.di := ofs(fcb1) + 1; {Parse command line into }
- regs.ds := seg(parm); regs.si := ofs(parm) + 1; {the FCB's }
- regs.ax := $2901;
- msdos(regs);
- regs.di := ofs(fcb2) + 1;
- regs.ax := $2901;
- msdos(regs);
- pgm_name := pgm_name + #00; {program name must be an ASCIIZ string}
- command_string := chr(ord(parm[0]) + 1) + ' ' + parm + #$0D; {command Line}
- ds := seg(pgm_name); dx := ofs(pgm_name) + 1; {ds:dx points to program }
- param.environment := memw[cseg:$2C];
- param.cmd_line_seg := seg(command_string); {put address of command line}
- param.cmd_line_ofs := ofs(command_string) + 1; {into the parameter block}
- param.fcb1_seg := seg(fcb1); param.fcb1_ofs := ofs(fcb1) + 1; {ditto for }
- param.fcb2_seg := seg(fcb2); param.fcb2_ofs := ofs(fcb2) + 1; {fcb's }
- es := seg(param); bx := ofs(param); {es:bx points to parameter block }
- load := shell(es,ds,dx,bx); {load the program }
- end;
-
- function dos;
-
- {Setup to invoke COMMAND.COM, passing it Pgm_Name and Parm
- Returns = 0 Normal Return from Command.com
- < 0 Error loading COMMAND.COM
- code and $7FFF is DOS error code }
-
- type
- environment = array[1..500] of char;
- env_ptr = ^environment;
-
- const
- comspec : string[7] = 'OMSPEC=';
-
- var
- env : env_ptr;
- env_seg,
- loc,nloc : integer;
- found : boolean;
- parm_string,
- dos_string : str;
-
- begin
- env_seg := memw[cseg:$2C]; {The following sequence of code }
- env := ptr(env_seg,0); {finds the "COMSPEC=" in the }
- loc := -1; {current environment and extracts }
- repeat {from the enivronment the current }
- repeat {command processor. This code is }
- loc := loc + 1; {kind of yukkie, because the Turbo }
- until env^[loc] = 'C'; {POS function requires a string and }
- found := true; {the environment is not in string }
- nloc := loc + 1; {format }
- while (found) do begin
- if env^[nloc] = comspec[nloc-loc] then nloc := nloc + 1
- else found := false;
- end;
- if ((nloc - loc) = 8) then found := true
- else begin
- while (env^[nloc] <> #00) do
- nloc := nloc + 1;
- loc := nloc;
- end;
- until found;
- dos_string := '';
- while (env^[nloc] <> #00) do begin
- dos_string := dos_string + env^[nloc];
- nloc := nloc + 1;
- end; {we've found and extracted the COMSPEC }
- parm_string := '/C ' + pgm_name + ' ' + parm; {Dos parameter string }
- dos := load(dos_string,parm_string); {load and run dos/program }
- end;
-