为什么PE文件中的MZ DOS头签名是0x54AD?

3
我最近开始学习PE(可移植可执行文件)文件格式,更具体地说是PE / COFF。我正在阅读Randy Kath的教程。当我浏览MZ DOS头的结构时,我发现MZ DOS头使用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;

教程中提到:

所有兼容MS-DOS的可执行文件都将此值设置为0x54AD,它代表ASCII字符MZ。

我的问题也一样。

MZ的ascii值分别是7790,在十六进制中分别转换为4D5A。那么0x54AD如何表示MZ

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

谢谢。

1个回答

2

首先,声称签名是0x54AD的来源是错误的;在十六进制中,MZ实际上是0x5A4D(对于小端架构),这可以通过此程序的输出证明:

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

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

输出:

0x5A4D

你可能会有疑问,为什么在签名实际上是'MZ'的情况下,字节'Z'(5A)先出现呢?
这与字节序有关,即以半字、字、双字等为单位存储字节的顺序。
大端存储将最重要的字节存储在最高的内存地址中,而小端则相反,将最重要的字节存储在最不重要的内存地址中。
x86和x64架构采用小端序,因此'MZ'中最重要的字节(即'Z')先出现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接