컴퓨터 구조

[2/20 출근 전 공부하는 컴퓨터 구조] C 언어 컴파일 과정 + CPU

여러가지 공부를 하고 있습니다. 2025. 2. 20. 08:30

 

C언어 컴파일 과정

 

1. 프로그램 실행 과정

1.1 전처리 과정 (Preprocessing)

➡️ 본격적인 컴파일을 하기 전에 코드에 대해 필요한 작업을 수행하는 과정.
✔ #include → 외부 라이브러리 포함
✔ #define → 매크로 변환
✔ #if, #ifdef → 특정 코드 블록을 포함/제외

📌 💡 중요한 이유:

  • 전처리가 없으면 코드 재사용성이 떨어지고, 유지보수가 어려움
  • C/C++ 컴파일러가 코드의 해석을 더 빠르게 할 수 있도록 도와줌

 


1.2 컴파일 과정 (Compiling)

➡️ 전처리된 소스 코드를 기계어로 변환하는 과정.
✔ 소스 코드(.c, .cpp) → 어셈블리 코드(.s) 로 변환
고급 언어 → 저급 언어(어셈블리어)로 변환하는 과정

📌 💡 중요한 이유:

  • CPU가 직접 이해할 수 있도록 코드 변환
  • 최적화된 코드로 변환하여 실행 속도를 높일 수 있음

1.3 어셈블 과정 (Assembling)

➡️ 어셈블리어를 기계어로 변환하는 과정
✔ 어셈블리어(.s) → 목적 코드(Object Code, .o)

📌 💡 중요한 이유:

  • 어셈블리어는 여전히 사람이 읽을 수 있는 형태이므로 최종적으로 0과 1로 이루어진 기계어로 변환 필요
  • 컴퓨터의 CPU가 직접 실행할 수 있는 바이너리 코드(기계어) 가 만들어짐

1.4 링킹 과정 (Linking)

➡️ 여러 개의 목적 파일을 하나의 실행 파일로 묶는 과정
✔ 목적 파일(.o) + 라이브러리 → 실행 파일(.exe, .out) 생성
외부 라이브러리(.lib, .dll, .so)와의 연결 포함

📌 💡 중요한 이유:

  • C 언어처럼 여러 개의 파일로 구성된 프로그램을 하나로 합치는 과정이 필수적
  • 표준 라이브러리(printf, scanf 등)를 포함하는 역할

 

Main.c를 실행파일로 바꿔도 실행할 수 없을 것이다. Helper.c와 연결을 시켜줘야함

그것을 둘이 연결시켜주는 작업을 링킹이라고 함

 

각기 다른 목적코드를 하나의 실행파일로 묶어주는 작업을 링킹이라고 한다. 


2. CPU 구조 및 역할

2.1 CPU 내부 구조

 

CPU는 크게 3가지 주요 요소로 나뉨:

  1. ALU (Arithmetic Logic Unit, 산술 논리 연산 장치)
    • 연산(덧셈, 뺄셈, 논리 연산 등) 수행
    • 연산 결과를 레지스터에 저장
  2. 제어장치(Control Unit)
    • 명령어를 해석하고 실행
    • CPU 내부 및 외부 장치에 제어 신호를 보냄
  3. 레지스터(Register)
    • CPU 내부의 초고속 메모리
    • 연산에 필요한 데이터를 저장 (일반 RAM보다 훨씬 빠름)

📌 💡 중요한 이유:

  • CPU는 단순히 연산하는 것이 아니라, 데이터 이동 & 제어 역할도 함께 수행해야 함.
  • 레지스터를 사용하면 메모리 접근 속도를 줄여 실행 속도를 높일 수 있음.

2.2 ALU(산술 논리 연산 장치)의 역할

 

 

✔ 레지스터에서 연산할 데이터를 받아 연산 수행
✔ 연산 결과를 레지스터 또는 메모리에 저장
✔ 연산 결과에 대한 부가 정보를 플래그로 저장

