3. Programme:

   a. DOS-Com

Kein spezielles File-Format vorhanden.

   b. DOS-Exe

Offset Laenge  Name     Inhalt   ("Header")
  0h     1W   ExeKen   Kennung des EXE-Headers (='MZ')
  2h     1W   ExeGlP   Anzahl der Bytes in der letzten Page
  4h     1W   ExeGPg   Groess der EXE-Datei in Pages a 512 Bytes
  6h     1W   ExeARe   Anzahl der Relokationseintraege
  8h     1W   ExeGHe   Groesse des Headers in Paragraphen a 16 Bytes
  Ah     1W   ExeMiP   Minimaler zusaetzlicher Speicherbedarf in Par.
  Ch     1W   ExeMaP   Maximaler zusaetzlicher Speicherbedarf in Par.
  Eh     1W   ExeSSS   Startwert des SS-Registers
 10h     1W   ExeSSP   Startwert des SP-Registers
 12h     1W   ExePrf   Negative Pruefsumme aller 16bit Worte
 14h     1W   ExeSIP   Startwert IP-Register
 16h     1W   ExeSCS   Startwert CS-Register
 18h     1W   ExeSRe   Offset der Relokationstabelle (Dateistart)
 1Ah     1W   ExeOvl   Nummer des durch Linker erzeugten Overlays

Literatur:
  Martin Aschoff: "Die Unterschiede zwischen Com- und Exe-Dateien",
    DOS 03/88, S24ff

   c. Erweiterte EXE-Dateien (386er Treiber etc.)

Offset Laenge  Name     Inhalt   ("EXE-Header")
  0h     1W   ExeKen   Kennung des EXE-Headers (='MZ')
  2h     1W   ExeGlP   Anzahl der Bytes in der letzten Page
  4h     1W   ExeGPg   Groess der EXE-Datei in Pages a 512 Bytes
  6h     1W   ExeARe   Anzahl der Relokationseintraege
  8h     1W   ExeGHe   Groesse des Headers in Paragraphen a 16 Bytes
  Ah     1W   ExeMiP   Minimaler zusaetzlicher Speicherbedarf in Par.
  Ch     1W   ExeMaP   Maximaler zusaetzlicher Speicherbedarf in Par.
  Eh     1W   ExeSSS   Startwert des SS-Registers
 10h     1W   ExeSSP   Startwert des SP-Registers
 12h     1W   ExePrf   Negative Pruefsumme aller 16bit Worte
 14h     1W   ExeSIP   Startwert IP-Register
 16h     1W   ExeSCS   Startwert CS-Register
 18h     1W   ExeSRe   Offset der Relokationstabelle (Dateistart) (=40h)
 1Ah     1W   ExeOvl   Nummer des durch Linker erzeugten Overlays
 1Ch    16W   ExeRes   Reserviert
 3Ch     1D   ExeAdN   Offset zum erweiterten (LE-)Header

