Board index » delphi » Exec Question - Not The One You Think!

Exec Question - Not The One You Think!

Quote
Karl Dyson wrote:

> Hello there,

> I don't believe this is in the FAQ - but if it is, you have my humblest
> appologies.

> I have a program which needs to call an external program such as Edit.
> The problem is: my program uses too much stack and heap memory for
> exec() to be able to execute any DOS programs via the Command.Com.

> Is there any way I can get around this?

> Thanks,

> Karl
> --
> Karl Dyson <ka...@feklore.demon.co.uk>
> "Gutted!"

Karl,

This is from a Menu Program which is currently being used. First, you
must limit the amount of memory used by the calling program:

{$M $2000, 0, 0 }  { 16K Stack, No Heap }

This is the procedure that does the actuall calling:

procedure run(akey : byte ; dvsn : integer ; dvsn_name : string) ;
  var prog_name, divsn, command : string ;
  begin
    case akey of
      1 : prog_name := '.\REF01' ;
      2 : prog_name := '.\REF02' ;
      3 : prog_name := '.\REF03' ;
      4 : prog_name := '.\REF04' ;
      5 : prog_name := '.\REF05' ;
      6 : prog_name := '.\REF06' ;
     end ; { case }
  if (dvsn<10) then dvsn := dvsn + 48
               else dvsn := dvsn + 55 ;
  divsn := chr(dvsn) ;
  command := ' /C ' + prog_name + ' ' + divsn + ' ' + dvsn_name ;
  prog_name := 'c:\command.com' ;
  SwapVectors;
  Exec(prog_name,Command) ;
  SwapVectors;
  end ; { r u n }

In addition to running the other programs (REF01 thru REF06) I am also
passing information on the command line because these programs would
access a different set of files for each Division being used.

If you have any questions about this just post them here.

--
Val Mehling - anti-spam in effect.
For e-mail reply to:
  va...@earthlink.net

 

Re:Exec Question - Not The One You Think!


Karl Dyson schrieb:

Quote

> Hello there,

> I don't believe this is in the FAQ - but if it is, you have my humblest
> appologies.

> I have a program which needs to call an external program such as Edit.
> The problem is: my program uses too much stack and heap memory for
> exec() to be able to execute any DOS programs via the Command.Com.

> Is there any way I can get around this?

> Thanks,

> Karl
> --
> Karl Dyson <ka...@feklore.demon.co.uk>
> "Gutted!"

Yes, there is. I do it since 1984: Using a multitasking operating
system. Look at my prof. homepage for REAL/32 and then link
to the phantastic developers who make it.

There is almost nothing new for DOS programmers, but all is
much easier, even if you need DPMI.

Regards,
Franz Glaser
http://members.eunet.at/meg-glaser

Re:Exec Question - Not The One You Think!


Quote
Karl Dyson (ka...@feklore.demon.co.uk) wrote:

: I have a program which needs to call an external program such as Edit.
: The problem is: my program uses too much stack and heap memory for
: exec() to be able to execute any DOS programs via the Command.Com.
:
: Is there any way I can get around this?

       I don't know if this will help or not,
I have been using it about ten years.

PROCEDURE execute_string(s : str255);
    { execute_string -- execute a command line }
  VAR
    save_ax : Integer;
  CONST
    save_ss : Integer = 0;
    save_sp : Integer = 0;
BEGIN
    s[Length(s)+1] := ^M;
    INLINE(
      $1E/                    {   push    ds                   }
      $55/                    {   push    bp                   }
      $2E/$8C/$16/save_ss/    {   mov     cs:[save_ss],ss      }
      $2E/$89/$26/save_sp/    {   mov     cs:[save_sp],sp      }
      $8C/$D0/                {   mov     ax,ss                }
      $8E/$D8/                {   mov     ds,ax                }
      $8D/$76/<s/             {   lea     si,s[bp]             }
      $CD/$2E/                {   int     2eh                  }
      $FA/                    {   cli                          }
      $2E/$8E/$16/save_ss/    {   mov     ss,cs:[save_ss]      }
      $2E/$8B/$26/save_sp/    {   mov     sp,cs:[save_sp]      }
      $FB/                    {   sti                          }
      $5D/                    {   pop     bp                   }
      $1F/                    {   pop     ds                   }
      $89/$46/<save_ax        {   mov     save_ax[bp],ax       }
      );
    IF save_ax <> 0 THEN WriteLn('Exit code = ', save_ax);
END;

Ken Fischer

---

Re:Exec Question - Not The One You Think!


In article <ctEQvFAHx$o1E...@feklore.demon.co.uk>,
Karl Dyson  <ka...@feklore.demon.co.uk> wrote:

