我最近开始使用PE(Portable Executable)
文件格式,更具体地说是PE/COFF
。我正在阅读Randy Kath here的教程。
当我阅读MZ DOS标头的结构时,发现使用e_magic
字段中的签名验证了MZ DOS标头。结构如下:
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。
我的问题是一样的。
M
和Z
的ascii值分别是77
和90
,以十六进制转换为4D
和5A
。 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
)中的最高有效字节排在第一位。