[1-4] 코드가 실행 파일이 되기까지

C 언어는 사람이 작성하는 인간 친화적인 언어입니다. 컴퓨터는 C 언어로 된 코드를 해석해서 실행할 능력이 없습니다.

컴퓨터는 컴퓨터 나름대로 쓰는 말(언어)이 따로 있습니다. 기계어라고 합니다.

소크 코드가 기계어가 되는 과정은 다음과 같습니다.

컴파일 과정

전처리의 컴파일하기에 전처리 지시자를 해석합니다. 전처리 지시사는 #으로 시작합니다. 필요한 파일을 불러오고 컴파일 옵션을 적용하고 매크로를 치환 및 적용합니다. 앞에서 다룬 코드 첫 줄에 있는 #include라는 키워드는 뒤에 오는 파일을 포함하라는 전처리 지시사입니다. 이처럼 #으로 시작하는 모든 명령을 수행합니다.

[알림] 전처리 지시사에 대한 자세한 설명은 이후에 다룹니다. 매크로도 전처리 지시사입니다. 일단은 이대로 넘어가겠습니다.

컴파일러는 소스 코드를 기계어로 된 어셈블리 파일로 바꿉니다. 이를 컴파일이라고 합니다. 이때 소스 코드를 원시 코드라도 합니다. 이때 기계어는 CPU 종류에 따라 다릅니다.

어셈블러는 오브젝트 파일을 만듭니다. 어셈블리 파일이 기계어기는 하지만 아직은 특정 포맷을 갖춘 것이 아니기 때문에 오브젝트 형식의 파일로 만드는 겁니다.

링커는 오브젝트 파일을 모아 실행 파일을 만듭니다. 이를 링크한다고 합니다. 일반적으로 상용 프로그램은 소스 코드가 여러 파일로 구성됩니다. 각 파일마다 오브젝트 파일로 만들어져 있습니다. 링크는 실행 파일 형식에 오브젝트 파일들을 하나로 모으는 작업입니다.

원시 코드를 어셈블리 파일로 변환하는 자체로만 컴파일로 보는 시각은 좁은 해석입니다. 컴파일은 전처리, 컴파일, 어셈블, 링크를 모두 포함합니다. 이 글에서는 특별한 경우가 아니면 컴파일이라는 용어를 광의의 해석으로 사용할 겁니다.

관우가 지금까지 내용을 간단히 표현해보겠습니다.

  1. 전처리기 - 헤쳐 모여
  2. 컴파일러 - 1단 변신
  3. 어셈블러 - 2단 변신
  4. 링커 - 합체

이상으로 코드가 실행 파일이 되기까지의 과정을 알아보았습니다.

아차! 제 친구 제갈량이 CPU에 대한 깊은 이야기를 하고 싶다고 하네요. 물론 선택은 어려분의 몫입니다. 지금까지 관우였습니다!

제갈량의 동남풍

x86 호환 CPU

CPU도 종류가 엄청 다양합니다. 그래서 제각각의 언어를 가지고 있습니다. x86 호환 CPU가 들어간 PC에서는 일반적으로 x86 어셈블리 계열을 사용합니다. 16비트 시절 64비트까지 다음과 같이 발전했다.

IA-32 어셈블리 : x86-32라고도 합니다. 32비트 언어로 기존에 사용하던 16비트 인텔 x86 프로세서 아키텍쳐와에 완벽히 호환됩니다. x86-64 : AMD64 또는 AMD 64비트 확장입니다. 32비트에도 성능 손실 없이 호환되는 64비트용 언어입니다. 인텔 64.IA-32e 또는 EM64T라고도 합니다. x86-64와 거의 같습니다.

x86 계열 아키텍처는 원래 인텔이 처음 개발했는데, 32비트까지는 완벽하게 하위 호환을 제공했는데, 64비트에 대응하면서 하위 호환에도 문제가 있었습니다. 만년 2위던 AMD가 이틈을 놓치지 않고 AMD64라는 이름으로 32비트까지 완벽 호환하는 아키텍처를 제공하는 바람에 결국에는 치욕적이게도 인텔이 AMD 아키텍처를 따르게 되었습니다(자존심이 있으니까 AM64라고 명명을 못하고 x86-64라고 붙여 사용합니다. 그래서 인텔 64는 안녕 ㅠ,.ㅠ/~).