에듀테크 프로젝트 대시보드
CPU 구성요소 & 명령어 사이클
컴퓨터 구조를 배우는 가장 첫걸음 — CPU 안에는 무엇이 있고, 프로그램 한 줄은 어떤 과정을 거쳐 실제로 "실행"되는가.
CPU(중앙처리장치) 내부는 역할이 뚜렷이 다른 부품 몇 개로 나뉜다. 아래 다이어그램의 점선 상자가 CPU 하나다.
| 구성요소 | 역할 |
|---|---|
| 제어장치 Control Unit |
메모리에서 가져온 명령어를 해석하고, "지금 무엇을 해야 하는가"를 다른 부품들에게 신호로 지시하는 지휘자. 실제 계산은 하지 않는다. |
| ALU 산술논리연산장치 |
덧셈·뺄셈 같은 산술 연산과 AND·OR·비교 같은 논리 연산을 실제로 수행하는 계산기 부품. |
| 레지스터 Register |
CPU 내부에 있는 아주 작지만 초고속인 임시 저장소. 프로그램 카운터(PC)·명령어 레지스터(IR)처럼 사이클 진행용 특수 레지스터와, 계산에 쓰는 범용 레지스터(R1, R2…)가 있다. |
| 버스 Bus |
부품들 사이, 그리고 CPU와 메모리 사이에 주소·데이터·제어 신호를 실어 나르는 통로. 구조는 버스 구조 페이지에서 자세히. |
CPU는 이 네 부품을 이용해서 메모리에 저장된 명령어를 한 개씩 처리한다. 그 처리 과정은 항상 같은 세 단계를 거친다.
Fetch·Decode·Execute 각 단계는 아무 때나 일어나지 않는다. CPU 안의 클럭(Clock)이 규칙적인 "똑딱" 신호를 보내고, 그 박자에 맞춰 레지스터 값이 갱신되고 다음 단계로 넘어간다. 클럭이 빠를수록(클럭 속도, GHz) 이론상 사이클이 더 자주 도는 셈이지만, 사이클 하나에 여러 클럭이 필요하거나 코어 개수·병렬화 효율에 따라 실제 체감 성능은 달라진다. 이 계산은 암달의 법칙 페이지에서 다룬다.
결국 "프로그램이 실행된다"는 것은 이 Fetch → Decode → Execute 사이클이 메모리 끝에 다다를 때까지, 또는 프로그램이 끝날 때까지 수백만·수십억 번 반복되는 것뿐이다. 이 단순한 반복 위에 우리가 아는 모든 소프트웨어가 돌아간다.
그런데 한 사이클이 끝나야 다음 사이클의 Fetch가 시작되는 이 순차 방식은 한 순간에 하드웨어의 일부만 쓰고 나머지는 놀게 만든다.
파이프라이닝은 이 사이클들을 시간차를 두고 겹쳐 실행해서
놀고 있는 부품이 없도록 만드는 기법이다. 한편 LOAD R1, 5 같은 명령어 자체를 어떤 형태로,
얼마나 단순하게 또는 복잡하게 설계할지는 명령어 집합 구조(RISC vs CISC)에서 다루는 주제다.
지금 이 페이지에서 본 사이클이 그 두 이야기의 출발점이다.
위 시뮬레이터와 똑같은 동작을 하는 아주 작은 가상 CPU를 파이썬으로 옮기면 이렇게 된다.
# 레지스터: 프로그램 카운터(pc)와 범용 레지스터 regs = {"pc": 0, "R1": 0, "R2": 0, "R3": 0} memory = [ ("LOAD", "R1", 5), ("LOAD", "R2", 3), ("ADD", "R1", "R2"), ("STORE", "R1", 10), ] data = {} def step(): # 1. Fetch: PC가 가리키는 명령어를 읽고 PC를 +1 ir = memory[regs["pc"]] regs["pc"] += 1 # 2. Decode: 연산자와 피연산자를 분리 op, a, b = ir # 3. Execute: 실제 연산 수행 if op == "LOAD": regs[a] = b elif op == "ADD": regs[a] = regs[a] + regs[b] elif op == "STORE": data[b] = regs[a] while regs["pc"] < len(memory): step() # Fetch-Decode-Execute 무한 반복 = 프로그램 실행