Quote

>Hello there,

>I don't believe this is in the FAQ - but if it is, you have my humblest
>appologies.

>I have a program which needs to call an external program such as Edit.
>The problem is: my program uses too much stack and heap memory for
>exec() to be able to execute any DOS programs via the Command.Com.

>Is there any way I can get around this?

Use this.  (basically just get rid of the $M and then use the exec()
in this unit, or alternatively shell() or push).  It swaps the heap and
most of te stack to XMS before executing the program.

Unit Xheap;

Interface

uses dos;

{$ifdef msdos }

type string128=string[128];

procedure exec(const com,par:string128);
Function MaxProg:word;  { kilobytes }

Const Swapstack{:boolean}=true;    { Change if you wish }
Const UseXMS{:boolean}=true;       { Swap to XMS }
Const XmsInts{:boolean}=true;      { Use XMS for interrupts }
Const ComprHeap{:boolean}=true;    { Compress the heap }

{$endif}

{$define compressheap}

Const freeenv:word=300; { amount of free environment for shell/push }

Procedure Shell(const st:string);
Procedure Push;

Const errorcode=233;

Implementation

{$ifdef msdos}

const spmin=1500;

{-------------------------- XMS routines -----------------------}

Var Handle:word;
    intHandle:word;
    xmsentry:pointer;

Procedure GetXMSentry; assembler;
             asm
             xor ax,ax
             mov word ptr xmsentry,ax
             mov word ptr xmsentry+2,ax

             mov ax,4300h
             int 2fh
             cmp al,80h
             jne @out
             mov ax,4310h
             int 2fh
             mov word ptr xmsentry,bx
             mov word ptr xmsentry+2,es
      @out:
             end;

Function FreeXms:word; assembler;
         asm
         mov ax,word ptr xmsentry
         or ax,word ptr xmsentry+2
         jz @out
         mov ah,8
         call xmsentry
@out:
         End;

Function XInit(Kb:word;var handle:word):byte; assembler;
         asm
         mov ax,word ptr xmsentry
         or ax,word ptr xmsentry+2
         mov al,255
         jz @out
         mov dx,kb
         mov ah,9
         call XmsEntry
         cmp ax,1
         mov al,bl
         jne @out
         xor al,al
         les di,handle
         mov es:[di],dx
  @out:
         end;

Procedure XWrite(handle:word;p:pointer; count:longint);
type  emm=record
            count:longint;
            zero:word;
            P:pointer;
            handle:word;
            Pos:longint;
          End;
const e:emm=(count:0;zero:0;p:nil;handle:0;pos:0);
begin
  e.count:=count;
  e.p:=p;
  e.handle:=handle;
  asm
   mov ah,$b
   mov si,offset e
   call XmsEntry
  end;
End;

Procedure XRead(handle:word;p:pointer; count:longint);
type  emm=record
            count:longint;
            handle:word;
            Pos:longint;
            zero:word;
            P:pointer;
          End;
const e:emm=(count:0;handle:0;pos:0;zero:0;p:nil);
begin
  e.count:=count;
  e.p:=p;
  e.handle:=handle;
  asm
   mov ah,$b
   mov si,offset e
   call XmsEntry
  end;
End;

procedure XDone(handle:word); assembler;
  asm
  mov dx,handle
  mov ah,$a
  call xmsentry
  end;

{-----------------------  End XMS routines ----------------------- }

var xmsinuse:boolean;
    ints:word;   { segment address }

Type Words=Record
             lo,hi:Word;
           End;

     pp=^longint;

Function p2i(p:pointer):longint; assembler;
         asm
         mov ax,word ptr p+2
         mov dx,ax
         {$ifopt g+}
         shl ax,4
         shr dx,12
         {$else}
         mov cl,4;  shl ax,cl
         mov cl,12; shl dx,cl
         {$endif}
         add ax,word ptr p
         adc dx,0
         end;

function i2p(i:longint):pointer; assembler;
         asm
         mov ax,word ptr i
         mov dx,word ptr i+2
         mov bx,ax
         {$ifopt g+}
         shl dx,12
         shr bx,4
         {$else}
         mov cl,12; shl dx,cl
         mov cl,4;  shr bx,cl
         {$endif}
         and ax,15
         add dx,bx
         end;

{------------------ Routines for heap compression --------------- }

{ Move routines, faster than system.move() and allows explicit choice
  of the direction. }

procedure moveupw(var s,d; wcount:word);  assembler;
          asm
          push ds
          mov cx,wcount
          lds si,s
          les di,d
          mov dx,cx
          dec dx
          add dx,dx
          add di,dx
          add si,dx
          std
          rep movsw
          pop ds
          end;

