Skip to main content
Summary

이제 부품을 한 장의 지도에 모으자

지금까지 우리는 컴퓨터를 아주 작은 조각으로 나누어 보았다. 전기는 0과 1이 되었고, 스위치는 트랜지스터가 되었고, 트랜지스터는 논리 게이트가 되었다. 논리 게이트는 덧셈 회로를 만들었고, 기억 회로는 값을 붙잡았다. CPU는 명령어를 읽고, 메모리는 값과 명령을 보관했다. 입력 장치와 출력 장치는 바깥세상과 컴퓨터 사이를 번역했다.

이제 마지막으로 할 일은 흩어진 조각을 한 장의 설계도에 모으는 것이다.

우리가 만들 컴퓨터는 실제 노트북처럼 복잡하지 않다. 대신 원리가 보이는 작은 컴퓨터다. 장난감 자동차가 실제 자동차보다 단순하지만 바퀴, 축, 핸들, 동력의 관계를 보여 주듯이, 작은 컴퓨터도 진짜 컴퓨터의 핵심 구조를 보여 준다.

이 장에서는 종이나 시뮬레이터 위에 그릴 수 있는 8비트 컴퓨터를 설계해 보자. 8비트란 한 번에 다루는 데이터가 0과 1 여덟 개라는 뜻이다. 더 단순하게 만들고 싶다면 4비트로 줄여도 된다. 중요한 것은 크기가 아니라 구조다. 작아도 입력을 받고, 명령어를 읽고, 계산하고, 결과를 내보낼 수 있다면 이미 컴퓨터의 뼈대를 갖춘 셈이다.

나만의 작은 컴퓨터 설계하기AI 생성 이미지

작은 컴퓨터에 필요한 네 상자

먼저 종이 한가운데에 큰 상자 네 개를 그려 보자.

첫째, CPU다. CPU는 명령어를 읽고 실행하는 중심 장치다. 안에는 ALU, 제어장치, 레지스터가 들어 있다.

둘째, 메모리다. 메모리는 명령어와 데이터를 저장한다. 이 작은 컴퓨터에서는 16칸짜리 메모리를 사용하자. 주소는 0번부터 15번까지다. 각 칸에는 8비트가 들어간다.

셋째, 입력 장치다. 예를 들어 스위치 8개를 생각하면 된다. 스위치가 위로 올라가 있으면 1, 내려가 있으면 0이라고 약속할 수 있다.

넷째, 출력 장치다. 예를 들어 LED 8개를 생각하자. 각 LED는 결과의 한 비트를 보여 준다. 00000101이라면 오른쪽에서 첫 번째와 세 번째 LED만 켜지는 식이다.

이 네 상자를 연결하는 길도 필요하다. 값을 옮기는 데이터 버스, 주소를 고르는 주소 버스, 읽기와 쓰기를 알려 주는 제어 신호다. 버스는 부품들이 함께 쓰는 길이다. 우체국의 배달길처럼, 값이 어디에서 출발해 어디로 가야 하는지 정해 주어야 한다.

우리의 설계도는 이렇게 시작할 수 있다.

부분크기역할
메모리16칸 × 8비트명령어와 데이터 저장
데이터 버스8비트값 이동
주소 버스4비트16개 위치 선택
A 레지스터8비트ALU가 주로 사용하는 값 저장
PC4비트다음 명령어 주소 저장
IR8비트지금 실행 중인 명령어 저장
OUT 레지스터8비트LED로 보낼 결과 저장

여기서 PC는 프로그램 카운터다. 다음에 읽을 명령어의 주소를 들고 있는 손가락이라고 생각하면 된다. IR은 명령어 레지스터다. 방금 메모리에서 꺼낸 명령어를 잠시 들고 있는 쪽지다.

PC가 4비트인 이유는 주소가 0부터 15까지, 모두 16개이기 때문이다. 4비트로는 0000부터 1111까지 표현할 수 있고, 이것이 바로 0부터 15까지의 주소가 된다.

명령어 집합이라는 약속표

컴퓨터는 부품만 있다고 움직이지 않는다. 어떤 0과 1을 보면 무슨 일을 해야 하는지 약속해야 한다. 이 약속표가 명령어 집합이다.

우리의 명령어는 8비트로 만들자. 앞의 4비트는 무엇을 할지 나타내는 opcode, 뒤의 4비트는 주소나 작은 값을 나타내는 operand로 사용한다.

