            How to Reduce the Memory Requirement 
        for Loading an EXE File Compressed with LZEXE

                      by Pete Petrakis
                       CIS 76555,1175


  LZEXE is a program that can greatly reduce the disk size of most EXE
files.  The compressed files remain executable and they expand themselves
very rapidly when they are run.  Except for very large programs, the auto-
decompression time for an LZEXE-compressed EXE file is too short to
be noticeable.  Even with very large programs the delay is barely
noticeable, amounting to perhaps only a second or two of additional time. 
Disk file size reductions usually are in the range of 30-40 percent, although
I've gotten compressions as high as 67-71 percent on a few EXE files. 
The compressions are comparable to those achieved with PKZIP and
LHARC.  In fact those archiving programs rarely can add anything to a
compression already achieved with LZEXE, and they simply store such
files unchanged in the archive file.  The program's author, Fabrice Bellard
of Grabels, France deserves great respect for an excellent piece of work.

  A frequent result of compression with LZEXE is a significant increase
in the amount of memory required to load the program.  This can be seen
with Microsoft's EXEMOD program (which is included with some of its
language packages).  When run with only an EXE file name on its
command line, EXEMOD reveals information about the program such as
disk file size, minimum memory needed to load, stack space, minimum
allocation, and maximum allocation.  When run with appropriate command
line switches, EXEMOD allows some of the values to be changed.

  One author of a rather large program found that compression with
LZEXE reduced the disk file size of his program from 183k to 112k but
added nearly 100k of minimum load memory to the 211k the program
needed in the uncompressed form.  He concluded, "I can't pay that price." 
The good news I have for that author (and for others who might be
similarly dismayed) is that there is a way to eliminate most or all of the
increment in the minimum load requirement that occurs when files are
compressed with LZEXE.

  The method is one I stumbled upon purely by trial and error, with
countless reboots required because of a locked system.  It involves
Microsoft's EXEMOD program.

  I couldn't begin to explain why this empirical method works.  The
