If you appreciate the work done within the wiki, please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

Format:PE

From The Cutting Room Floor
Jump to navigation Jump to search

PE, or Portable Executable, is the executable file format employed by Microsoft on Windows ever since NT in 1993, and 95 for home users. Canonically valid executables meant as programs that can be run will always come with the extension .exe, which became known as its name for most people due to being its one unique identifier for them. Dynamic Link Libraries, also known as DLLs are also simply PEs with different characteristics and the canonical extension .dll instead, having overall the same structure besides that.

Header

DOS Stub

Since in 1993 the MZ format was still being widely used for DOS executables in Microsoft systems, PE employs a DOS executable at the start so that it can also run on them.

Location Specification name Meaning Function
0x00 e_magic MZ stub signature. Used to identify the MZ stub and a PE as a whole, still.
0x08 e_cparhdr (executable_countparagraphsheader) The count of paragraphs (16 bytes long) in the header. Practically, only used to point to where does the MZ executable begin.
0x3C e_lfanew (*longfileaddress) Pointer to the PE's new header, the PE header.

Some PEs will have a second mode just for DOS, but by the time of Windows 95's popularity, this executable was turned into a stub with only the following message:

This program must be run under Win32

A second, alternative message was also used in the following years and became the default DOS stub message by the time of Windows XP, replacing the first message.

This program cannot be run on DOS mode.

Machine Code

What comes before it will always be 16-bit x86 instructions to show the message, since Microsoft only ran its products on x86 PCs at the time. They are noted down here in Assembly.

push cs       ; Move Code Segment to stack
pop ds        ; Move stack to Data Segment
; Without these two instructions above, code cannot run on DOS
mov dx, $0E   ; Move 0x0E (offset to the message) to whole data register
mov ah, $09   ; Move 9 ("Print String" function on INT 21h) to high accumulator
int $21       ; INT 21h
mov ax, $4C01 ; Move 0x4C01 to accumulator, effectively executing functions 0x4C and 1 ("Terminate a Process" and "Read Keyboard Input", giving control back to DOS)
int $21