Windows 32、64位系统编译器各数据类型大小和字节对齐关系
何为32位64位?
32位64位其实就是32bit 64bit ,32位cpu单次处理指令4字节,64位8字节,因为1字节=1byte=8bit(32/8=4字节,64/8=8字节)
32位编译器:32位系统下指针占用4字节
64位编译器:64位系统下指针占用8字节
struct结构体成员中对齐关系:
字节对齐的细节和具体编译器实现相关,但一般而言,需满足以下四个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。
4)结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储
随便贴几个32/64相同结构体字节对齐填充示例:
{32位}
_UNICODE_STRING = packed record
Length : USHORT;
MaximumLength : USHORT;
Buffer : PWideChar;
end;
UNICODE_STRING = _UNICODE_STRING;
PUNICODE_STRING =^_UNICODE_STRING;
{64位}
_UNICODE_STRING64 = packed record
Length : USHORT; //USHORT=2字节
MaximumLength : USHORT;
Fill : DWORD; //填充4字节对齐
Buffer : ULONG64;//ULONG64; //PVOID64
end;
UNICODE_STRING64 = _UNICODE_STRING64;
PUNICODE_STRING64 =^_UNICODE_STRING64;
{32位}
PLDR_DATA_TABLE_ENTRY = ^LDR_DATA_TABLE_ENTRY;
LDR_DATA_TABLE_ENTRY = packed Record
InLoadOrderModuleList:LIST_ENTRY;
InMemoryOrderModuleList:LIST_ENTRY;
InInitializationOrderModuleList:LIST_ENTRY;
BaseAddress:Cardinal;
EntryPoint:Cardinal;
SizeOfImage:Cardinal;
FullDllName:UNICODE_STRING;
BaseDllName:UNICODE_STRING;
Flags:Cardinal;
LoadCount:Word;
TlsIndex:Word;
SectionHandle:Cardinal;
CheckSum:Cardinal;
TimeDateStamp:Cardinal;
end;
{64位}
PLDR_DATA_TABLE_ENTRY64= ^LDR_DATA_TABLE_ENTRY64;
LDR_DATA_TABLE_ENTRY64 = packed record
InLoadOrderModuleList:LIST_ENTRY64;//PVOID64;//LIST_ENTRY;
InMemoryOrderModuleList:LIST_ENTRY64;//PVOID64;//LIST_ENTRY;
InInitializationOrderModuleList:LIST_ENTRY64;//PVOID64;//LIST_ENTRY;
BaseAddress:ULONG64;
EntryPoint:ULONG64;
SizeOfImage:ULONG64;//ULONG; //8字节对齐
FullDllName:UNICODE_STRING64;
BaseDllName:UNICODE_STRING64;
Flags:ULONG;
LoadCount:USHORT;
TlsIndex:USHORT;
end;
{32位}
PPEB_LDR_DATA =^PEB_LDR_DATA;
PEB_LDR_DATA = packed record
Len:Cardinal;
Initialized:Bool;
SsHandle:PPointer;
InLoadOrderModuleList:LIST_ENTRY;
InMemoryOrderModuleList:LIST_ENTRY;
InInitializationOrderModuleList:LIST_ENTRY;
end;
{64位}
PPEB_LDR_DATA64= ^PEB_LDR_DATA64;
PEB_LDR_DATA64 = packed record
Length:ULONG; //4Byte
Initialized:BOOLEAN; //1Byte
Reserved1: array [0..2] of Byte; //3Byte 补3字节填充跟前面一起凑成8字节
SsHandle:ULONG64; //8Byte
InLoadOrderModuleList:LIST_ENTRY64; // PVOID64
InMemoryOrderModuleList:LIST_ENTRY64;
InInitializationOrderModuleList:LIST_ENTRY64;
EntryInProgress:ULONG64;
end;
{32位}
PPEB = ^PEB;
PEB = packed record
Reserved1: array[0..1] of Byte;
BeingDebugged: ByteBool;
Reserved2: Byte;
Reserved3: array[0..1] of Pointer;
Ldr: PPEB_LDR_DATA; //Pointer
ProcessParameters: PRTL_USER_PROCESS_PARAMETERS;
Reserved4: array[0..103] of Byte;
Reserved5: array[0..51] of Pointer;
end;
{64位}
PPEB64 = ^PEB64;
PEB64 = packed record
InheritedAddressSpace : UCHAR; //1 Byte
ReadImageFileExecOptions : UCHAR;
BeingDebugged: UCHAR;
BitField: UCHAR;
Reserved1:DWORD; //因为64位系统是8字节对齐,所以补4位,跟前面4个uchar一起凑成8字节
Mutant:ULONG64; //编译器问题,VC++不用补位,实测VS2017,VS2015中编译器貌似会自动填充对齐
ImageBaseAddress: ULONG64;
Ldr:PVOID64; //PPEB_LDR_DATA64; //ULONG64;
ProcessParameters:PVOID64;//PRTL_USER_PROCESS_PARAMETERS64; // ULONG64;
SubSystemData: ULONG64;
ProcessHeap: ULONG64;
FastPebLock: ULONG64;
AtlThunkSListPtr:ULONG64;
IFEOKey: ULONG64;
CrossProcessFlags: ULONG64;
UserSharedInfoPtr: ULONG64;
SystemReserved: ULONG;
AtlThunkSListPtr32:ULONG;
ApiSetMap: ULONG64;
end;
Delphi中32位64位程序在64位系统下各数据类型占用字节统计如下:
具体字节对齐填充原理可以参考此连接:
原创文章,转载请注明出处!谢谢
本文来自博客园,作者:IT情深,转载请注明原文链接:https://www.cnblogs.com/wh445306/p/16751793.html