procedure movedownw(var s,d; wcount:word);  assembler;
          asm
          push ds
          mov cx,wcount
          lds si,s
          les di,d
          cld
          rep movsw
          pop ds
          end;

var cut:longint;

Procedure LMove(s,d,c:longint);  { Addresses linear 20 bit, c even }
var sp,dp:pointer;
const seginc=4095;     { Cannot do full 64K as offset can be up to 15 }
      count=16*seginc; { 65520 }
begin
  if (s<p2i(freelist)) or (d<p2i(freelist)) or
     (c<0) or (c>720*1024)
      then runerror(errorcode+5);
  if d<s then begin
    sp:=i2p(s);
    dp:=i2p(d);
    while c>count do begin
      movedownw(sp^,dp^,count shr 1);
      dec(c,count);
      inc(words(sp).hi,seginc);
      inc(words(dp).hi,seginc);
    End;
    movedownw(sp^,dp^,word(c) shr 1);
  End
  else if s<>d then begin
     sp:=i2p(s+c-count);
     dp:=i2p(d+c-count);
     while c>count do begin
       moveupw(sp^,dp^,count shr 1);
       dec(c,count);
       dec(words(sp).hi,seginc);
       dec(words(dp).hi,seginc);
     End;
     moveupw(i2p(s)^,i2p(d)^,word(c) shr 1);
  end
End;

type PFreenode=^Tfreenode;
     Tfreenode=record next,size:Pfreenode end;

Procedure Compressheap;
var p,q:pfreenode;
    count,fb:longint;
begin
  p:=freelist;
  cut:=0;
  while p<>heapptr do begin
    if (words(p).hi<words(heaporg).hi) or
       (words(p).hi>words(heapptr).hi) then runerror(errorcode+4);
    fb:=p2i(p^.size);                   { Get the size of the free block }
    q:=p^.next;                         { Get ptr to the next free block}
    movedownw(p^,i2p(p2i(p)-cut)^,4);   { move the nextptr an size }
    if fb>8 then begin
      count:=p2i(q)-p2i(p)-fb;          { The size of the used block }
      lmove(p2i(p)+fb,p2i(p)+8-cut,count); { Move the used block }
      inc(cut,fb-8);                    { the no of compressed bytes }
    End;
    p:=q;
  End;
  Heapptr:=i2p(p2i(heapptr)-cut);       { Modify heapptr for heapout }
End;

Procedure ExpandHeap;
var p:pfreenode;
    nxt:longint;
    d:longint;
    fb,count:longint;

begin
  Heapptr:=i2p(p2i(heapptr)+cut);       { restore the heapptr }
  lmove(p2i(freelist),p2i(freelist)+cut,p2i(heapptr)-p2i(freelist)-cut);
  d:=p2i(freelist);                     { move the stuff way up }
  p:=i2p(p2i(freelist)+cut);            { '+cut' because of above move}
  while cut>0 do begin
    nxt:=p2i(p^.next);
    movedownw(p^,i2p(d)^,4);            { move the next ptr and size }
    inc(d,p2i(p^.size));                { skip the free block }
    fb:=p2i(p^.size);
    count:=nxt-p2i(p)-fb+cut;
    lmove(p2i(p)+8,d,count);            { move the used block down }
    inc(d,count);
    dec(cut,fb-8);                      { reduce the no. or compr. bytes}
    p:=i2p(nxt+cut);
  End;
End;

{----------------------------------------------------------------}

var startptr:pointer;  { Start of the area swappted to XMS }
    len:longint;       { no of bytes in XMS }

{ Startptr: Start of the area to be written to XMS
  Endptr: End of area to be kept }

procedure HeapOut(stptr,endptr:pointer);
var rg:registers;
    fx:word;
