[OOP] 컴파일 언어가 실행 파일이 되는 과정 (컴파일, 어셈블, 링킹)

세동네·2022년 6월 16일
0
post-thumbnail
post-custom-banner

객체지향 프로그래밍 언어 중 C++는 컴파일 언어로 분류된다.

작성한 소스코드를 컴파일 - 어셈블 - 링킹이라는 단계에 거쳐 실행 파일을 만들게 되는데, 이 과정들에 대해 알아보자.

· 전처리

우리가 작성하는 코드들은 다양한 헤더 파일을 포함하고 특정 매크로를 지정하는 등 # 즉, 전처리 지시자가 포함된 구문을 작성할 것이다.

#include <iostream>
 
#define MAX(a, b) ((a > b) ? a : b)
#define LEN 2

전처리기는 전처리 지시자가 포함된 헤더를 포함하는 구문은 해당 헤더 파일 내부 코드로 변경해주고, 매크로 상수나 함수는 정의한 내용으로 소스코드를 변경해준다.

#include <iostream>

#define MAX(a, b) ((a > b) ? a : b)
#define LEN 2

int main() {
	int arr[LEN] = { 3, 5 };

	std::cout << MAX(arr[0], arr[1]) << std::endl;
}

예를 들어 위와 같은 소스코드을 작성했다면, 전처리 단계를 거쳐 iostream 헤더, MAX 매크로 함수, LEN 매크로 상수를 치환한다. iostream 헤더는 원래 아래와 같이 생겼다.

iostream이 포함하는 다른 헤더에 헤더를 타고 들어가다 보면 iostream 헤더 하나가 수천 줄의 코드로 이루어졌다는 것을 알 수 있다.

이러한 코드들이 앞서 살펴본 소스코드에 삽입되며 전처리 단계가 끝나면 아래와 같은 형태가 된다.

// iostream standard header

// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#pragma once
#ifndef _IOSTREAM_
#define _IOSTREAM_
#include <yvals_core.h>	// 이것과
#if _STL_COMPILER_PREPROCESSOR
#include <istream>		// 이 헤더도 그 내부 내용으로 치환된다.

#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
_STD_BEGIN
#ifdef _M_CEE_PURE
__PURE_APPDOMAIN_GLOBAL extern istream cin;
__PURE_APPDOMAIN_GLOBAL extern ostream cout;

...

#pragma warning(pop)
#pragma pack(pop)
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _IOSTREAM_

#define MAX(a, b) ((a > b) ? a : b)
#define LEN 2

int main() {
	int arr[2] = { 3, 5 };

	std::cout << ((arr[0] > arr[1]) ? arr[0] : arr[1]) << std::endl;
}

· 컴파일

컴파일(Compile)은 고수준 언어를 저수준 언어로 바꾸는 작업을 말한다. 엄밀히 말하자면 특정 언어로 작성된 코드를 다른 언어로 바꾸는 작업을 컴파일이라고 하지만, 일반적으로 사용하는 컴파일의 의미는 인간이 이해하는 고수준 언어를 어셈블리어와 같은 저수준 언어로 번역하는 것을 일컫는다. 그리고 컴파일을 해주는 소프트웨어를 컴파일러(Compiler)라 한다.

앞선 전처리 단계도 이 컴파일러가 함께 해주기 때문에 전처리 후 저수준 언어로의 변환까지 하나의 스텝으로 이해해도 괜찮다.

· 어셈블

어셈블(Assemble) 단계는 컴파일 단계에서 만들어진 저수준 언어 코드를 2진수로 이루어진 완전한 기계어로 번역해 .o 확장자를 가지는 목적 파일로 만들어주는 단계로, 어셈블러(Assembler)라는 프로그램이 이를 담당한다.

· 링킹

링킹(Linking)은 컴파일러가 생성한 목적 파일들과 정적 라이브러리를 합쳐 하나의 실행 파일을 만드는 작업이다. 정적 라이브러리는 이미 그 자체로 컴파일되어 손쉽게 가져다 사용할 수 있는 함수들의 집합이기 때문에 앞서 새롭게 컴파일한 목적 파일들과 손쉽게 합쳐질 수 있다.


· 참조

[나무위키] 컴파일러
정적 라이브러리와 동적 라이브러리
C++의 컴파일 과정
링킹

post-custom-banner

0개의 댓글