Offset Laenge  Name     Inhalt   ("LE-Header")
  0h     1W   ExlKen   Kennung des neuen Headers (='LE')
  2h     1B   ExlLnV   Linker-Versionsnummer
  3h     1B   ExlLnR   Linker-Revisionsnummer
  4h     1D   ExlEFL   executable Format Level ???
  8h     1W   ExlCPU   Notwendiger CPU-Typ:
                         1h - 80286 oder aufwaerts
                         2h - 80386 oder aufwaerts
                         3h - 80486 oder aufwaerts
                         4h - 80586 oder aufwaerts
                        20h - 80860 oder kompatibel
                        40h - MIPS Mark I oder kompatibel
                        41h - MIPS Mark II oder kompatibel
                        42h - MIPS Mark III oder kompatibel

  Ah     1W   ExlTOS   Ziel-Betriebssystem:
                         1 - Microsoft OS/2
                         2 - Microsoft Windows
                         3 - MS-DOS 4.x (mit Detach-Unterstuetzung)
                         4 - Microsoft Windows 386
  Ch     1W   ExlMoV   Modul-Version
 10h     1D   ExlMoT   Modul-Typ-Flags:
                         b15 : Programm ist Bibliotheksmodul (DLL,FON)
                               oder Treiber
                         b13 : Programm enthaelt Linker-Error
                         b8+9: Benutzung des MS-Win bzw PM-API:
                               1 - Vollscreen-Applikation
                               2 - Kompatibel mit API
                               3 - Benutzt das API
                         b5  : Programm enthaelt keine externen FixUps
                         b4  : Programm enthaelt keine internen FixUps
                         b2  : Programm benutzt Globale Initialisierung
 14h     1D   ExlAMP   Anzahl der benutzten Speicherseiten
 18h     1D   ExlSIP   Startwert des EIP-Registers
 1Ch     1D   ExlSCS   Startwert des CS-Registers
 20h     1D   ExlSSP   Startwert des ESP-Registers
 24h     1D   ExlSSS   Startwert des SS-Registers
 28h     1D   ExlPSi   Groesse der Speicher-Seiten
 2Ch     1D   ExlBLP   Anzahl der Bytes in der letzten Speicherseite
 30h     1D   ExlFSS   Groesse der FixUp-Sektion
 34h     1D   ExlFSC   Check-Summe der FixUp-Sektion
 38h     1D   ExlLSS   Groesse der Lader-Sektion
 3Ch     1D   ExlLSC   Check-Summe der Lader-Sektion
 40h     1D   ExlOOT   Offset der Objekt-Tabelle
 44h     1D   ExlEOT   Eintraege in der Objekt-Tabelle
 48h     1D   ExlRe1   Unbekannt (=010Ch ???)
 4Ch     1D   ExlRe2   Unbekannt (=0000h ???)
 50h     1D   ExlORT   Offset der Resource-Tabelle
 54h     1D   ExlERT   Eintraege in der Resource-Tabelle
 58h     1D   ExlORN   Offset der residenten Namenstabelle
 5Ch     1D   ExlOET   Offset der Entry-Tabelle
 60h     1D   ExlOMD   Offset der Modul-Direktiven-Tabelle
 64h     1D   ExlEMD   Eintraege in der Modul-Direktiven-Tabelle
 68h     1D   ExlRe3   Offset einer unbekannten Tabelle ??
 6Ch     1D   ExlRe4   Offset einer unbekannten Tabelle ??
 70h     1D   ExlOIM   Offset der Imported-Modul Namens-Tabelle
 74h     1D   ExlEIO   Imported Module ???
 78h     1D   ExlOPN   Offset der Imported-Procedur Namens-Tabelle
 7Ch     1D   ExlOPC   Offset der Check-Summen-Tabelle (Pro Seite)
 80h     1D   ExlOPP   Offset der Pre-Load Seiten
 84h     1D   ExlAPP   Anzahl der Pre-Load Seiten
 88h     1D   ExlONN   Offset der Tabelle nicht residenter Namen
 8Ch     1D   ExlANN   Laenge der Tabelle nicht residenter Namen
 90h     1D   ExlNNC   Check-Summe der nicht residenten Namen
 94h     1D   ExlADA   Automatisches Daten Objekt ???
 98h     1D   ExlODI   Offset der Debug-Informationen
 9Ch     1D   ExlADI   Laenge der Debug-Informationen
 A0h     1D   ExlNPI   Anzahl der Speicher-Seiten fuer PreLoad-Instanzen
 A4h     1D   ExlNDI   Anzahl der Speicher-Seiten fuer Demand-Instanzen
 A8h     1D   ExlEHA   Speicher-Anforderung des Extra-Heaps

Literatur:
  R.Brown: "Interrupt List", Release 33

   d. Windows-Exe (V 2.xx u. 3.xx)

Offset Laenge  Name     Inhalt   ("EXE-Header")
  0h     1W   ExeKen   Kennung des EXE-Headers (='MZ')
  2h     1W   ExeGlP   Anzahl der Bytes in der letzten Page
  4h     1W   ExeGPg   Groess der EXE-Datei in Pages a 512 Bytes
  6h     1W   ExeARe   Anzahl der Relokationseintraege
  8h     1W   ExeGHe   Groesse des Headers in Paragraphen a 16 Bytes
  Ah     1W   ExeMiP   Minimaler zusaetzlicher Speicherbedarf in Par.
  Ch     1W   ExeMaP   Maximaler zusaetzlicher Speicherbedarf in Par.
  Eh     1W   ExeSSS   Startwert des SS-Registers
 10h     1W   ExeSSP   Startwert des SP-Registers
 12h     1W   ExePrf   Negative Pruefsumme aller 16bit Worte
 14h     1W   ExeSIP   Startwert IP-Register
 16h     1W   ExeSCS   Startwert CS-Register
 18h     1W   ExeSRe   Offset der Relokationstabelle (Dateistart) (=40h)
 1Ah     1W   ExeOvl   Nummer des durch Linker erzeugten Overlays
 1Ch    16W   ExeRes   Reserviert
 3Ch     1D   ExeAdN   Offset zum neuen (NE-)Header