📌 💡 중요한 이유:

  • CPU의 핵심 연산 장치로, 모든 산술 & 논리 연산을 담당함.
  • 연산 결과가 양수/음수인지, 오버플로우가 발생했는지를 플래그로 저장하여 이후 명령어 실행에 활용됨.

2.3 플래그 레지스터 (Flag Register)의 역할

ALU가 연산한 결과를 CPU가 해석할 수 있도록 연산 결과에 대한 정보를 저장하는 공간.

플래그역할

부호 플래그 (Sign Flag, SF) 연산 결과가 음수(1) 인지 양수(0) 인지 저장
제로 플래그 (Zero Flag, ZF) 연산 결과가 0이면 1, 아니면 0
캐리 플래그 (Carry Flag, CF) 덧셈에서 올림수 발생 여부, 뺄셈에서 빌림 발생 여부 저장
오버플로우 플래그 (Overflow Flag, OF) 연산 결과가 표현할 수 있는 범위를 초과하면 1

📌 💡 중요한 이유:

  • CPU는 이 플래그 값을 기반으로 다음 명령어를 실행할지 결정함
  • 예를 들어, ZF = 1이면 결과가 0이므로 특정 분기문(if 문)이 실행될 수도 있음

2.4 제어장치(Control Unit)의 역할

 

 

제어장치는 CPU의 모든 동작을 조정하는 두뇌 역할을 수행함.

명령어 레지스터(IR, Instruction Register)에서 명령어를 가져와 해석
ALU와 레지스터, 메모리, I/O 장치와 데이터를 주고받는 제어 신호를 생성
클럭 신호에 맞춰서 명령어를 실행

📌 💡 중요한 이유:

  • CPU가 무엇을 해야 하는지 결정하는 핵심 회로
  • 메모리에서 데이터를 읽어오는지, ALU에 연산을 시킬 것인지, 결과를 저장할 것인지 판단

3. 추가적으로 중요한 개념

3.1 클럭 신호(Clock Signal)

➡️ 컴퓨터의 모든 동작이 동기적으로 진행되도록 하는 시간 신호.
✔ 1Hz(헤르츠) = 1초에 1번 실행
CPU 속도는 GHz 단위 (예: 3.5GHz = 초당 35억 번 실행)

📌 💡 중요한 이유:

  • 클럭이 빨라질수록 연산 속도가 증가
  • 하지만 발열 증가, 전력 소비 증가 문제 발생 → 최근 CPU는 클럭 효율 최적화 연구 진행 중

3.2 파이프라이닝(Pipelining)

➡️ CPU의 성능을 향상시키기 위해 명령어 실행 단계를 여러 개로 나누어 동시 실행
✔ 명령어를 Fetch → Decode → Execute → Write 순서로 실행
✔ 여러 개의 명령어를 동시에 처리하여 CPU 성능을 극대화

📌 💡 중요한 이유:

  • CPU 성능을 높이는 핵심 기술
  • 하나의 명령어가 실행되는 동안, 다음 명령어를 미리 준비하여 처리 속도를 높임

최종 정리

전처리 → 컴파일 → 어셈블 → 링킹 → 실행 과정 필수 개념
CPU는 ALU(연산), 제어장치(명령 해석), 레지스터(고속 저장)로 구성
ALU는 연산 후 플래그 레지스터를 통해 결과를 저장하고, CPU는 이를 활용
제어장치는 CPU 내부, 외부의 모든 동작을 조정하는 역할
파이프라이닝, 클럭 최적화 등 CPU 성능 향상을 위한 기술이 중요해지고 있음

더보기

전처리 과정 (preprocessing)

 

- 본격적으로 컴파일하기 전에 처리할 작업들

