C 컴파일 과정의 기본

이 기사에서는 gcc (GNU Compiler Collection) 및 C 으로 작성된 "Hello, World"프로그램을 사용하여 컴파일러가 작동하는 방식에 대해 논의할 것입니다.

요약


  • Introduction

  • What is a compiler?
  • Preprocessing
  • Compiling
  • Assembling
  • Linking

  • References

  • 소개




    // simple_program.c
    
    #include <stdio.h>
    
    int main(){
        printf("Hello, world!\n");
        return 0;
    }
    


    먼저 모든 컴퓨터 프로그램은 위의 simple_program.c와 같은 텍스트 파일로 시작합니다. 이 텍스트 파일에는 문자(인간 문자)가 포함되어 있어 코드를 쉽게 작성하고 이해할 수 있습니다.

    $ xxd simple_program.c
    
    00000000: 2369 6e63 6c75 6465 2022 7374 6469 6f2e  #include "stdio.
    00000010: 6822 0a0a 696e 7420 6d61 696e 2829 7b0a  h"..int main(){.
    00000020: 2020 2020 7072 696e 7466 2822 4865 6c6c      printf("Hell
    00000030: 6f2c 2077 6f72 6c64 5c6e 2229 3b0a 2020  o, world\n");.  
    00000040: 2020 7265 7475 726e 2030 3b0a 7d0a         return 0;.}.
    


    my xxd 에서 simple_program.c 명령을 사용하여 소스 코드의 hexadecimal 표현을 읽을 수 있습니다. 예를 들어, 첫 번째 줄에는 2369 , 23 는 16진수, 2335 에 대한 ASCII 코드인 10진수 시스템에서 # 입니다. 이 패턴은 이 C 프로그램의 다른 모든 문자에 대해 동일합니다. 이러한 유형의 표현은 인간에게 매우 적합하므로 모든 것을 이해하고 코드를 작성할 수 있습니다.

    그러나 컴퓨터는 사람이 아니라 기계이며 기계는 이진수(0과 1)만 이해합니다. 위의 코드를 컴퓨터가 읽고 실행할 수 있는 것으로 어떻게 "번역"하거나 컴파일합니까? 이를 위해 "컴파일러"라는 소프트웨어를 사용합니다.

    컴파일러 란 무엇입니까?



    컴파일러는 단순히 어떤 프로그래밍 언어로 작성된 코드를 다른 프로그래밍 언어로 번역하는 소프트웨어입니다. 우리의 경우 C 코드를 일련의 저수준 기계 명령어로 변환하는 컴파일러가 필요합니다. 그 번역을 하기 위해서는 전처리, 컴파일, 어셈블, 링크의 4가지 주요 단계를 이해해야 합니다.

    전처리



    처리 단계에서 컴파일러는 # 로 시작하는 모든 지시문을 읽습니다. 우리의 경우 #include <stdio.h> , 목표는 지시문 stdio.h을 읽고 stdio.h의 모든 내용을 프로그램에 직접 삽입하는 것입니다. 예를 들어 printf() 를 사용하여 Hello, world! 를 인쇄할 때 printf() 함수는 stdio.h 에 저장됩니다. 이것이 우리가 이 지시문을 포함해야 하는 이유입니다. 그렇지 않으면 컴파일에서 오류가 발생할 수 있습니다.

    처리 결과를 얻으려면 gcc -E simple_program.c 를 실행할 수 있습니다.

    컴파일



    컴파일 단계에서 컴파일러는 사전 처리된 프로그램을 가져와 실제로 Assembly 이라는 저수준 언어로 컴파일합니다.

    어셈블리 지침을 얻기 위해 다음 명령을 실행할 수 있습니다. gcc -S simple_program.c 그러면 simple_program.s라는 파일이 생성됩니다( .s는 어셈블리 지침이 있는 파일의 확장자입니다).

    조립



    어셈블리 단계에서 컴파일러는 simple_program.s 파일을 가져오고 기계 명령이 포함된 이진 파일인 파일 개체.o(Windows의 경우 .exe)를 빌드하기 위해 어셈블러를 사용합니다.

    연결



    링크는 컴파일의 마지막 단계입니다. 이 단계에서 컴파일러는 프로그램에서 잠재적으로 사용했던 여러 모듈의 모든 개체 코드를 연결합니다. 예를 들어 printf() 에서 stdio.h 를 사용했습니다. 이제 링커는 모든 것을 바이너리 파일에 넣고 우리 프로그램인 단일 실행 파일을 만듭니다.

    프로그램을 얻으려면 gcc simple_program.c 를 실행할 수 있습니다. 결과는 a.out라는 파일이 됩니다(simple_program.c 에 오류가 없으면 바이너리를 얻을 수 없습니다).

    이제 프로그램을 실행할 수 있습니다.

    $ ./a.out
    Hello, world!
    


    이제 프로그램을 변경할 때마다 소스 코드에서 컴파일러를 다시 실행해야 소프트웨어가 변경 사항으로 새 바이너리를 생성할 수 있습니다.

    참고문헌



    Assembly Language
    Compiler
    C programming language

    좋은 웹페이지 즐겨찾기