为什么PE文件中的MZ DOS Header Signature 0x54AD?

Why is the MZ DOS Header Signature 0x54AD in PE files?

我最近开始使用 PE(Portable Executable) 文件格式,更具体地说 PE/COFF。我正在阅读 Randy Kath here.

的教程

当我阅读 MZ DOS header 的结构时,我发现 MZ DOS header 是使用 e_magic 字段中的签名验证的。结构如下:

typedef struct _IMAGE_DOS_HEADER {  // DOS .EXE header
    USHORT e_magic;         // Magic number
    USHORT e_cblp;          // Bytes on last page of file
    USHORT e_cp;            // Pages in file
    USHORT e_crlc;          // Relocations
    USHORT e_cparhdr;       // Size of header in paragraphs
    USHORT e_minalloc;      // Minimum extra paragraphs needed
    USHORT e_maxalloc;      // Maximum extra paragraphs needed
    USHORT e_ss;            // Initial (relative) SS value
    USHORT e_sp;            // Initial SP value
    USHORT e_csum;          // Checksum
    USHORT e_ip;            // Initial IP value
    USHORT e_cs;            // Initial (relative) CS value
    USHORT e_lfarlc;        // File address of relocation table
    USHORT e_ovno;          // Overlay number
    USHORT e_res[4];        // Reserved words
    USHORT e_oemid;         // OEM identifier (for e_oeminfo)
    USHORT e_oeminfo;       // OEM information; e_oemid specific
    USHORT e_res2[10];      // Reserved words
    LONG   e_lfanew;        // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

教程说:

All MS-DOS-compatible executable files set this value to 0x54AD, which represents the ASCII characters MZ.

我的问题也是一样

MZ的ascii值分别是7790,转化为十六进制的4D5A . 0x54AD如何表示MZ

这可能是个愚蠢的问题。但如果它太傻了,请帮助我理解。

谢谢。

首先,声称签名的来源是0x54AD是错误的; MZ 在十六进制中实际上是 0x5A4D (对于小端架构),正如该程序的输出所证明的那样:

#include <Windows.h> // for the USHORT type
#include <stdio.h>

int main()
{
    USHORT MZ = ('M' | 'Z' << 8);
    printf("0x%.4X\n", MZ);
    return 0;
}

输出:

0x5A4D

你可能还有疑问,为什么'Z'(5A)的字节在前面,而签名实际上是'MZ'

这与字节顺序有关,字节顺序是字节存储在各个半字、字、双字等中的顺序。

大端存储字节,最高有效字节在最高内存地址,小端则相反,最高有效字节在最低有效内存地址。

x86 和 x64 架构是小尾数法,因此 MZ(即 Z)中的最高有效字节在前。