Offset Laenge  Name     Inhalt   ("NE-Header")
  0h     1W   ExnKen   Kennung des neuen Headers (='NE')
  2h     1B   ExnLnV   Linker-Versionsnummer
  3h     1B   ExnLnR   Linker-Revisionsnummer
  4h     1W   ExnOET   Offset der Eintragstabelle (rel. NE)
  6h     1W   ExnLET   Laenge der Eintragstabelle
  8h     4B   ExnRe1   Reserviert (CRC-Summe ?)
  Ch     1W   ExnFl1   Flags
                         b15 : Programm ist Bibliotheksmodul (DLL,FON)
                               oder Treiber
                         b14 : Programm liegt als Bibliotheksmodul oberhalb
                               des EMS-Speichers
                         b13 : Programm enthaelt Linker-Error
                         b11 : Programm enthaelt eigenen Loader (FAPI)
                         b10 : Reserviert
                         b8+9: Benutzung des MS-Win bzw PM-API:
                               1 - Vollscreen-Applikation
                               2 - Kompatibel mit API
                               3 - Benutzt das API
                         b7  : Programm enthaelt 80x87-Instruktionen
                         b6  : Programm enthaelt 80386-Instruktionen
                         b5  : Programm enthaelt 80286-Instruktionen
                         b4  : Programm enthaelt 8086-Instruktionen
                         b3  : Programm laeuft nur im Protected-Mode
                         b2  : Programm benutzt Globale Initialisierung
                         b0-1: Verwaltung der DGROUP:
                               0 - Keine DGroup vorhanden (NOAUTODATA)
                               1 - Eine gesharete DGroup (SINGLEDATA)
                               2 - Mehrere nicht gesharte DGroups
(MULTIPLEDA.)
  Eh     1W   ExnADS   Anzahl der Automatischen Datensegmente
 10h     1W   ExnGLH   Anfangsgroesse des lokalen Heaps
 12h     1W   ExnGSS   Anfangsgroesse des Stacks
 14h     1W   ExnSIP   Startwert des IP-Registers
 16h     1W   ExnSCS   Startwert des CS-Registers
 18h     1W   ExnSSP   Startwert des SP-Registers
 1Ah     1W   ExnSSS   Startwert des SS-Registers
 1Ch     1W   ExnASe   Anzahl der Segmenttabellen-Eintraege
 1Eh     1W   ExnARe   Anzahl der Eintraege in der Modul-Referenztabelle
 20h     1W   ExnARN   Laenge der res. Namenstabelle
 22h     1W   ExnOSe   Offset zum Anfang der Segmenttabelle (rel. NE)
 24h     1W   ExnORe   Offset zum Anfang der Ressourcentabelle (rel. NE)
 26h     1W   ExnORN   Offset zum Anfang der residenten Namenstabelle (rel.
NE)
 28h     1W   ExnOMR   Offset zum Anfang der Modul-Referenztab. (rel. NE)
 2Ah     1W   ExnOIN   Offset zum Anfang der "Importet" Namenstab. (rel. NE)
 2Ch     1D   ExnONN   Offset zum Anfang der nicht res. Namenstab. (rel. MZ)
 30h     1W   ExnAVE   Anzahl der verschieb. Eintrittspunkte
 32h     1W   ExnAli   ALIGN-Wert des Linkers
 34h     1W   ExnARS   Anzahl der Ressourcensegmente
 36h     1B   ExnFl2   Ziel-Betriebbsystem-Flag:
                         0 = Betriebystem unbekannt
                         1 = Microsoft OS/2
                         2 = Microsoft Windows
                         3 = MS-DOS 4.x (mit Detach-Unterstuetzung)
                         4 = Microsoft Windows 386
                         5 = BOSS (Borlands DOS Erweiterung)
 37h     1B   ExnFl3   Flags fuer Windows 3.0
                         b3  : Programm enthaelt Fast-Load-Area
                         b2  : Win 2.xx Applikation unterstuetzt Prop.-Schrift
                         b1  : Win 2.xx Applikation laeuft im Win 3.0
                               Protected Mode
                         b0  : OS/2 Programm unterstuetzt lange Dateinamen
 38h     1W   ExnAFL   Anfang der Fast-Load-Area (nur Windows)
 3Ah     1W   ExnLFL   Laenge der Fast-Load-Area (nur Windows)
 3Ch     1W   ExnRes   Minimale Code-Swap Area-Groesse
 3Eh     1W   ExnVer   Windows-Versionsnummer (nur Windows)

