| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- Dos Stub
- __stdcall
- 리버싱
- x32
- crackme
- RVA
- 함수 호출 규약
- __fastcall
- 코드엔진
- x64
- Programmers
- __cdecl
- rev
- Calling Convention
- Python
- 32bit
- stack frame
- 프로그래머스
- image section header
- pe format
- 실행파일
- Rich Header
- 크랙미
- Reversing
- ABI
- 파이썬
- Image dos header
- __vectorcall
- CodeEngn
- 리치헤더
- Today
- Total
kj0on
[Definition] 컴파일 (Compilation) 본문
1. 정의
| 표준 | 정의 |
| ISO/IEC 15145:1997(en), 2.1.10 | To transform source code into dictionary definitions. |
| ISO/IEC 20060:2010(en), 3.9 | transform higher-level specifications of software and/or data into executable form |
| ISO/IEC 2382:2015(en), 2121864 | translate all or part of a program expressed in a high-level language into a program expressed in an intermediate language, an assembly language, or a machine language |
| ISO/IEC/IEEE 24765:2017(en), 3.679 | to translate a computer program expressed in a high-order language into its machine language equivalent |
ISO/IEC 15145:1997은 "소스 코드를 사전(dictionary) 정의로 변환"
ISO/IEC 20060:2010은 "소프트웨어 또는 데이터의 상위 사양을 실행 가능한 형태로 변환"
ISO/IEC 2382:2015는 "고급 언어로 표현된 프로그램의 전부 또는 일부를 중간 언어, 어셈블리 언어 또는 기계 언어로 표현된 프로그램으로 번역"
ISO/IEC/IEEE 24765:2017은 "고급(고차) 언어로 작성된 컴퓨터 프로그램을 기계어 등가물로 번역"
위 표준들에서의 정의를 종합해 보면 컴파일은 사람이 이해할 수 있는 고수준 언어를 컴퓨터가 해석 또는 실행할 수 있는 저수준 형태(중간어, 기계어, 사전 구조)로 변환하는 과정을 의미한다.
2. 컴파일 & 인터프리터

일반적으로 C, C++은 소스 코드를 기계어로 변환해 목적 프로그램 또는 실행파일(exe)을 만들고, Python은 실행 시점에 소스를 바이트코드로 변환해 인터프리터(VM)가 즉시 실행하는 인터프리트 방식을 택한다. Java는 두 방식의 중간쯤에 위치해 소스를 먼저 바이트코드(.class)로 컴파일한 뒤 JVM이 그 바이트코드를 실행한다. 컴파일 방식은 한 번 빌드해 목적 프로그램을 만들어 두면 소스 없이도 반복 실행할 수 있는 반면, 인터프리트 방식은 매 실행마다 소스와 해당 인터프리터 환경이 함께 있어야 한다는 점이 가장 큰 차이다.

컴파일 언어는 분석 이후 합성(Synthesis) 단계를 거치기 때문에 처음 한 번은 빌드 시간이 필요하다. 반면 인터프리트 언어는 별도 빌드 단계 없이 곧바로 소스를 읽어 실행을 시작기 때문에 처음 실행은 인터프리트 방식이 더 빠를 수 있다. 다만 기계어로 완전히 변환된 컴파일 언어 프로그램은 실행 시 추가 해석이 없어, 일반적으로 인터프리트 언어 프로그램보다 빠르게 동작한다.
3. 컴파일 전체 과정

전형적인 빌드 파이프라인은 보통
(1) (소스) Skeleton Source → (2) 전처리기(Preprocessor) → (3) 컴파일러(Front-Back-End) → (4) 어셈블러 → (5) 링커 → (6) 완전한 실행 파일(Absolute Machine Code)
순으로 설명한다. 다만 문헌마다 컴파일의 범위를 다르게 잡기 때문에, 어떤 자료는 전처리, 컴파일, 어셈블까지만을 컴파일 단계로 보고 링커를 별도 단계로 분리하거나, 반대로 전처리까지 포함한 전 과정을 통틀어 컴파일이라 칭하기도 한다.
4. GCC
이번 실습에서는 GCC(GNU Compiler Collection)를 이용해 전처리 → 컴파일 → 어셈블 → 링크로 이어지는 전체 빌드 파이프라인을 직접 살펴본다. 각 단계 내부의 세부 절차는 설명 범위에서 제외한다.
4-1. 소스

hello.c에는 전처리 지시문, 함수 정의, 주석 등이 그대로 들어 있다. 프로그램의 논리와 의도를 사람이 이해할 수 있는 형태로 담아 전처리기로 넘기는 출발점이 된다.
4-2. 전처리기

전처리기는 #include, #define, 조건부 컴파일 지시문 등을 해석해 헤더를 삽입하고 매크로를 펼쳐 하나의 완전한 번역 단위로 정리한다. 컴파일러가 바로 토큰화를 시작할 수 있도록 소스를 정규화하고 불필요한 주석을 제거하는 역할을 한다.
4-3. 컴파일러

컴파일러는 전처리 결과를 받아 토큰화, 분석을 거쳐 중간 표현(IR)을 만들고, 최적화를 수행한 뒤 대상 ISA에 맞는 어셈블리나 머신 코드로 변환한다. 언어 차원의 의미를 이해하고 하드웨어가 실행 가능한 명령, 레지스터 조합으로 설계하는 역할을 한다.
4-4. 어셈블러

어셈블러는 컴파일러가 만든 어셈블리 텍스트를 0과 1의 기계어 바이트로 인코딩하고, 코드, 데이터, 심벌, 재배치 정보를 포함한 오브젝트 파일(.o)을 생성한다. 명령어 목록을 실제 CPU 명령어 시퀀스로 찍어내는 역할을 한다.
4-5. 링커

링커는 여러 오브젝트 파일과 라이브러리를 모아 전역 심벌을 해석하고 섹션을 배치하며 재배치를 적용해 단일 실행 파일을 만든다. 흩어져 있던 코드와 데이터를 하나로 묶어 완전하게 주소가 결정된 프로그램 이미지를 조립하는 역할을 한다.
4-6. 완전한 실행 파일

최종 실행 파일은 운영체제 로더가 바로 메모리에 적재해 CPU에 넘길 수 있는 형태로, 사용자가 명령을 내리면 즉시 실행된다.
4-7. GCC 전체 과정

5. Visual Studio

cl /EP hello.c > hello.i # or cl /P hello.c

cl /c /FAcs hello.c /Fohello.obj /Fahello.asm


link hello.obj /OUT:hello.exe /SUBSYSTEM:CONSOLE /ENTRY:mainCRTStartup



6. 참고 문헌
[1] 컴파일(Compile)에 대한 이해, https://bradbury.tistory.com/226
'Reversing > Definition' 카테고리의 다른 글
| [Definition] 32비트 함수 호출 규약 (32bit Calling Convention) (5) | 2025.07.14 |
|---|---|
| [Definition] 32비트 스택 프레임 (32bit Stack Frame) (0) | 2025.07.13 |
| [Definition] RVA to RAW (0) | 2025.07.07 |
| [Definition] VA & RVA & RAW (0) | 2025.07.06 |
| [Definition] Rich Header (3) | 2025.07.05 |