I am reading Eldad Eilam's reverse engineering book and trying to follow his RtlInitializeGenericTable example.

The first part of it is fairly straightfoward-

7C921A3E MOV EAX,DWORD PTR SS:[EBP+8] ; eax = UnknownStruct->Member1
7C921A43 LEA ECX,DWORD PTR DS:[EAX+4] ; ecx = UnknownStruct->Member2

7C921A46 MOV DWORD PTR DS:[EAX],EDX   ; UnknownStruct->Member1 = 0;
7C921A48 MOV DWORD PTR DS:[ECX+4],ECX ; UnknownStruct->Member3 = &UnknownStruct->Member2;
7C921A4B MOV DWORD PTR DS:[ECX],ECX   ; UnkownStruct->Member2  = &UnknownStruct->Member2;
7C921A4D MOV DWORD PTR DS:[EAX+C],ECX ; UnknownStruct->Member4 = &UnknownStruct->Member2;

Where I get confused is in the second part:

7C921A50 MOV ECX,DWORD PTR SS:[EBP+C] ; ecx = UnknownStruct->Member2
7C921A53 MOV DWORD PTR DS:[EAX+18],ECX; UnknownStruct->Member7 = UnknownStruct->Member2;
7C921A56 MOV ECX,DWORD PTR SS:[EBP+10]; ecx = UnknownStruct->Member3
7C921A59 MOV DWORD PTR DS:[EAX+1C],ECX; UnknownStruct->Member8 = UnknownStruct->Member3; 

In this part, offsets to the EBP are used to access variables and set their value. However, in his decompiled-c-equivalent output, it is shown that memory addresses are not being used as the initialization value, i.e.

UnknownStruct->Member7 = UnknownStruct->Member2;

whereas in the first part, they are:

UnknownStruct->Member3 = &UnknownStruct->Member2;

Why is this the case? As far as I can tell both parts should be the same- the only difference between the first and second is the LEA instruction, but that should only calculate the offset to the base pointer, the same as what is done in the second part.


  • 1
    Note that some compilers are use lea to encode arithmetic operations. It allows to perform an addition together with a multiplication by a constant at once and it is known to be much quicker than calling the add or imul instructions. It seems to be the case here. – perror Aug 12 '19 at 10:30
  • You may also take a look at this answer on Stack-Overflow. – perror Aug 12 '19 at 10:36

if eax = 1000 ecx will be 1004 in first part uf ebp = 1000 ecx will be *(dword *) 100c in second part

simply put in pseudo c

ecx = foo in first part it is simple assignment

ecx = * foo in second part it is dereferencing

notice the difference of & ( addressof operator) in both comments

the Function in Question Has A prototype of

NTSYSAPI VOID RtlInitializeGenericTable(
  PRTL_GENERIC_TABLE            Table,
  PVOID                         TableContext

so some one calling that function will be doing some thing like this

rettype callingconv comp(...);  //prototype for actual function implemented elsewhere
rettype callingconv alloc(...);
rettype callingconv free(...);

RTL_GENERIC_TABLE mytable = {0}; 


so [ebp + 8] the FirstArgument to the Function will hold the address of mytable
or by design the Address of first member of that Structure
which is PRTL_SPLAY_LINKS TableRoot; which is documented to be SystemResereved
so a NULL is filled in there (xor edx,edx , mov [eax],edx)

lea ecx is Load Effective Address of [eax+4]

so ecx will by design be the address of LIST_ENTRY InsertOrderList;

so there ecx, ecx+4 which point to Flink and Blink of the LIST_ENTRY are initialised with ecx

eax + c the third member of RTL_GENERIC_TABLE is

PLIST_ENTRY OrderedPointer; which is initialised with ecx too

| improve this answer | |
  • are you asking about the function name RtlInitializeGenericTable if yes I did not guess it the op mentions it at start I just looked up the documentation for the function – blabb Aug 12 '19 at 22:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.