Literatur:
  Detlev Hoppenrath: "OS/2: Das neue EXE-Format", D&E 07/88, S.109ff
  Kevin P. Welch: "Die Dateiformate von Windows-Programmen und Ressourcen",
    MSJ 1/92, S.59ff
  R.Brown: "Interrupt List", Release 33

   e. OS/2-Exe

File-Format V1.x siehe Windows-Exe, da vom Aufbau identisch.

File-Format V2.0 siehe Erweiterte-Exe, da vom Aufbau prinzipiell identisch.
(Ausnahme: 'LE'-Kennung wurde durch 'LX'-Kennung ersetzt.)

   f. Novell ladbare Module NLM (*)

Offset Laenge  Name     Inhalt
  0h    23B   NlmKen   NLM-Kennug (='NetWare loadable Module')
 17h     5B   NlmRe1   Reserviert ?
 1Ch    13B   NlmDat   Dateiname (PString)
 29h    89B   NlmRe2   Reserviert ?
 82h     xB   NlmNam   Modul-Name (PString)

Keine Formatbeschreibung vorliegend, daher alle Angaben ohne Gewaehr.

   g. Novell VAPs (*)

Normales DOS-EXE-Programm mit zusaetzlichem VAP-Header am Anfang des Programm
Textes

Offset Laenge  Name     Inhalt   ("VAP-Header")
  0h     6B   VapKen   VAP-Kennung (='NWProc')
  6h    28B   VapRe1   Reserviert ?
 22h    64B   VapInf   VAP-Name (Null-terminiert)

Keine Formatbeschreibung vorliegend, daher alle Angaben ohne Gewaehr.




hier nun das beispielproggi:
{$G+,S-,N-}                 { KOPFINFO - Anzeige der Kopfinformation }
{$M $800,0,0}               { von .EXE-Programmen. (c) 1990-95 by    }
program EXE_Header;         { Mathias Mueller@2:240/4019.24          }
                            { Freeware                               }

                            { getestet }

const
    DoRelocTbl: boolean = false;
    DoRelocHex: boolean = false;
    fname: string = '';

Type
  EXEHdrType = Record       { Kopf einer .EXE-Datei von DOS               }
    Signature,              { Signatur ('MZ')
                                           Mark Zbikovski laesst gruessen }
    ImgLo, ImgHi,           { 'eigentliche' Dateigroesse                  }
    RelocItems,             { Anzahl Elemente in RelocTbl                 }
    HdrSize,                { Groesse des Dateikopfes in Paragraphs       }
    MinHeap, MaxHeap,       { minimaler, maximaler Platzbedarf            }
    StartSS, StartSP,       { Startwert fuer SS:SP                        }
    Checksum,
    StartIP, StartCS,       { Startwert fuer CS:IP                        }
    RelocStart : Word;      { Startadresse RelocTbl im Dateikopf          }
  end;
  li = LongInt;             { bin schreibfaul                             }


var KopfInfo: ExeHdrType;               { einmal Kopfinfo }
    f: file;
    s: string;
    i: integer;
    RelAdress: pointer;                 { eine relocations-Adresse }
    RelVal: li;                         { als Offset }


function HexB(zahl: byte): string;      { Zeigt ein Byte als Hex }
const Digits: array[0..15] of char =
      '0123456789ABCDEF';
begin
  HexB:= Digits[zahl shr 4] +           { High-Nibble zuerst }
         Digits[zahl and $0F];          { Low-Nibble dazu }
end;

function Hex(W: word): string;          { Zeigt ein Word als Hex }
begin
  Hex:= HexB(hi(W)) + HexB(lo(W));
end;