예를 들어 0001 1110이라는 명령어가 있다고 하자. 앞의 0001이 LDA라면, 뒤의 1110은 주소 14번을 뜻한다. 그러면 이 명령어의 뜻은 '14번 위치의 값을 A 레지스터로 가져와라'가 된다.

작은 컴퓨터에 필요한 명령어는 많지 않다.

opcode이름뜻
0000NOP아무것도 하지 않고 다음으로 넘어간다
0001LDA 주소주소의 값을 A 레지스터에 넣는다
0010ADD 주소주소의 값을 A에 더한다
0011STA 주소A의 값을 주소에 저장한다
0100JMP 주소PC를 그 주소로 바꾼다
0101OUTA의 값을 출력 장치로 보낸다
1111HALT실행을 멈춘다

여기서 OUT이나 HALT처럼 따로 주소가 필요 없는 명령도 있다. 그래도 명령어 한 칸은 항상 8비트로 맞추기로 했으므로, 남는 뒤쪽 4비트는 그냥 무시해도 된다. 예를 들어 OUT을 0101 0000, HALT를 1111 0000처럼 적을 수 있다. 뒤의 0000은 모양을 맞추기 위한 빈칸에 가깝다.

이 정도만 있어도 작은 프로그램을 만들 수 있다. 값을 가져오고, 더하고, 저장하고, 출력하고, 멈출 수 있기 때문이다. 조건 판단까지 넣고 싶다면 JZ 같은 명령을 추가할 수 있다. JZ는 '결과가 0이면 점프하라'는 뜻이다. 하지만 처음 설계에서는 위의 명령어만으로도 충분하다.

메모리 지도를 그리자

메모리는 그냥 칸들의 모음이지만, 사람이 보기 쉽게 용도를 정해 두면 설계가 편해진다. 이것을 메모리 지도라고 부를 수 있다. 놀이공원의 안내 지도처럼, 몇 번 칸에 무엇이 있는지 정해 두는 것이다.

예를 들어 이렇게 정하자.

주소용도
0~7프로그램 명령어
8~12계산에 쓸 데이터
13두 번째 입력값
14첫 번째 입력값
15결과 저장 위치

주소 14와 13은 실제 메모리 칸일 수도 있고, 스위치 입력 장치와 연결된 특별한 주소일 수도 있다. 이 책에서는 원리를 보기 위해 13번과 14번을 입력 장치가 값을 내보내는 주소처럼 사용해 보자. 이렇게 특정 주소를 읽었을 때 메모리가 아니라 장치 값이 들어오게 만드는 방식을 메모리 맵 입출력이라고 한다.

어려운 말처럼 보이지만 뜻은 간단하다. 장치에도 메모리처럼 주소를 붙여서 CPU가 같은 방식으로 읽고 쓰게 하는 방법이다.

그러면 CPU 입장에서는 입력 장치가 특별하지 않다. 그냥 14번 주소를 읽었더니 스위치 값이 들어오는 것이다. 15번 주소도 실제 RAM 칸으로 둘 수도 있고, LED 출력 장치와 연결된 주소로 정할 수도 있다. 이번 설계에서는 결과를 15번 칸에 저장한 뒤, OUT 명령으로 OUT 레지스터에 보내 LED를 켜는 방식으로 해 보자.

덧셈 프로그램을 올려 보자

이제 프로그램을 메모리에 넣어 보자. 목표는 간단하다.

첫 번째 입력값을 읽는다. 두 번째 입력값을 더한다. 결과를 저장한다. 그리고 LED에 보여 준다.

프로그램은 이렇게 쓸 수 있다.

주소명령어기계어 예뜻
0LDA 140001 1110첫 번째 입력값을 A에 넣기
1ADD 130010 1101두 번째 입력값을 A에 더하기
2STA 150011 1111결과를 15번 칸에 저장하기
3OUT0101 0000A의 값을 LED로 보내기
4HALT1111 0000멈추기

기계어 예를 보면 앞의 4비트가 명령의 종류이고, 뒤의 4비트가 주소라는 것을 확인할 수 있다. 주소가 필요 없는 OUT과 HALT는 뒤쪽 4비트를 0000으로 채웠다.

이제 이 프로그램이 실제로 어떻게 움직이는지 따라가 보자.

전원이 켜지고 리셋되면 PC는 0이 된다. PC가 0이라는 말은 '0번 주소의 명령어부터 읽어라'라는 뜻이다.

