일부 레지스터의 사용에 관하여 Windows debugging

레지스터는 CPU 연산에 필요한 데이타를 사용하기 위한 저장고이다. IA32 체계에서 EAX, EBX ECX, ESI, EDI 등등의 명칭으로 사용되고 있는 데, register가 사용되는 용도가 구분되어 있다. (참고: http://ko.wikipedia.org/wiki/IA32#.EB.A0.88.EC.A7.80.EC.8A.A4.ED.84.B0) Debugging 하다 보면, Assembly 언어를 분석할 때, register의 용도에 따라서 적절히 분석되는 것이 필요한데 몇가지 문서에 언급외에 독특한 register의 사용에 대해서 언급하고자 한다.

 

0:000> u 766dbf97-10 766dbf97+10

wininet!MEMMAP_FILE::ValidateListGroupOffset+0x38:

766dbf87 038d34118bc6    add     ecx,dword ptr [ebp-3974EECCh]

766dbf8d 5e              pop     esi

766dbf8e 5d              pop     ebp

766dbf8f c20400          ret     4

766dbf92 90              nop

766dbf93 90              nop

766dbf94 90              nop

766dbf95 90              nop

766dbf96 90              nop

wininet!MEMMAP_FILE::GrowMapFile:

766dbf97 8bff            mov     edi,edi

766dbf99 55              push    ebp

766dbf9a 8bec            mov     ebp,esp

766dbf9c 56              push    esi

766dbf9d 8bf1            mov     esi,ecx

766dbf9f 8b4604          mov     eax,dword ptr [esi+4]

766dbfa2 8b4e18          mov     ecx,dword ptr [esi+18h]

766dbfa5 69c080ed0100    imul    eax,eax,offset <Unloaded_es_kr.dll>+0x1ed6f (0001ed80)

 

Nop No-operation이다. 근데, Function starting point (노란색 블럭)mov edi, edi 가 보인다. 사실 그 아래 push ebp; mov ebp, esp; 는 일반적으로 Stack Frame을 만드는 시작 code이다. ebp stack base address이므로, 앞선 Function stack frame에 대한 base address stack save 하여 보존하고, 현 시점의 stack pointer base address로 지정하여 새로운 stack frame을 시작하도록 하는 역할을 한다. 그러므로, 그 앞서서 있는 mov edi, edi는 아무런 의미가 없다. , nop와 동일하다. 다른 점이라면, 2bytes opcode로써의 nop라는 점이다. 이는 나중에 jmp code로 변경하여 Hot patching에 이용되도록 집어 넣어둔 code이다. 이와 같은 방식은 CLR에서 method jitting의 경우도 방법자체로 보면 유사하다. MethodDesc RVA라는 거의 의미 없는 값을 가지고 있다가 나중에 JIT에 의해서 code generation된 이후에는 jmp instruction으로 해당 code address를 가리키도록 op code가 변경되는 구조를 갖는 다.

 

그 다음은 ecx/esi 에 대한 부분이다. ecx는 일반적으로 loop counter역할을 담당한다. 하지만, Debugging 할때 가장 많이 경험하는 것은 counter의 역할보다는 this pointer를 넘기는 데, 많이 사용된다. 

 

ChildEBP RetAddr  Args to Child             

00125bfc 76698bd7 00004000 00125c74 00000020 wininet!MEMMAP_FILE::GrowMapFile+0xb0 (FPO: [1,0,0])

00125c38 7667ff81 00001000 00000031 00000000 wininet!MEMMAP_FILE::AllocateEntry+0x4d (FPO: [Non-Fpo])

 

0:000> ub 76698bd7

. . .

76698bcf 50              push    eax

76698bd0 8bcb            mov     ecx,ebx   <- - - this pointer wininet!MEMMAP_FILE Class

76698bd2 e8c0330400      call    wininet!MEMMAP_FILE::GrowMapFile (766dbf97)

 

This pointer는 곧바로 esi register mov 된다. ecx register Frame 안에서 counter와 같은 범용레지스터로 사용되기 때문에 this pointer보존을 위해 esi mov 하고, esi+offset 형태로 this class member function이나 member property에 접근할 수 있다. 아래와 같은 assembly code 형태가 말해준다.

 

766dbf9c 56              push    esi

766dbf9d 8bf1            mov     esi,ecx

766dbf9f 8b4604          mov     eax,dword ptr [esi+4]

766dbfa2 8b4e18          mov     ecx,dword ptr [esi+18h]

 

그리고, 또한 eax register 의 역할이다. 아래 assembly code를 보면, function call되기 전에 push에 의해서 parameter를 전송하는 아름다운 모습이 보인다. 이는 Function calling convention에 의존적이다. 그리고, 나면, 저 아래께 쯤에 cmp instruction에 뜬금없는 eax ecx의 비교가 보인다. ecx esi+offset의 언급한 this class member property로 부터 온것임을 알 수 있다. 그럼, eax는 무엇인가 .

 

766dbfc2 6a02            push    2

766dbfc4 6a00            push    0

766dbfc6 57              push    edi

766dbfc7 ff761c          push    dword ptr [esi+1Ch]

766dbfca ff1570116676    call    dword ptr [wininet!_imp__SetFilePointer (76661170)]

766dbfd0 8b4e18          mov     ecx,dword ptr [esi+18h]

766dbfd3 03cf            add     ecx,edi

766dbfd5 3bc1            cmp     eax,ecx

 

이는 SetFilePointer function return value 이다. eax는 항상 function call이후에 return 값을 저장하는 데, 사용된다.


덧글

댓글 입력 영역