Computer/Programming

Compilation of C++ to binary

holycall 2008. 1. 11. 15:41
array 사용이 컴파일되었을 때의 모양
일반적인 local variable의 경우
    mov [ebp+var_38], 0    ; i = 0
과 같이 ebp 레지스터에 대한 상대 위치를 이용하여 표현한다.
array도 마찬가지인데
    mov [ebp+eax*4+var_2C], ecx   ; a[i] = i;
과 같이 ebp에 대한 상대 위치로 표현한다.
MOV r/m32, r32
MOV r32, r/m32
MOV r32, imm32
같은 instruction을 사용한다.
stack guard 같은 것을 사용하려면 첫번째 argument가 r/m32인 것만 찾으면 되는 것일까?


function pointer가 컴파일되었을 때의 모양
function pointer 값을 배열에 assign할 때
    fp[0] = &a;    // c++

    move [ebp+var_14], offset loc_4110F5
와 같이 컴파일되는 것을 볼 수 있다.
function을 call할 때
    (*fp[i])();   // c++

    move ecx, [ebp_eax*4+var_14]
    call ecx
와 같이 컴파일되는 것을 볼 수 있다.

즉 assign할 때는 location 값이 그대로 들어가고,
call할 때는 register에 location을 넣고 그대로 jump한다.

import한 function에 대한 call이 compile되는 경우 (VS2005)
DS / SS / CS (DS:data segment / SS:stack segment / CS:code segment)
    call    ds:__imp__scanf
의 경우 ds는 data segment를 가르키고,
__imp__scanf가 data segment 안에 있는 주소를 가리키는 offset이 된다.

전에 VS98로 compile할 때는
prinf같은 메소드들도 embed되었던 것 같다.


switch문의 경우 switch 갯수가 몇 개 되지 않을 때는 cmp를 이용하여 그대로 compile되지만,
갯수가 많을 때는
1. default(가장 큰 숫자보가 크다면 jmp) cmp / ja 형태로 컴파일되며
2. 나머지는 table에 만들어 넣는다. 1 byte이기 때문에 많아야 255개인데, default를 빼고 나머지에 대해서만 table을 만들어서 해당되는 숫자에 대한 주소를 그대로 읽어오고 그 곳으로 jump하는 식이다. vs 2005에서는 table이 text section 뒤에 붙어 있었다. 즉 code와 data가 mix되어 text section에 있던 것이다.

.text:00413779                 mov     eax, [ebp+var_8]
.text:0041377C                 mov     [ebp+var_D0], eax
.text:00413782                 cmp     [ebp+var_D0], 5Fh
.text:00413789                 ja      loc_4138C2
.text:0041378F                 mov     ecx, [ebp+var_D0]
.text:00413795                 movzx   edx, ds:byte_413954[ecx]
.text:0041379C                 jmp     ds:off_413920[edx*4]
.text:004137A3
.text:004137A3 loc_4137A3:                             ; DATA XREF: .text:off_413920o
.text:004137A3                 mov     esi, esp
.text:004137A5                 push    offset aA_0     ; "a"
.text:004137AA                 call    ds:__imp__printf
.text:004137B0                 add     esp, 4
.text:004137B3                 cmp     esi, esp
.text:004137B5                 call    j__RTC_CheckEsp
.text:004137BA
.text:004137BA loc_4137BA:                             ; CODE XREF: wmain+5Cj
.text:004137BA                                         ; DATA XREF: .text:00413924o
.text:004137BA                 mov     esi, esp
.text:004137BC                 push    offset aA       ; "a"
.text:004137C1                 call    ds:__imp__printf
.text:004137C7                 add     esp, 4
.text:004137CA                 cmp     esi, esp
.text:004137CC                 call    j__RTC_CheckEsp

이정도가 예제가 될듯


virtual call이 compile되는 경우
switch ~ case와 마찬가지로  table이 만들어져서,
해당하는 function으로 jump하도록 하고 있다.