첫 번째 박자에서 CPU는 주소 버스에 0을 내보낸다. 메모리는 0번 칸의 명령어 LDA 14를 데이터 버스에 올린다. CPU는 그 명령어를 IR에 저장한다. 그리고 PC는 다음 명령어를 가리키도록 1이 된다.

제어장치는 IR을 보고 생각한다. 앞부분 opcode가 LDA다. 그러면 해야 할 일은 분명하다. 주소 14번의 값을 읽어 A 레지스터에 넣어야 한다. 주소 버스에는 14가 놓이고, 입력 장치의 스위치 값이 데이터 버스를 타고 CPU 안으로 들어온다. A 레지스터는 그 값을 붙잡는다.

두 번째 명령어는 ADD 13이다. CPU는 1번 주소에서 이 명령어를 가져와 IR에 넣는다. 이번에는 주소 13번의 값을 읽는다. 그 값은 ALU로 들어간다. ALU의 다른 입력에는 A 레지스터의 값이 들어 있다. ALU는 두 값을 더한다. 덧셈 결과는 다시 A 레지스터에 저장된다.

여기서 작은 주의점이 하나 있다. 이 컴퓨터는 8비트 컴퓨터이므로 A 레지스터에는 0부터 255까지의 값만 담을 수 있다. 만약 200과 100을 더하면 결과는 300이지만, 8비트 안에는 300을 그대로 담을 수 없다. 실제 설계에서는 넘친 자리, 즉 carry를 따로 표시하거나 넘친 값을 버리기로 약속해야 한다. 처음 실습에서는 입력값을 작게 해서 결과가 255를 넘지 않게 하면 이해하기 쉽다.

세 번째 명령어는 STA 15다. 이제 A 안에는 덧셈 결과가 들어 있다. CPU는 주소 버스에 15를 올리고, 데이터 버스에는 A의 값을 올린다. 쓰기 신호가 켜지면 15번 칸에 결과가 저장된다.

네 번째 명령어는 OUT이다. 제어장치는 A의 값을 OUT 레지스터로 보내라는 신호를 낸다. OUT 레지스터에 들어간 8비트는 LED 8개로 이어진다. 0인 비트의 LED는 꺼지고, 1인 비트의 LED는 켜진다. 사람이 결과를 눈으로 볼 수 있게 된 것이다.

마지막 명령어는 HALT다. CPU는 더 이상 PC를 앞으로 보내지 않고 멈춘다.

이 짧은 순간에 앞에서 배운 거의 모든 것이 등장했다. 입력 장치가 0과 1을 만들었다. 버스가 값을 옮겼다. 메모리가 명령어를 내주었다. PC가 순서를 기억했다. IR이 현재 명령어를 붙잡았다. 제어장치가 신호를 보냈다. ALU가 덧셈을 했다. 레지스터가 결과를 잠시 저장했다. 출력 장치가 숫자를 빛으로 바꾸었다.

이것이 컴퓨터다.

설계할 때 꼭 정해야 하는 질문들

나만의 컴퓨터를 설계하려면 멋진 부품 이름보다 먼저 질문을 정해야 한다.

첫째, 한 번에 몇 비트를 다룰 것인가? 4비트는 단순해서 이해하기 쉽다. 하지만 표현할 수 있는 수가 작다. 8비트는 조금 더 복잡하지만 문자나 간단한 숫자를 다루기 좋다.

둘째, 메모리는 몇 칸으로 할 것인가? 주소 버스가 4비트라면 16칸을 고를 수 있다. 주소 버스가 8비트라면 256칸을 고를 수 있다. 주소 비트가 하나 늘어날 때마다 고를 수 있는 칸 수는 두 배가 된다.

셋째, 레지스터는 몇 개 둘 것인가? A 레지스터 하나만 있어도 아주 작은 컴퓨터는 만들 수 있다. 하지만 B 레지스터나 임시 레지스터를 추가하면 명령어가 더 편해진다.

넷째, 어떤 명령어를 넣을 것인가? 처음에는 LDA, ADD, STA, OUT, JMP, HALT 정도면 충분하다. 나중에 SUB, AND, OR, JZ를 추가하면 계산과 판단이 더 풍부해진다.

