en:docs:tk:formats:newexe

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:docs:tk:formats:newexe [2024/09/22 09:40] prokusheven:docs:tk:formats:newexe [2026/05/15 03:41] (current) prokushev
Line 1: Line 1:
 +====== New Executable file format ======
 +
 +New Executable (NE) file format used by set of operating system including OS/2, Windows, Multitasking MS-DOS 4 and set of DOS Extenders. It is designed to be store on disk and in-memory usage. In-disk format is same for all OSes, but In-memory usage is mostly specific for Windows systems.
 +
 +===== New Executable header =====
 +
 ^ Offset ^ Size ^ Name ^ Description ^ ^ Offset ^ Size ^ Name ^ Description ^
-| 00h | WORD | e_magic 0x4d0x5a. This is the "magic number" of an EXE file. The first byte of the file is 0x4d and the second is 0x5a. +| 00h | WORD | ne_magic Signature word NEMAGIC (0x4E45'NE') | 
-02h WORD e_cblp  The number of bytes in the last block of the program that are actually used. If this value is zero, that means the entire last block is used (i.e. the effective value is 512)+| On-disk |||| 
-| 04h | WORD | e_cp Number of blocks in the file that are part of the EXE file. If [02-03] is non-zero, only that much of the last block is used. +| 02h | BYTE | ne_ver | Version number of the linker 
-| 06h | WORD | e_crlc | Number of relocation entries stored after the header. May be zero. +03h BYTE ne_rev Revision number of the linker | 
-08h | WORD | e_cparhdr Number of paragraphs in the header. The program's data begins just after the header, and this field can be used to calculate the appropriate file offset. The header includes the relocation entries. Note that some OSs and/or programs may fail if the header is not a multiple of 512 bytes. +| In-memory (Windows|||| 
-0Ah WORD e_minalloc Number of paragraphs of additional memory that the program will needThis is the equivalent of the BSS size in a Unix program. The program can't be loaded if there isn't at least this much memory available to it. +| 02h | WORD | count | Usage count  
-| 0Ch | WORD | e_maxalloc Maximum number of paragraphs of additional memoryNormally, the OS reserves all the remaining conventional memory for your program, but you can limit it with this field. | +| 04h | WORD | ne_enttab Entry Table file offset, relative to the beginning of the segmented EXE header | 
-0EH | WORD | e_ss Relative value of the stack segment. This value is added to the segment the program was loaded at, and the result is used to initialize the SS register. | +| On-disk |||
-10h | WORD | e_sp Initial value of the SP register. +| 06h | WORD | ne_cbenttab | Number of bytes in the entry table 
-12h | WORD | e_csum Word checksum. If set properly, the 16-bit sum of all words in the file should be zero. Usuallythis isn't filled in. +In-memory (Windows) |||| 
-14h | WORD | e_ip Initial value of the IP register. +| 06h | WORD | next Selector to next module 
-16h | WORD | e_cs Initial value of the CS register, relative to the segment the program was loaded at. +On-disk |||
-18h | WORD | e_lfarlc Offset of the first relocation item in the file+| 08h | DWORD | ne_crc | 32-bit CRC of entire contents of fileThese words are taken as 00 during the calculation | 
-1Ah | WORD | e_ovno Overlay number. Normally zeromeaning that it'the main program. +| In-memory (Windows) ||||     
-1Ch | WORD | e_res[ERES1WDS] | | +| 08h | WORD | dgroup_entry | Near ptr to segment entry for DGROUP | 
-    WORD e_oemid; +| 0Ah | WORD | fileinfo | Near ptr to file info (OFSTRUCT) 
-    WORD e_oeminfo; +| 0Ch | WORD | ne_flags Flag word | 
-    WORD e_res2[ERES2WDS]; +| 0Eh | WORD | ne_autodata | Segment number of automatic data segmentThis value is set to zero if SINGLEDATA and MULTIPLEDATA flag bits are clearNOAUTODATA is indicated in the flags word. A Segment number is an index into the module's segment tableThe first entry in the segment table is segment number 1 
-    DWORD e_lfanew;+10h | WORD | ne_heap Initial size, in bytes, of dynamic heap added to the data segment. This value is zero if no initial local heap is allocated | 
 +| 12h | WORD | ne_stack | Initial size, in bytes, of stack added to the data segment. This value is zero to indicate no initial stack allocationor when SS is not equal to DS | 
 +| 14h | DWORD | ne_csip | Segment number:offset of CS:IP | 
 +| 18h | DWORD | ne_sssp | Segment number:offset of SS:SP \\ If SS equals the automatic data segment and SP equals zero, the stack pointer is set to the top of the automatic data segment just below the additional heap area\\ <code>+--------------------------+ 
 +! additional dynamic heap  ! 
 ++--------------------------+ <- SP 
 +!    additional stack      ! 
 ++--------------------------+ 
 +! loaded auto data segment ! 
 ++--------------------------+ <- DS, SS </code> 
 +1Ch | WORD | ne_cseg Number of entries in the Segment Table 
 +1Eh | WORD | ne_cmod Number of entries in the Module Reference Table | 
 +| 20h | WORD | ne_cbnrestab | Number of bytes in the Non-Resident Name Table | 
 +| 22h | WORD | ne_segtab | Segment Table file offsetrelative to the beginning of the segmented EXE header 
 +24h | WORD | ne_rsrctab Resource Table file offset, relative to the beginning of the segmented EXE header 
 +26h | WORD | ne_restab Resident Name Table file offset, relative to the beginning of the segmented EXE header | 
 +| 28h | WORD | ne_modtab | Module Reference Table file offset, relative to the beginning of the segmented EXE header 
 +2Ah | WORD | ne_imptab Imported Names Table file offset, relative to the beginning of the segmented EXE header | 
 +| 2Ch | DWORD | ne_nrestab | Non-Resident Name Table offset, relative to the beginning of the file | 
 +30h | WORD | ne_cmovent Number of movable entries in the Entry Table | 
 +| 32h | WORD | ne_align | Logical sector alignment shift countlog(base 2) of the segment sector size (default 9) 
 +34h | WORD | ne_cres Number of resource entries 
 +| 36h | BYTE | ne_exetyp | Executable type, used by loader. \\ 00h=Unknown (any “new‑format” OS) \\ 01h=OS/2 \\ 02h=Windows \\ 03h=European MS‑DOS 4.x \\ 04h=Windows 386 \\ 05h=BOSS (Borland Operating System Services) \\ 81h=PharLap 286<nowiki>|</nowiki>DOS-Extender, OS/2 \\ 82h=PharLap 286<nowiki>|</nowiki>DOS-Extender, Windows | 
 +| 37h | BYTE | ne_flagsothers | Operating system flags | 
 +| 38h | WORD | ??? | offset to return thunks or start of gangload/fastload area | 
 +| 3Ah | WORD | ??? | offset to segment reference thunks or length of gangload/fastload area (Windows) | 
 +| 3Ch | WORD | ??? | minimum code swap area size (Windows) | 
 +| 3Eh | 2 BYTEs | ??? | expected Windows version (minor version first) (Windows)|
  
 +===== Flag word (ne_flags) =====
 +^ Bit(s) ^ Mask ^ Name ^ Description ^
 +| 0-1 | - | NOAUTODATA | No an automatic data segment |
 +| 0 | 0001h | SINGLEDATA | Per-process library data (shared DGROUP) |
 +| 1 | 0002h | MULTIPLEDATA | Per-instance library data |
 +| 8 | 0100h | NENOTWINCOMPAT | Not compatible with PM Windowing (full screen only) (OS/2) |
 +| 9 | 0200h | NEWINCOMPAT | Compatible with PM Windowing (OS/2) |
 +| 10 | 0300h | NEWINAPI | Uses PM Windowing API (OS/2) |
 +| 11 | 0800H | FIRSTDISC/NEBOUND | First segment in the executable file contains code that loads the application (Windows). Bound Family API (OS/2) |
 +| 13 | 2000h | LINKERROR | Errors detected at link time, module will not load |
 +| 14 | 4000h | NENOTMPSAFE | Non-conforming program (valid stack is not maintained) (Windows) Process is not multi‑processor safe (OS/2) |
 +| 15 | 8000h | LIBRARY | Module is a dynamic‑link library (DLL) |
  
