CPU 내부: Instruction Execution Cycle에 대한 완전 가이드와 RAM에서 데이터가 검색되는 방식
Source: Dev.to
CPU 실행 사이클이란?
CPU(중앙 처리 장치)는 명령 사이클 또는 Fetch–Decode–Execute(FDE) 사이클이라고 불리는 반복 루프를 사용해 명령을 처리합니다. ADD, MOV, LOAD, 함수 호출, 분기 등 모든 명령은 이 사이클을 거칩니다.
세 가지 주요 단계는 다음과 같습니다:
- Fetch – 메모리(RAM 또는 캐시)에서 명령을 가져옵니다.
- Decode – 명령이 의미하는 바를 해석합니다.
- Execute – 연산을 수행합니다(ALU 연산, 메모리 접근, 분기 등).
이 사이클은 초당 수십억 번 반복됩니다.
CPU 아키텍처 한눈에 보기
레지스터
CPU 내부에 있는 작고 매우 빠른 저장 장치:
- PC (Program Counter) – 다음 명령의 주소를 보관합니다.
- IR (Instruction Register) – 현재 디코딩/실행 중인 명령을 보관합니다.
- MAR (Memory Address Register) – 메모리 주소를 보관합니다.
- MDR (Memory Data Register) – 메모리와 주고받는 데이터를 보관합니다.
- General Registers – AX, BX, RAX, RBX 등, 아키텍처에 따라 다릅니다.
ALU (Arithmetic Logic Unit)
수학 연산(덧셈, 뺄셈, 곱셈)과 논리 연산(AND, OR, XOR)을 수행합니다.
제어 장치
전체 실행 사이클을 제어하며, fetch, decode, execute를 조율합니다.
캐시
명령 및 데이터 접근 속도를 높이는 매우 빠른 메모리 계층(L1, L2, L3)입니다.
RAM(주 메모리)
프로그램이 실행되는 동안 명령과 데이터가 저장되는 곳입니다.
명령 사이클 단계별 가이드
단계 1: Fetch
- PC → MAR – 프로그램 카운터 주소가 메모리 주소 레지스터에 복사됩니다.
- CPU가 메모리 읽기 요청 – 주소가 주소 버스에 놓입니다.
- 메모리가 명령을 반환 → MDR – 메모리 데이터가 메모리 데이터 레지스터에 들어갑니다.
- MDR → IR – 가져온 명령이 명령 레지스터에 저장됩니다.
- PC 증가 –
PC = PC + size_of_instruction(보통 +1, +4 등).
이 시점에서 CPU는 명령을 로드했으며 디코딩 준비가 됩니다.
단계 2: Decode
제어 장치가 명령을 해석합니다:
- Opcode – 연산 종류(덧셈, 이동, 점프).
- Operands – 레지스터 번호, 메모리 주소, 상수 등.
- Addressing modes – 직접, 간접, 즉시, 인덱스 등.
아직 데이터 처리는 일어나지 않고, 해석만 수행됩니다.
단계 3: Execute
CPU가 동작을 수행하며, 형태는 여러 가지가 될 수 있습니다:
- 산술/논리 연산 – ALU가 연산을 수행하고 결과를 레지스터에 저장합니다.
- 메모리 읽기(LOAD)
- 유효 주소를 계산합니다.
- 주소를 MAR에 넣습니다.
- 제어 장치가 메모리에 읽기 요청을 보냅니다.
- 데이터가 데이터 버스를 통해 MDR로 이동합니다.
- MDR → 대상 레지스터.
- 메모리 쓰기(STORE) – 데이터를 MDR에 넣고, 주소를 MAR에 넣은 뒤 메모리에 쓰기 신호를 보냅니다.
- 분기 – 조건이 참이면 PC를 새로운 주소로 업데이트하고, 그렇지 않으면 기존대로 진행합니다.
- I/O – 제어 신호가 I/O 컨트롤러를 활성화합니다.
실행이 끝나면 다음 명령으로 사이클이 다시 시작됩니다.
CPU가 실제로 RAM에서 데이터를 가져오는 과정
단계 1: 캐시 확인
CPU는 먼저 캐시 계층(L1 → L2 → L3)을 확인합니다.
- Cache hit – 데이터가 즉시(나노초 수준) 읽혀집니다.
- Cache miss – CPU가 RAM에서 데이터를 가져와야 하며, 이때는 더 느립니다.
단계 2: 주소를 RAM에 전송
주소가 주소 버스를 통해 MAR에 놓입니다.
단계 3: RAM 응답
RAM이 요청된 데이터를 데이터 버스에 올립니다.
단계 4: 데이터가 MDR에 도착
CPU가 데이터를 메모리 데이터 레지스터에 잡아냅니다.
단계 5: 대상 레지스터로 전송
예시 어셈블리:
LOAD R1, [0x5000]
최종 단계는 MDR → R1입니다.
전체 흐름 예시
ADD R1, [0x2000]
- Fetch – PC가 가리키는 주소에서 명령을 가져옵니다.
- Decode – opcode
ADD와 피연산자(레지스터R1+ 메모리 주소0x2000)를 식별합니다. - Execute
- 유효 주소
0x2000을 계산합니다. MAR = 0x2000.- RAM → MDR (메모리 읽기).
- ALU가
R1+MDR을 더합니다. - 결과를
R1에 저장합니다.
- 유효 주소
이 모든 과정은 몇 개의 CPU 사이클 안에 이루어집니다.
파이프라인 및 병렬성(현대 CPU)
현대 CPU는 다음과 같은 기법으로 처리량을 높입니다:
- Instruction pipelining – 여러 명령에 대해 fetch, decode, execute 단계를 겹쳐서 수행합니다.
- Superscalar execution – 한 클럭 사이클에 여러 명령을 발행합니다.
- Out‑of‑order execution – 파이프라인 정체를 피하기 위해 명령 순서를 재배열합니다.
- Branch prediction – 분기의 결과를 미리 추측해 파이프라인을 채워 둡니다.
이러한 최적화 덕분에 초당 수십억 번의 연산이 가능해집니다.
요약
Fetch: PC → MAR → Memory → MDR → IR → PC++
Decode: 제어 장치가 opcode와 피연산자를 해석합니다.
Execute:
- ALU 연산
- 메모리 Load/Store
- 분기
- I/O 연산
Memory Access: 항상 캐시 → (필요 시) RAM → MDR → 레지스터 순으로 흐릅니다.
이 사이클을 이해하면 코드가 하드웨어 수준에서 어떻게 실행되는지 깊이 파악할 수 있어, 시스템 설계, 어셈블리 프로그래밍, 컴파일러 구현, 성능 최적화 등에 필수적인 지식이 됩니다.