begin
  writeln;
  writeln('KOPFINFO - Anzeige der Kopfinformation von .EXE-Programmen');
  Writeln('           (c) 1990-95 by Mathias Mueller@2:240/4019.24');
  writeln;


  if Paramcount = 0 then
  begin
    writeln;
    writeln('Benutzung: KOPFINFO <EXE-Datei[.EXE]> [/R] [/H]');
    writeln('<EXE-Datei> muss ein Programm sein,');
    writeln('wenn Sie -R angeben, wird die Relocationsliste ausgegeben,');
    writeln('     mit -H hexadezimal.');
    halt(1);
  end;
  for i:= 1 to ParamCount do
  begin
    s:= ParamStr(i);
    if (s[1] = '-') and (UpCase(s[2]) = 'R') then  { irgendwelche Optionen }
      DoRelocTbl:= true
    else
    if (s[1] = '-') and (UpCase(s[2]) = 'H') then
      DoRelocHex:= true
    else
      fname:= s;                        { nein, dann isses wohl ein Filename }
  end;
  if fname = '' then
  begin
    writeln('Programmname fehlt in der Kommandozeile!');
    halt(2);
  end;
  filemode:= 0;                { nur Lesen, keine Probleme mit Schreibschutz }
  for i:= 1 to length(fname) do fname[i]:=upcase(fname[i]);
  if pos('.',fname) = 0 then fname:=fname + '.EXE' else fname:=fname;
  assign(f,fname);
  {$I-} reset(f, 1); {$I+}
  if IOResult <> 0 then
  begin
    writeln('Datei ',fname,' laesst sich nicht oeffnen!');
    halt(3);
  end;
  blockread(f, KopfInfo, sizeof(KopfInfo));             { Kopfinfo holen }
  writeln('Kopfinformation von ',fname,':');
  with KopfInfo do
  begin
    if Signature <> $5A4D then
    begin
      writeln(fname,' entspricht nicht dem EXE-Format!');
      halt(4);
    end;
    writeln('Signatur:                            ',
             char(lo(Signature)),char(hi(Signature)));
    writeln('Dateigroesse (DOS):                  ',
             FileSize(f):8,' Byte');
    writeln('Programmgroesse (Kopfinformation):   ',
             li(ImgHi-1) * 512 + ImgLo:8,' Byte');
    writeln('Anzahl zu relozierender Adressen:    ',
             RelocItems:8);
    writeln('Groesse der EXE-Kopfinformation:     ',
             li(HdrSize) * 16:8,' Byte');
    writeln('Minimaler Bedarf oberhalb Programm:  ',
             li(MinHeap) * 16:8,' Byte');
    writeln('Maximaler Bedarf oberhalb Programm:  ',
             li(MaxHeap) * 16:8,' Byte');
    writeln('Stacksegment relativ zum Codesegment:   $',
             Hex(StartSS),' (',StartSS,') Paragraphs = ',li(StartSS) * 16,
             ' Byte ');
    writeln('Startwert fuer Stackpointer (SP):       $',
             Hex(StartSP),' (',StartSP,') Byte');
    writeln('Pruefsumme (?):                         $',
             Hex(Checksum),' (',Checksum,')');
    writeln('1. Codesegment relativ zum Programm:    $',
             Hex(StartCS),' (',StartCS,') Paragraphs = ',li(StartCS) * 16,
             'Byte ');
    writeln('Startwert fuer Instructionpointer (IP): $',
             Hex(StartIP),' (',StartIP,')');
    writeln('Offset Relocationsliste im File:     ',
             RelocStart:8,' Byte');
    if DoRelocTbl or DoRelocHex then            { Relokationsliste gefragt? }
    begin
      seek(f, RelocStart);                      { auf Beginn }
      writeln('zu relozierende Adressen (Offset ab Dateianfang):');
      for i:= 1 to RelocItems do
      begin
        blockread(f, RelAdress, sizeof(RelAdress));
        RelVal:= li(seg(RelAdress^))*16 + ofs(RelAdress^); { Konversion }
        if DoRelocHex and (RelVal <= $FFFF) then   { Hex geht nur fuer word }
          write('$',Hex(RelVal),'  ')
        else
          write(RelVal:6,' ');
        if i mod 11 = 0 then writeln;   { Zeilenvorschub }
      end;
    end;
  end;
end.