- 외부에 선언된 다양한 소스 코드, 라이브러리 포함 (e.g. #include)

- 프로그래밍의 편의를 위해 작성된 매크로 변환 (#define)

- 컴파일할 영역 명시 (#if, #ifdef)

 

컴파일 과정 (compiling)

 

- 전처리가 완료 되어도 여전히 소스 코드

- 전처리 완료된 소스 코드를 저급 언어(어셈블리 언어)로 변환

 

어셈블 과정 (assembling) -> 컴퓨터가 이해할 수 있는 0과 1로 이루어진 기계어로 변환 

 

- 어셈블리어를 기계어로 변환

- 목적 코드(object file)를 포함하는 목적 파일이 됨

 

목적 파일 vs 실행 파일

 

- 목적 파일과 실행 파일은 둘 다 기계어로 이루어진 파일

- 하지만 목적 파일과 실행 파일은 다르다

- 목적 파일은 링킹(linking)을 거친 이후에야 실행 파일이 된다. 

 

 

Main.c를 실행파일로 바꿔도 실행할 수 없을 것이다. Helper.c와 연결을 시켜줘야함

그것을 둘이 연결시켜주는 작업을 링킹이라고 함

 

각기 다른 목적코드를 하나의 실행파일로 묶어주는 작업을 링킹이라고 한다. 

 

이상으로 마치고 CPU에 대해 알아보기로 하겠다.

 

CPU 내부에는 ALU, 제어장치, 레지스터로 구분되어 있다. 

 

ALU는 계산하는 장치

제어장치는 제어 신호를 발생시키고 명령어를 해석하는 장치

 

ALU가 내보내고 받아들이는 정보와 제어장치가 내보내고 받아드리는 정보에 대해서 공부해보자

 

 

ALU는 레지스터로부터 피연산자를 받아들이고, 제어장치로부터 제어 신호를 받아 들인다.

 

CPU내부에 있는 계산기와 같은 회로다 

 

결괏값은 수자, 문자, 주소 등등이 될 수 있음. 

 

이러한 결과를 레지스터에 저장하는 이유는 메모리보다 레지스터가 더 빠르기 때문이다.

 

내보내는 신호중에는 플래그도 있는데 플래그는 연산 결과에 대한 부가 정보임 : 전에 말했던 연산 결과가 음수거나 0이거나 이러한 정보 또는 연산 결과가 레지스터에 비해 너무 클 경우에도 정보 반환 

 

플래그의 종류에는

 

부호 플래그 : 연산환 결과의 부호를 나타낸다, 1일 경우는 음수, 0일 경우 양수

 

제로 플래그 : 연산 결과가 0인지 여부를 나타낸다. 1일 경우는 0, 0일 경우는 0이 아님을 의미

 

캐리 플래그 : 연산 결과 올림수나 빌림수가 발생했는지를 나타낸다. 1일 경우는 올림수가 빌림수가 발생, 0 일 경우는 발생 x

 

오버플로우 플래그 : 오버플로우가 발생했는지 등등이 있다 1일경우 오버플로우 발생 

 

위와 같이 ALU가 내보내는 신호로 CPU가 알 수 있음.

 

제어장치에 대해서 알아보겠다.

 

 

쿨럭 신호란 무엇일까?

 

컴퓨터의 모든 부품을 일사불란하게 움직일 수 있게 하는 시간 단위 

 

 

쿨럭신호에 단위에 맞춰서 명령어 들이 실행이 됨 

 

또한 제어장치가 받아 들이는 것으로써는 명령어 레지스터로 부터 해석할 명령어를 받아들인다. 

 

명령어 레지스터로 부터 해석할 명령어를 받아들여 그 명령어를 해석하고 제어신호를 내보낸다.

 

플래그 레지스터로 부터 플래그를 받아들이기도 하고 CPU 외부에서 발생한 제어신호를 받아 들이면 

 

그 신호가 어떤 신호인지 제어장치가 해석을 한다. 

 

제어 장치가 내보는 신호는 CPU 내부에 전달하는 신호가 있고 CPU 외부에 전달하는 신호가 있는데

 

CPU 내부: 레지스터에 내보내는 제어신호로는 레지스터가 어떤 값을 저장, 이동하도록 하는 어떤 행위에 대한 제어 신호를 내보내고 

 

ALU에는 어떤 연산을 수행해야 할지 지시하는 제어 신호이다.

 

CPU 외부 : 어떤 메모리 주소 값을 읽어라 메모리를 써라 등등의 지시, 입출력 장치를 읽어라, 써라, 테스트 해라 등등의 제어신호