다섯째, 입출력은 어떻게 연결할 것인가? 스위치와 LED를 특별한 주소에 붙이면 CPU가 메모리를 읽고 쓰듯 장치를 다룰 수 있다. 또는 이번 예시처럼 OUT 전용 명령과 OUT 레지스터를 두어 출력만 따로 처리할 수도 있다. 어느 쪽이든 중요한 것은 CPU와 장치가 서로 알아들을 수 있는 약속을 정하는 일이다.

여섯째, 넘치는 값은 어떻게 할 것인가? 덧셈 결과가 레지스터 크기를 넘어갈 때 carry를 따로 기억할지, 그냥 낮은 8비트만 남길지 정해야 한다. 작아 보이는 약속이지만, 실제 컴퓨터에서는 이런 약속들이 명령어와 프로그램의 동작을 결정한다.

이 질문에 답하는 과정이 바로 컴퓨터 설계다. 컴퓨터는 마법의 상자가 아니라, 수많은 작은 약속이 정확히 맞물려 움직이는 약속의 기계다.

다음 실습 단계 고르기

이 책의 목표는 집에서 반도체 칩을 직접 만들게 하는 것이 아니다. 실제 칩 제조는 고온, 화학 물질, 초정밀 장비가 필요한 전문 공정이다. 대신 안전한 방식으로 원리를 실험할 수 있다.

가장 쉬운 방법은 종이 설계도다. 상자를 그리고, 버스를 그리고, 명령어 표를 만든다. PC가 어디를 가리키는지, 데이터가 어느 길로 이동하는지 색연필로 따라가 보자. 생각보다 많은 오류를 종이 위에서 찾을 수 있다.

다음은 논리 회로 시뮬레이터다. 화면 위에서 AND, OR, NOT, 플립플롭, 레지스터, 메모리를 연결해 볼 수 있다. 전선이 잘못 연결되어도 실제 부품이 타지 않는다. LED 표시를 보며 신호가 어떻게 바뀌는지 확인할 수 있다.

그다음은 브레드보드 실습이다. 브레드보드는 납땜 없이 부품을 꽂아 회로를 시험하는 판이다. 74HC 계열 같은 논리 IC, LED, 저항, 스위치를 이용하면 작은 게이트와 레지스터를 직접 구성해 볼 수 있다. 이때는 반드시 낮은 전압의 안전한 전원만 사용하고, 저항 없이 LED를 직접 연결하지 않도록 주의해야 한다.

더 깊이 가고 싶다면 FPGA도 있다. FPGA는 안쪽 회로 연결을 다시 설정할 수 있는 칩이다. 실제 칩을 새로 만드는 것은 아니지만, 논리 회로를 설계해서 하드웨어처럼 동작하게 만들 수 있다. 작은 CPU를 FPGA 안에 넣어 실행해 보는 일도 가능하다.

어느 길을 고르든 순서는 같다. 먼저 작은 것을 만든다. 한 비트가 움직이는지 본다. 그다음 4비트, 8비트로 넓힌다. 명령어 하나를 실행해 본다. 그다음 프로그램 하나를 돌린다.

아, 이래서 컴퓨터구나

컴퓨터를 만든다는 말은 꼭 금속을 깎고 칩을 굽는다는 뜻만은 아니다. 더 깊은 뜻은 '정보가 흐르는 규칙을 설계한다'는 것이다.

0과 1은 재료다. 논리 게이트는 작은 판단이다. 가산기는 계산이다. 플립플롭과 메모리는 기억이다. 버스는 길이다. CPU는 명령어를 따라 움직이는 일꾼이다. 소프트웨어는 그 일꾼에게 주는 순서표다. 입력과 출력은 세상과 컴퓨터 사이의 번역이다.

이 조각들이 따로 있을 때는 전선, 스위치, 숫자표처럼 보인다. 하지만 정해진 박자에 맞춰 연결되면 이야기가 생긴다. 입력이 들어오고, 명령어가 읽히고, 값이 이동하고, 계산이 일어나고, 결과가 저장되고, 빛이나 소리로 나온다.

그 순간 우리는 깨닫게 된다.

컴퓨터는 한 번에 똑똑해진 기계가 아니다. 아주 단순한 약속들이 층층이 쌓여, 복잡한 일을 해내는 기계다. 그리고 그 약속을 이해하면, 컴퓨터는 더 이상 까만 상자가 아니다. 우리가 그릴 수 있고, 설명할 수 있고, 조금씩 만들어 볼 수 있는 생각의 기계가 된다.

책 목록

처음부터 이해하는 컴퓨터 만들기

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기