CPU: 명령을 수행하는 두뇌
CPU는 똑똑해 보이지만 실제로 하는 일은 놀랄 만큼 단순하다. 메모리에서 명령 하나를 가져와서, 무슨 뜻인지 해석하고, 실행한다. 그리고 다음 명령으로 넘어간다. 이것을 1초에 수십억 번 반복할 뿐이다. 이 장에서는 명령어 8개짜리 장난감 CPU를 직접 한 박자씩 돌려 보며 그 반복을 눈으로 확인한다.
- CPU의 구성 요소(제어 장치, ALU, 레지스터, 프로그램 카운터)의 역할을 설명한다.
- 명령어도 숫자이며, 숫자 안에 “무엇을 할지”와 “어디에 할지”가 들어 있음을 안다.
- 명령어 사이클(가져오기 → 해석하기 → 실행하기)을 단계별로 따라간다.
- 조건 점프 하나로 “만약 ~라면”과 “반복”을 만드는 원리를 이해한다.
- 장난감 CPU와 실제 CPU(x86, ARM)의 공통점과 차이를 안다.
CPU 안의 네 식구
CPU 내부는 몇 개의 핵심 부품으로 나뉜다. 1장의 주방 비유를 이어 가면, 요리사 한 명의 머리와 손을 나눠 보는 셈이다.
| 부품 | 하는 일 | 주방에서는 |
|---|---|---|
| 제어 장치 Control Unit | 명령을 해석해서 각 부품에 “지금 이걸 해”라고 신호를 보낸다. | 레시피를 읽고 손에게 지시하는 요리사의 머리 |
| ALU | 덧셈, 뺄셈, 비교, AND/OR 같은 실제 계산을 한다(3장의 덧셈기). | 칼질하고 섞는 손놀림 |
| 프로그램 카운터 (PC) | 다음에 실행할 명령이 메모리 몇 번지에 있는지 기억한다. | 레시피의 “지금 몇 번째 줄” 손가락 |
| 명령 레지스터 (IR) | 방금 가져온 명령을 붙잡아 둔다. | 지금 읽고 있는 레시피 한 줄 |
| 범용 레지스터 (A) | 계산에 쓰는 값을 잠시 쥐고 있다. 장난감 CPU는 A 하나, 실제 CPU는 16~32개. | 손에 쥔 재료 |
| 플래그 | “방금 결과가 0이었나?” 같은 짧은 상태를 기록한다. | “냄비가 끓었나?” 확인 표시 |
명령어도 숫자다
1장에서 프로그램도 데이터처럼 메모리에 저장된다고 했다. 메모리에는 숫자만 들어가니 명령어도 숫자여야 한다. CPU 설계자는 “이 숫자는 이 명령”이라는 약속표를 만드는데, 이것을 명령어 집합(ISA, Instruction Set Architecture)이라 한다.
이 장의 장난감 CPU는 명령어가 8비트다. 앞 4비트는 무엇을 할지(연산 코드, opcode), 뒤 4비트는 메모리 몇 번지를 대상으로 할지(주소)를 나타낸다. 예를 들어 ADD 15는 0010 1111이다. “0010 = 더하기”, “1111 = 15번지”.
| 명령 | 코드 | 뜻 |
|---|---|---|
| LOAD n | 0001 nnnn | 메모리 n번지의 값을 A로 가져온다 |
| ADD n | 0010 nnnn | A ← A + (n번지 값) |
| SUB n | 0011 nnnn | A ← A − (n번지 값) |
| STORE n | 0100 nnnn | A의 값을 메모리 n번지에 저장한다 |
| JUMP n | 0101 nnnn | 다음 명령을 n번지에서 가져온다 (PC ← n) |
| JZ n | 0110 nnnn | A가 0이면 n번지로 점프, 아니면 그냥 다음 명령 |
| OUT | 1110 0000 | A의 값을 화면에 출력한다 |
| HALT | 1111 0000 | 멈춘다 |
메모리에 00100111(39)이 있다면 이것은 “ADD 7”이라는 명령일까, 그냥 숫자 39일까? 메모리는 모른다. PC가 가리켜서 명령으로 가져가면 명령이고, LOAD로 읽으면 데이터다. 2장에서 말한 “모든 것은 해석의 약속”이 여기서도 그대로 적용된다.
명령어 사이클: 가져오기 → 해석 → 실행
CPU는 전원이 켜져 있는 동안 다음 세 단계를 끝없이 반복한다.
- 가져오기(Fetch): PC가 가리키는 메모리 번지에서 명령을 읽어 IR에 넣는다. 그리고 PC를 1 늘려 다음 줄을 가리키게 한다.
- 해석하기(Decode): 제어 장치가 IR의 앞 4비트를 보고 무슨 명령인지, 뒤 4비트로 대상 주소가 어디인지 알아낸다.
- 실행하기(Execute): ALU로 계산하거나, 메모리에 쓰거나, PC를 바꾸는(점프) 등 실제 동작을 한다.
이제 직접 돌려 보자. 한 단계 버튼을 누를 때마다 위 세 단계 중 하나가 진행된다. 무엇이 어디로 움직이는지 반짝이는 칸을 따라가 보자.
장난감 CPU
CPU
메모리 (16칸, 0~15번지)
점프 하나로 판단과 반복을
“카운트다운” 프로그램을 다시 보자. CPU에는 “반복하라”는 명령이 없다. 대신 JUMP로 앞쪽 줄로 되돌아가면 반복이 되고, JZ(0이면 점프)로 반복을 빠져나간다.
우리가 프로그래밍 언어에서 쓰는 if(만약), while(~하는 동안), for(~번 반복)는 모두 결국 이런 조건 점프로 번역된다(13장). 아무리 복잡한 앱도 CPU에게는 “계산하고, 저장하고, 조건에 따라 다른 줄로 점프하기”의 반복일 뿐이다.
놀랍게도 “메모리 읽기/쓰기, 더하기/빼기, 조건 점프” 정도만 있으면 (메모리가 충분하다는 가정하에) 어떤 계산이든 할 수 있다는 것이 증명되어 있다. 이런 성질을 튜링 완전이라 한다. 장난감 CPU도 원리적으로는 슈퍼컴퓨터와 같은 문제를 풀 수 있다. 다만 엄청나게 느리고 메모리가 작을 뿐이다.
실제 CPU는 무엇이 다를까
원리는 장난감 CPU와 같다. 하지만 규모가 다르다.
| 장난감 CPU | 요즘 실제 CPU | |
|---|---|---|
| 한 번에 다루는 비트 | 8 | 64 |
| 범용 레지스터 | 1개 | 16~32개 (+ 벡터 레지스터) |
| 명령어 종류 | 8개 | 수백~수천 개 |
| 메모리 주소 | 16칸 | 2⁴⁸ 칸 이상 (수백 TB) |
| 클럭 | 손가락 | 3~5.5 GHz |
| 한 박자에 처리하는 명령 | 1/3개 | 여러 개 (파이프라인·슈퍼스칼라, 5장) |
| 코어(CPU 두뇌) 수 | 1 | 8~24개 이상 |
실제 명령어 집합으로는 PC와 서버에서 쓰는 x86-64(인텔, AMD)와 스마트폰과 최신 맥에서 쓰는 ARM이 대표적이다. 같은 일도 ISA에 따라 다른 숫자로 적는다. 그래서 윈도우용 프로그램이 그대로 스마트폰에서 돌아가지 않는다. 같은 레시피라도 다른 언어로 써야 하는 것이다.
x86은 한 명령이 복잡한 일(메모리에서 읽어 더하기까지)을 한꺼번에 하는 CISC 전통에서, ARM은 단순한 명령만 두고 대신 빠르게 많이 실행하는 RISC 전통에서 출발했다. 요즘은 x86도 내부에서 복잡한 명령을 단순한 조각으로 쪼개 실행하기 때문에 둘의 차이는 많이 줄었다. 전력 효율이 중요한 스마트폰에서는 ARM이 우세하다.
핵심 정리
- CPU는 제어 장치(해석·지시), ALU(계산), 레지스터(초고속 소형 기억)로 이루어진다.
- PC(프로그램 카운터)는 다음 명령의 주소를 가리킨다. 레시피를 짚는 손가락이다.
- 명령어도 숫자다. 앞부분은 연산 종류(opcode), 뒷부분은 대상(주소·레지스터)을 담는다. 이 약속표가 ISA다.
- CPU는 가져오기 → 해석 → 실행을 끝없이 반복한다.
- 반복과 조건 판단은 모두 점프와 조건 점프로 만든다.
- 실제 CPU는 원리는 같지만 비트 폭, 레지스터, 명령어 수, 속도, 코어 수가 훨씬 크다. x86과 ARM은 서로 다른 ISA다.
확인 퀴즈
프로그램 카운터(PC)가 저장하는 것은?
장난감 CPU에서 0011 1110은 어떤 명령인가?
명령어 사이클의 올바른 순서는?
CPU가 “반복문”을 실행할 수 있게 해 주는 것은?
윈도우 PC용 프로그램이 스마트폰에서 그대로 실행되지 않는 근본 이유 중 하나는?