-/* In-disk and In-memory module structureSee 'Windows Internals' p219 */+===== Operating system flags (ne_flagsothers) ===== 
 +^ Bit ^ Mask ^ Name ^ Description ^ 
 +| 0 | 01h | NELONGNAMES | Supports long file names (OS/2) | 
 +| 1 | 02h | NEWINISPROT | Windows 2.x app runs in protected mode (Windows) | 
 +| 2 | 04h | NEWINGETPROPFON | Windows 2.x app gets proportional font (Windows) | 
 +| 3 | 08h | NEGANGLOAD | Contains gangload/fastload area (Windows) | 
 +| 7 | 80h | NEWLOAPPL | WLO application on OS/2 (markwlo.exe) (OS/2) |
  
-struct new_exe { +On-disk segment entry
-    WORD  ne_magic; /* Signature word EMAGIC */ +
- union { +
- struct { +
- BYTE   ne_ver; /* Version number of the linker */ +
- BYTE   ne_rev; /* Revision number of the linker */ +
- }; +
- WORD  count; /* Usage count (ne_ver/ne_rev on disk) */ +
- }; +
-    WORD  ne_enttab; /* Entry Table file offset, relative to the beginning of +
-    the segmented EXE header */ +
- union { +
- WORD  ne_cbenttab; /* Number of bytes in the entry table */ +
- WORD  next; /* Selector to next module */ +
- }; +
- union { +
- DWORD            ne_crc; /* 32-bit CRC of entire contents of file. +
-    These words are taken as 00 during the calculation */ +
- struct { +
- WORD dgroup_entry; /* Near ptr to segment entry for DGROUP */ +
- WORD fileinfo; /* Near ptr to file info (OFSTRUCT)*/ +
- }; +
- }; +
-    WORD  ne_flags; /* Flag word */ +
-    WORD  ne_autodata; /* Segment number of automatic data segment. +
-    This value is set to zero if SINGLEDATA and +
-    MULTIPLEDATA flag bits are clear, NOAUTODATA is +
-    indicated in the flags word.+
  
-    A Segment number is an index into the module's segment +^ Offset ^ Size ^ Name ^ Description ^ 
-    table. The first entry in the segment table is segment +| 00h | WORD | ns_sector | Logical-sector offset (n byte) to the contents of the segment datarelative to the beginning of the fileZero means no file data | 
-    number 1 */ +| 02h | WORD | ns_cbseg | Length of the segment in the file, in bytes. Zero means 64K | 
-    WORD  ne_heap; /* Initial sizein bytes, of dynamic heap added to the +| 04h | WORD | ns_flags | Flag word | 
-    data segmentThis value is zero if no initial local +| 06h | WORD | ns_minalloc | Minimum allocation size of the segment, in bytes. Total size of the segment. Zero means 64K |
-    heap is allocated */ +
-    WORD  ne_stack; /* Initial size, in bytes, of stack added to the data +
-    segmentThis value is zero to indicate no initial +
-    stack allocation, or when SS is not equal to DS */ +
-    DWORD            ne_csip; /* Segment number:offset of CS:IP */ +
- DWORD            ne_sssp; /* Segment number:offset of SS:SP. +
-    If SS equals the automatic data segment and SP equals +
-    zerothe stack pointer is set to the top of the +
-    automatic data segment just below the additional heap +
-    area.+
  
-    +--------------------------+ +In-memory (Windows) segment entry
-    | additional dynamic heap  | +
-    +--------------------------+ <- SP +
-       additional stack      | +
-    +--------------------------+ +
-    | loaded auto data segment | +
-    +--------------------------+ <- DS, SS */ +
-    WORD  ne_cseg; /* Number of entries in the Segment Table */ +
-    WORD  ne_cmod; /* Number of entries in the Module Reference Table */ +
-    WORD  ne_cbnrestab; /* Number of bytes in the Non-Resident Name Table */ +
-    WORD  ne_segtab; /* Segment Table file offset, relative to the beginning +
-    of the segmented EXE header */ +
-    WORD  ne_rsrctab; /* Resource Table file offset, relative to the beginning +
-    of the segmented EXE header */ +
- WORD  ne_restab; /* Resident Name Table file offset, relative to the +
-    beginning of the segmented EXE header */ +
-    WORD  ne_modtab; /* Module Reference Table file offset, relative to the +
-    beginning of the segmented EXE header */ +
-    WORD  ne_imptab; /* Imported Names Table file offset, relative to the +
-    beginning of the segmented EXE header */ +
-    DWORD ne_nrestab; /* Non-Resident Name Table offset, relative to the +
-    beginning of the file */ +
-    WORD ne_cmovent; /* Number of movable entries in the Entry Table */ +
-    WORD ne_align; /* Logical sector alignment shift count, log(base 2of +
-    the segment sector size (default 9) */ +
-    WORD ne_cres; /* Number of resource entries */ +
-    BYTE ne_exetyp; /* Executable type, used by loader. +
-    02h = WINDOWS */ +
-    BYTE ne_flagsothers; /* Operating system flags */ +
-    char ne_res[NERESBYTES]; /* Reserved */  +
-};+
  
