포스트

시스템 프로그래밍 3. Complie

시스템 프로그래밍 3. Complie

건국대학교 시스템 프로그래밍 진현욱 교수님의 수업을 정리한 내용입니다.

Complie

Complie이란, .c .cpp .java ... 등의 사람 친화적인 언어를 기계어(Binary)로 번역하는 과정이다. 컴파일 과정은 크게 네 단계로 구분한다.

Preprocessing Phase

전처리 단계. #이 붙은 전처리 구문을 처리하거나, 주석을 없앤다.

  • #define MAX(x, y) ((x >= y) ? (x) : (y))을 보고, 모든 MAX를 (x >= y) ? (x) : (y)로 치환한다.
  • #if, #ifndef, ifdef, #else 와 같이 조건이 만족되지 않은 부분을 버린다.

Compilation Phase

CAssembly Language로 번역하는 단계.

만약 C 문법에 오류가 있다면, 이 과정에서 오류가 발생한다.

Assembly Phase

Assembly Language를 기계어로 번역하는 단계.

Linking Phase

라이브러리, 다른 파일의 함수 호출 등을 연결해서 하나의 실행 파일로 만든다.

[!NOTE] NOTE{title} 현재 파일에서 호출은 하고 있지만, 다른 파일에 있는건가? 싶은 것들을 한 테이블에 몰아둔다.

각각의 파일들이 갖고 있는 모든 Symbol(public 함수 이름, 전역 변수 이름) 등을 찾아서 테이블에 있는 것과 연결할 수 있는게 있는지 본다.

그렇게 해서 연결하고, 하나의 파일로 만든다.

Static Library라면 라이브러리 파일을 실행 파일과 합쳐서 하나의 파일로 만들고, Dymamic Library라면 라이브러리를 불러올 여지만 만들어둔다.

Library (라이브러리)

라이브러리는 정적 라이브러리(Static Library)와 동적 라이브러리(Dynamic Library) 두가지가 존재한다. 정적 라이브러리와 동적 라이브러리의 차이는 무엇인가?

Static Library

링크 시간에 프로그램에 포함되는 라이브러리.

.a, .lib 확장자를 가진다.

Dymamic Library

프로그램 실행 시점에 동적으로 링크되는 라이브러리.

.so, .dll 확장자를 가진다.

GCC (GNU Compiler Collection)

각 단계를 담당하는 Preprocessor, Complier, Assembler, Linker가 존재한다. Preprocessor에 c 파일을 넣어 나온 결과를 Complier에 넣고, 나온 .s 파일을 Assembler에 넣어 .o 파일을 얻고, 최종적으로 Linker에 모든 파일을 넣어 Executable (실행 가능한) 파일을 얻는다.

이 과정을 묶어 한번에 해줄 수 있게 만든게 GCC다.

Command 사용법

1
gcc -Og p1.c p2.c -o name
  • -o name : out 파일 이름을 name으로 명시하겠다.
  • -Og, -Os, -O0, -O1, -O2, -O3, -Ofast : Optimization Level (최적화 레벨) 설정.
    • 최적화의 정도를 지정한다.
    • -Og는 가장 기본적인 최적화, -Os는 코드 크기를 최소화 하는 최적화,
    • -O0 ~ -Ofast는 뒤로 갈수록 빡센 최적화를 수행한다.
    • 그럼 최적화가 잘될 수록 좋은게 아니냐?
      • 너무 최적화를 빡세게 하면, 코드의 논리가 바뀌어버릴 수도 있으니 적당히.
  • -E : Preprocessing 까지만 해라
  • -S : Compile 까지만 해라
    • 어셈블리 언어로 번역된 파일(.s)을 얻을 수 있음
  • -c : Assembley 까지만 해라
    • 기계어로 번역된 파일(.o)을 얻을 수 있음
  • -l<디렉토리> : 헤더 파일이 들어있는 곳을 명시할 수 있음.
    • -lopengl -lglew32
  • -g : 디버깅 모드로 컴파일.

Disassemble

Pasted image 20240914110330.png

기계어에서 어셈블리 언어로 되돌리는 방법이다. 하지만 원래 어셈블리 코드와 100% 똑같은 코드를 만들어내지는 않는다. 결정적으로 원래 변수의 이름을 알 수가 없다.

Command

1
objdump -d name

name이라는 execuable 파일을 disassembler 하라.