详细分析CONTAINING_RECORD宏

来源:互联网 发布:js获取div高度并赋值 编辑:程序博客网 时间:2024/05/16 02:05


该宏的作用是:用结构成员中的ListEntry的地址(0x108)减去结构体成员ListEntry到首地址的距离(8)得到结构体首地址(0x100

 

 

pEntry中的值就是结构成员中的ListEntry的地址。即:0x108

ListEntry

0x108 结构成员中的ListEntry的地址,也是RemoveHeadList函数函数的值

 

y

0x104

ListEntry在结构体中的开始位置是8

x

0x100结构体首地址

 

第一个成员存在低地址上

内存的地址是由低往高

 

 

typedef struct _MYDATASTRUCT{

 

        Ulongx;

        Ulongy;

        LIST_ENTRYListEntry;//这里的ListEntry在结构体中的开始位置是8

        

}MYDATASTRUCT,*PMYDATASTRUCT;

 

PLIST_ENTRYpEntry = RemoveHeadList(&head);

PMYDATASTRUCTpMydata = CONTAINING_RECORD(pEntry,MYDATASTRUCT,ListEntry);//可以理解为:pEntry - &MYDATASTRUCT.ListEntry

 

【注释】

 

1、实参MYDATASTRUCTListEntry用于返回ListEntry在结构体中的开始位置8,之后用结构成员中的ListEntry的地址(保存在了pEntry中)减去它就得到了结构体首地址(0x100)

 

2、反汇编代码如下:

 

#define CONTAINING_RECORD(address, type, field) ((type*)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))

 

注释:

 

(type *)((PCHAR)(address)就是pEntry中的值,就是0x108

 

(ULONG_PTR)(&((type *)0)->field)))返回的是结构体成员ListEntry到首地址的距离

 

((type *)0)->field  转换为(*0).field = [EAX(eax=0) + field] 。&会转换为LEA就返回8了  即:LEA [EAX(0)+8]

 

即:0x108- 8 = 0x100  指向了结构体的起始地址

 

3、若MYDATASTRUCT结构的第一个成员是ListEntry,就不存在这种问题了,因为100-0=100还是指向了结构体的第一个成员,CONTAINING_RECORD的作用就是指向结构体的第一个成员,若不指向结构体第一个成员就该报错了。

 

typedefstruct _MYDATASTRUCT{

 

  LIST_ENTRY ListEntry;

        ULONG x;

        Ulong y;

                

}MYDATASTRUCT,*PMYDATASTRUCT;

 

 

 

 

 

y

0x108

 

x

0x104

pEntry 起初指向了这里-->

ListEntry

0x100

0 0
原创粉丝点击