-// On-disk segment entry +^ Offset ^ Size ^ Name ^ Description ^ 
-struct new_seg { +| 00h | WORD ns1_sector Logical-sector offset (n byte) to the contents of the segment data, relative to the beginning of the file. Zero means no file data | 
-    WORD  ns_sector; /* Logical-sector offset (n byte) to the contents of the segment +| 02h | WORD ns1_cbseg Length of the segment in the file, in bytes. Zero means 64K | 
-    data, relative to the beginning of the file. Zero means no +| 04h | WORD ns1_flags Flag word | 
-    file data */ +| 06h | WORD ns1_minalloc Minimum allocation size of the segment, in bytes. Total size of the segment. Zero means 64K | 
-    WORD  ns_cbseg; /* Length of the segment in the file, in bytes. Zero means 64K */ +| 08h | WORD ns1_handle Selector or handle (selector - 1) of segment in memory |
-    WORD  ns_flags; /* Flag word */ +
-    WORD  ns_minalloc; /* Minimum allocation size of the segment, in bytes. Total size +
-    of the segment. Zero means 64K */ +
-}; +
- +
-// In-memory segment entry +
-struct new_seg1 { +
-    WORD  ns1_sector; /Logical-sector offset (n byte) to the contents of the segment +
-    data, relative to the beginning of the file. Zero means no +
-    file data */ +
-    WORD  ns1_cbseg; /Length of the segment in the file, in bytes. Zero means 64K */ +
-    WORD  ns1_flags; /Flag word */ +
-    WORD  ns1_minalloc; /Minimum allocation size of the segment, in bytes. Total size +
-    of the segment. Zero means 64K */ +
-    WORD  ns1_handle; /Selector or handle (selector - 1) of segment in memory */ +
-};+
  
 +<code c>
 struct new_segdata { struct new_segdata {
     union {     union {
Line 135: Line 104:
     } ns_union;     } ns_union;
 }; };
 +</code>
  