Begin
  if comprheap then compressheap;

  ints:=0;
  startptr:=stptr;

  inc(words(startptr).hi,words(startptr).lo shr 4);
  words(startptr).lo:=words(startptr).lo and 15;

  inc(words(endptr).hi,words(endptr).lo shr 4);
  words(endptr).lo:=words(endptr).lo and 15;

  len:=p2i(heapptr)-p2i(startptr);
  if usexms and (xinit((len+1023) shr 10,handle)=0) then begin
     xwrite(handle,startptr,len);
     xmsinuse:=true;                           { Write the heap into XMS }
  End
  else begin
     if usexms then fx:=freexms;        { lets get what XMS we can get }
     if usexms and (fx>0) and (xinit(fx,handle)=0) then begin
        len:=longint(fx)*1024;
        startptr:=i2p(p2i(heapptr)-len);
        xwrite(handle,startptr,len);
        xmsinuse:=true;
        endptr:=startptr;
     end else begin
       xmsinuse:=false;
       EndPtr:=HeapPtr;
     End;
  End;

  rg.bx:=words(Endptr).hi-prefixseg+65;
  if rg.bx>=memw[prefixseg:2]-prefixseg then begin
     if xmsinuse then xdone(handle);
     exit;                                           { No reduction }
  End;

  if xmsints and (xinit(1,inthandle)=0) then begin   { Get 1K for iv's }
     dec(rg.bx,64);                                  { Decrese 1K }
     xwrite(inthandle,ptr(0,0),1024);
     ints:=1;  { Ints in XMS }
  End
  else begin
        if rg.bx>=memw[prefixseg:2]-prefixseg then exit;   { No reduction }
        ints:=words(endptr).hi+1;
        move(ptr(0,0)^,ptr(ints,0)^,1024);
       End;

  rg.es:=prefixseg;
  rg.ah:=$4a;
  MsDos(rg);                   { Reduce the memory block }
  if rg.flags and fcarry>0 then begin   { Should not fail }
     if xmsinuse then xdone(handle);
     if ints=1 then xdone(inthandle);
     Runerror(errorcode);
  End;
End;

Procedure HeapIn;
var rg:registers;
    done:boolean;
    i:integer;
Begin
  if ints>0 then begin                { Heapout did not do anything }
    if xmsints and (ints=1) then begin
       xread(inthandle,ptr(0,0),1024);  { Read ints from XMS. Safe? }
       xdone(inthandle);
    End
    else
       asm
       push ds
       mov ds,ints
       xor si,si
       xor di,di                        { Load ints from base mem }
       mov es,si
       mov cx,512

       cld
       cli
       rep movsw
       sti

       pop ds
       end;

    repeat
...

read more »

Re:Exec Question - Not The One You Think!


Quote
Karl Dyson wrote in message ...
>...
>The problem is: my program uses too much stack and heap memory for
>exec() to be able to execute any DOS programs via the Command.Com.
>...

One technique I have seen, on an XT-class machine with no EMS or XMS,
is to have a small shell program. This program is fairly dumb, its
most important attribute is that it takes little memory - it's small,
has no heap and little stack. It will look for an instruction file
(the directory can be got from ParamStr(0)) which contains a program
name and a command line (on separate lines). If the file is found, it
is read and deleted, and the program is run. If the file is not found,
it runs your program, the name of which is hardcoded into the shell
program. So instead of having a myprog.exe file for your program, you
have a shell called myprog.exe which will run myprogx.exe in the
absence of other instructions.

So to run EDIT you would write C:\WINDOWS\EDIT.EXE and the command
line (or COMMAND.COM and a command line starting EDIT) to the
instruction file and terminate. Your program no longer occupies any
memory and EDIT can run. Of course, when EDIT is finished your program
starts at the beginning again which may or may not be acceptable.

If you have XMS you could swap your program there while EDIT runs.
Look on DEJANEWS for a message by Osmo Ronkanen entitled "Re:
allocating memory for exec" posted 12th February, that might do it for
you.

FP

Re:Exec Question - Not The One You Think!


Quote
Karl Dyson <ka...@feklore.demon.co.uk> wrote:

>Hello there,

>I don't believe this is in the FAQ - but if it is, you have my humblest
>appologies.

>I have a program which needs to call an external program such as Edit.
>The problem is: my program uses too much stack and heap memory for
>exec() to be able to execute any DOS programs via the Command.Com.

>Is there any way I can get around this?

For some of my large (real-mode) programs I use the swap-library
exec33b (free with full source) to find at Simtel; e.g.
ftp://ftp.uni-paderborn.de/simtelnet/msdos/pgmutl/exec33b.zip
It swaps the executing program to XMS/EMS/DISK leaving
only 3-6K in memory.
It works with all versions of MS-DOS, Novell-DOS, Win-DOS
I use(d) till now.

--
R.Fischer

Re:Exec Question - Not The One You Think!


Hello there,

I don't believe this is in the FAQ - but if it is, you have my humblest
appologies.

I have a program which needs to call an external program such as Edit.
The problem is: my program uses too much stack and heap memory for
exec() to be able to execute any DOS programs via the Command.Com.

Is there any way I can get around this?

Thanks,

Karl
--
Karl Dyson <ka...@feklore.demon.co.uk>
"Gutted!"

Re:Exec Question - Not The One You Think!


Uses Dos, Memory;

begin;

SwapVectors;
SetMemTop(HeapPtr);

Exec(GetEnv('COMSPEC'),'/C EDIT.COM');

SetMemTop(HeapEnd);
SwapVectors;

end.;

Hope This Helps.

Other Threads