The DOS EXE header

The header of an DOS EXE file:
 Offset   Size   Description
   00h    word    ID signature ('MZ' or 'ZM')
                    Some older compilers where little-endian 'ignorant'?  :-)
   02h    word    Image size mod 512 
                    bytes on last page
   04h    word    Number of 512-byte pages in image
                    Size of total file = [04h] * 512 + [02h]
   06h    word    count of relocation table entries
   08h    word    size of header, in paragraphs
                    Usually set to 20h for 512 bytes
   0Ah    word    min required mem
                    DOS (should) use this to find out how much memory
                     is required for the program.  
                     Size of EXE + [0Ah] = min ammount
   0Ch    word    max required mem
                    Usually set to 0FFFFh
   0Eh    word    stack seg offset in load module
   10h    word    initial value of sp
                    SS:SP = [OEh]:[10h]
   12h    word    file checksum
                    one's complement of the sum of all words in .exe file
                     ([12h] is assumed 00h when reading file for calculation)
                    If [12h] is zero, no checksum is used
   14h    word    initial value of IP
   16h    word    cs offset in load module
                    CS:IP = [16h]:[14h]
   18h    word    offset of first reloc item
                    (Usually set to 1Eh for MS, 1Ch for Borland)
   1Ah    word    overlay number
                    (most of the time is zero)
   1Ch    relocation items usually start here (unless MS, then 1Eh)
If you notice, we don't need the whole page (512 bytes) of disk space this header takes up. There is room for 121 4-byte relocation units after the overlay word above. If you don't use all of this room, why not modify the EXE file and header to get rid of this wasted space?

If we change the size of the file at the dword at offset 02h, change the size of the header at offset 08h, and then rewrite the EXE file with out the wasted space, we can cut an EXE file by 480 bytes if there no more than one relocation item. Please note that we must leave the header size in paragraphs (16 bytes). This will allow for one relocation entry and still get the maximum size reduction.

The new size of the header would be:

Size of header: 28 + (4 * relo entrys) rounded up to nearest para.

I have a utility included with my NewBasic package that will do this for you. See shrnkexe.com on that page. Also see exehdr.zip on the same page for a utility that will display this header (includes source code)

You should take a few more things into consideration if you plan to shrink your .EXE files. Some linkers (extractors) place other information in this 480 byte space such as copyright notices, etc., while some extractors will place extraction information here. Usually, they add to the header size word at offset 08h, but do not assume this.

Only shrink .EXE files that you created....