-struct new_rlcinfo { +Relocation table header
-    WORD  nr_nreloc; +
-};+
  
-struct new_rlc { +^ Offset ^ Size ^ Name ^ Description ^ 
-    char            nr_stype; +| 00h | WORD | nr_nreloc | Number of relocation table entries |
-    char            nr_flags; +
-    WORD  nr_soff; +
-    union { +
-        struct { +
-            char            nr_segno; +
-            char            nr_res; +
-            WORD  nr_entry; +
-          } nr_intref; +
-        struct { +
-            WORD  nr_mod; +
-            WORD  nr_proc; +
-          } nr_import; +
-        struct { +
-            WORD  nr_ostype; +
-            WORD  nr_osres; +
-          } nr_osfix; +
-      } nr_union; +
-};+
  
-#define NR_STYPE(x)     (x).nr_stype +Relocation table entry
-#define NR_FLAGS(x)     (x).nr_flags +
-#define NR_SOFF(x)      (x).nr_soff +
-#define NR_SEGNO(x)     (x).nr_union.nr_intref.nr_segno +
-#define NR_RES(x)       (x).nr_union.nr_intref.nr_res +
-#define NR_ENTRY(x)     (x).nr_union.nr_intref.nr_entry +
-#define NR_MOD(x)       (x).nr_union.nr_import.nr_mod +
-#define NR_PROC(x)      (x).nr_union.nr_import.nr_proc +
-#define NR_OSTYPE(x)    (x).nr_union.nr_osfix.nr_ostype +
-#define NR_OSRES(x)     (x).nr_union.nr_osfix.nr_osres+
  