documentation for EXEMOD that I've read explains WHAT can be
changed with that program, and it tells HOW to do it.  But it says not
one word about WHEN, WHY, and HOW MUCH to change anything. 
Since Microsoft provides absolutely no guidance on the intelligent use of
EXEMOD, people like me have no alternative but to use it stupidly.  If
Microsoft or anybody else can tell me why the method I groped my way
to works, I'll be grateful.

  Anyway, here is the method, step by step:


     1.  Examine the uncompressed file data with EXEMOD by typing

                 EXEMOD filename 

         at the DOS prompt.  You will get a table that looks something
         this:


         CAL                                (hex)           (dec)

         .EXE size (bytes)                  2CDA2          183714
         Minimum load size (bytes)          334F2          210162
         Overlay number                         0               0
         Initial CS:IP                  0000:0000
         Initial SS:SP                  30A4:0C00            3072
         Minimum allocation (para)            695            1685
         Maximum allocation (para)           FFFF           65535
         Header size (para)                    20              32
         Relocation table offset               1E              30
         Relocation entries                     0               0


         This example happens to be data for the uncompressed version
         of the program (CAL.EXE) I mentioned earlier -- the one that
         acquired an additional 100k of minimum load size after
         compression with LZEXE.

     2.  Compress the file with LZEXE and run EXEMOD again to
         analyze it.  Here is what EXEMOD reports about the same
         program after compression with LZEXE:

         CAL                                (hex)           (dec)

         .EXE size (bytes)                  1B65D          112221
      *  Minimum load size (bytes)          4524D          283213
         Overlay number                         0               0
         Initial CS:IP                  1B48:0012
         Initial SS:SP                  2D31:0080             128
      *  Minimum allocation (para)           29C1           10689
      *  Maximum allocation (para)           FFFF           65535
         Header size (para)                     2               2
         Relocation table offset               1C              28
         Relocation entries                     0               0


         Notice that the EXE file size has been reduced from 184k to
         112k, a saving of 72k.  But the three lines that matter most for
         this discussion are Minimum load size, Minimum allocation,
         and Maximum allocation.  They are marked with asterisks here
         so you can spot them quickly.

         Compare the value for Minimum load size in the two tables.
         Notice the increase of 72k for Minimum load size after
         compression with LZEXE.  We are going to reduce that number
         drastically in the next step, but before taking the next step
         we'll need to note the new hex value for Minimum allocation.
         In actual practice it's a good idea to write it down before
         proceeding.  Note that the Minimum allocation in this example is
         29C1 hex (we won't need the decimal value).

     3.  Run EXEMOD again, this time to change the maximum and
         minimum allocations.  This is the crucial step, and it involves
         using EXEMOD to do two things: (1) change the maximum
         allocation to the value for minimum allocation that was found
         in the previous step, and (2) change the minimum allocation to
         zero.  Using the same program as an example we type the
         following at the DOS prompt:

                    EXEMOD CAL /MAX 29C1 /MIN 0

         As EXEMOD does its work, the following message appears:

             EXEMOD : warning U4051: minimum allocation less than
             stack; correcting minimum

         Ignore it.


     4.  Run EXEMOD again to see what happened (just type EXEMOD
         and program name, without any switches).  Here is what we
         find for this example:

         CAL                                (hex)           (dec)

         .EXE size (bytes)                  1B65D          112221
         Minimum load size (bytes)          2D38D          185229
         Overlay number                         0               0
         Initial CS:IP                  1B48:0012
         Initial SS:SP                  2D31:0080             128
         Minimum allocation (para)           11D5            4565
         Maximum allocation (para)           29C1           10689
         Header size (para)                     2               2
         Relocation table offset               1C              28
         Relocation entries                     0               0


         Notice that the Minimum load size of the compressed program is
         greatly reduced.  It's actually smaller than it was before
         compression with LZEXE.  We have reduced the disk file size
         from 184k to 112k with LZEXE, and we have also reduced the
         memory needed to load the program from 210k to 185k, 25k lower
         than it was before compression.

  Now for a practical test.  After the compressed program was processed
by the method just described, it could be loaded and run in a system with
only 255k of total free RAM.  This was an absolute minimum determined
by using EATMEM, a program that lets you whittle down available RAM
to any amount you want for test purposes.  That minimum required RAM
size after LZEXE compression and processing with EXEMOD is within
only 2 or 3k of the minimum available RAM that was needed before
compression (also determined by using EATMEM).

  End result: a nearly 40 percent reduction in disk file size and no
significant change in memory requirements.

  The essence of the method is making the minimum allocation become
the maximum allocation and setting the minimum allocation to zero (thus
forcing EXEMOD to determine what the new minimum allocation should
actually be).

  Understand that I had absolutely no rationale for doing it this way.  It
is purely the result of many stabs in the dark.  I had to have some number
to plug into EXEMOD for maximum allocation, and since I had no
rational basis for picking one I simply used the one that was already there
for minimum allocation.  Then, because I didn't know what to put in for
minimum allocation, I made it zero, in effect telling EXEMOD, "You
figure it out."  Surely there is a way to select values for minimum and
maximum allocations intelligently and purposefully, but until Microsoft sees
fit to tell us what it is, this blind, ignorant method will have to suffice, at
least for me.  I have tested my empirical method with many LZEXE-
compressed programs, and so far it has substantially reduced the minimum
load size every time.  And the programs always work.  Usually the
resulting minimum load size is smaller than it was before compression with
LZEXE.  Don't ask me why.

  That's about it.  Maybe you can (1) explain why this method works and
(2) provide a method for choosing numbers for maximum and minimum
allocation that is grounded in theory rather than groping and rebooting.


                                               Pete Petrakis



NOTE: Since writing this I have written a shell program that does it all
automatically.  It runs LZEXE to compress your EXE file, and it runs
EXEMOD to set the load memory requirement lower.  The program is called
LZEFIX, and the method it uses is identical to what's described here.
It does exactly what you would do -- run EXEMOD, read screens, and make
changes.  LZEFIX is on Compuserve (IBMSYS and MSSYS) and may soon spread
to other systems.  It could have a short life if the author of LZEXE fixes
his program to give compressed programs a more reasonable memory
requirement for loading, and that would be fine with me.