hello 프로그램은 프로그래머가 에디터로 작성한 소스 프로그램(소스파일)으로 생명을 시작하고 hello.c라는 텍스트 파일로 저장된다.
소스 프로그램은 0 또는 1로 표시되는 비트의 연속이며 바이트라는 8비트 단위로 구성된다. 각 바이트는 프로그램의 텍스트 문자를 나타낸다.
hello.c처럼 아스키 문자들로만 이루어진 파일들을 텍스트 파일이라고 하며 다른 파일들은 바이너리 파일이라고 한다.
hello.c를 실행하려면 각 문장을 다른 프로그램에 의해 저급 기계어 인스트럭션으로 번역되어야 한다. 이를 목적 파일(object file)이라고 한다.
gcc 컴파일러 드라이버는 hello.c를 실행파일인 hello로 번역한다. 4개의 단계(전처리기, 컴파일러, 어셈블러, 링커)를 거치는데 이를 합쳐 컴파일 시스템이라고 부른다.
전처리 단계: 전처리기는 #문자로 시작하는 디렉티브에 따라 수정한다. 예를 들어 #include<stdio.h>는 전처리기에게 헤더파일인 stdio.h를 프로그램 문장에 직접 삽입하라고 지시한다. 그 결과 .i로 끝나는 새로운 C 프로그램이 생성된다.
컴파일 단계: 컴파일러는 텍스트파일 hello.i를 텍스트파일인 hello.s로 번역하며 이 파일에는 어셈블리어 파일이 저장된다.
어셈블리 단계: 어셈블러가 hello.s를 기계어 인스트럭션으로 번역하고 이들을 재배치가능 목적프로그램의 형태로 묶어서 hello.o라는 목적파일에 그 결과를 저장한다. 이 파일은 main 함수의 인스트럭션들을 인코딩하기 위한 17바이트를 포함하는 바이너리 파일이다.
링크 단계: printf 함수는 이미 컴파일된 별도의 printf.o에 들어있고 이 파일은 hello.o와 어떤 형태로든 결합되어야 한다. 링커 프로그램이 이 통합과정을 수행한다.
그 결과 hello 파일은 실행가능 목적파일로 메모리에 적재되어 시스템에 의해 실행된다.
프로그램 성능 최적화하기: 최신 컴파일러들은 복잡한 도구로 우수한 코드를 생성한다. 효율적인 코드를 작성하기 위해 컴파일러 내부 동작을 알 필요는 없다. 다만 컴파일러가 어떻게 기계어 코드로 번역하는지 알 필요는 있다.
링크 에러 이해하기
보안 약점 피하기
hello.c 소스 프로그램은 컴파일러에 의해 hello라는 목적파일(object file)로 변환된다. 이를 실행하기 위해서는 쉘에 그 이름을 입력하는데 명령어 라인이 쉘의 내장 명령어가 아니라면 쉘을 실행파일의 이름으로 판단하고 그 파일을 실행한다.