-#define NRSTYP      0x0f +^ Offset ^ Size ^ Name ^ Description ^ 
-#define NRSBYT      0x00 +| 00h | char | nr_stype | Source type (0Fh = NRSTYP - source mask): 00h = LOBYTE, 02h = SEGMENT, 03h = FAR_ADDR (32-bit pointer), 05h = OFFSET (16-bit offset) | 
-#define NRSSEG      0x02 +| 01h | char | nr_flags | Flags byte (03h = TARGET_MASK): 00h = INTERNALREF, 01h = IMPORTORDINAL, 02h = IMPORTNAME, 03h = OSFIXUP, 04h = ADDITIVE | 
-#define NRSPTR      0x03 +| 02h | WORD | nr_soff | Offset within this segment of the source chain. If the ADDITIVE flag is set, then target value is added to the source contents, instead of replacing the source and following the chain. The source chain is an 0FFFFh terminated linked list within this segment of all references to the target | 
-#define NRSOFF      0x05 +| Internal fixup |||| 
-#define NRPTR48     0x06 +| 04h | char | nr_segno | Segment number (for fixed segment) or 0FFh (for movable segment) | 
-#define NROFF32     0x07 +| 05h | char | nr_res | Reserved (usually zero) | 
-#define NRSOFF32    0x08+| 06h | WORD | nr_entry | Entry table number (for movable segment) offset segment | 
 +| Import |||| 
 +| 04h | WORD | nr_mod | ??? | 
 +| 06h | WORD | nr_proc | ??? | 
 +| OS Fixup |||| 
 +| 04h | WORD | nr_ostype | ??? | 
 +| 06h | WORD | nr_osres | ??? |
  
-#define NRADD       0x04 
-#define NRRTYP      0x03 
-#define NRRINT      0x00 
-#define NRRORD      0x01 
-#define NRRNAM      0x02 
-#define NRROSF      0x03 
-#define NRICHAIN    0x08 
  
-#if (EXE386 == 0)+^ Offset ^ Size ^ Name ^ Description ^ 
 +| 00h | char | rs_len | ??? | 
 +| 01h | char | rs_string[1] | ??? |
  
-#define RS_LEN(x)       (x).rs_len +^ Offset ^ Size ^ Name ^ Description ^ 
-#define RS_STRING(x)    (x).rs_string +| 00h | WORD | rt_id | ??? | 
-#define RS_ALIGN(x)     (x).rs_align+| 02h | WORD | rt_nres | ??? | 
 +| 04h | DWORD | rt_proc | ??? |
  
-#define RT_ID(x)        (x).rt_id +^ Offset ^ Size ^ Name ^ Description ^ 
-#define RT_NRES(x)      (x).rt_nres +| 00h | WORD | rn_offset | ??? | 
-#define RT_PROC(x)      (x).rt_proc+| 02h | WORD | rn_length | ??? | 
 +| 04h | WORD | rn_flags | ??? | 
 +| 06h | WORD | rn_id | ??? | 
 +| 08h | WORD | rn_handle | ??? | 
 +| 0Ah | WORD | rn_usage | ??? |
  
-#define RN_OFFSET(x)    (x).rn_offset +^ Offset ^ Size ^ Name ^ Description ^ 
-#define RN_LENGTH(x)    (x).rn_length +| 00h | WORD rs_align | ??? | 
-#define RN_FLAGS(x)     (x).rn_flags +| 02h | struct rsrc_typeinfo rs_typeinfo | ??? |
-#define RN_ID(x)        (x).rn_id +
-#define RN_HANDLE(x)    (x).rn_handle +
-#define RN_USAGE(x)     (x).rn_usage +
- +
-#define RSORDID     0x8000 +
- +
-#define RNMOVE      0x0010 +
-#define RNPURE      0x0020 +
-#define RNPRELOAD   0x0040 +
-#define RNDISCARD   0xF000 +
- +
-#define NE_FFLAGS_LIBMODULE 0x8000 +
- +
-struct rsrc_string { +
-    char    rs_len; +
-    char    rs_string[1]; +
-}; +
- +
-struct rsrc_typeinfo { +
-    WORD  rt_id; +
-    WORD  rt_nres; +
-    DWORD            rt_proc; +
-}; +
- +
-struct rsrc_nameinfo { +
-    WORD  rn_offset; +
-    WORD  rn_length; +
-    WORD  rn_flags; +
-    WORD  rn_id; +
-    WORD  rn_handle; +
-    WORD  rn_usage; +
-}; +
- +
-struct new_rsrc { +
-    WORD          rs_align; +
-    struct rsrc_typeinfo    rs_typeinfo+
-}; +
- +
-#endif +
- +
-#pragma pack(pop) +
- +
-#ifdef __cplusplus +
-} /* extern "C" */ +
-#endif+
  
-#endif 
  
 +  * Microsoft KB: Q65122: Executable-File Header Format
 +  * Windows SDK 3.1 (MSDN Library, September 1992)