명령어 집합은 CPU가 이해하는 명령어의 목록입니다. 메모리에 명령어가 준비되었으니, 이제 CPU가 이를 어떻게 실행하는지 살펴봅시다.
CPU가 명령어를 처리하려면 무엇을 해야 할까요? 메모리에서 명령어를 가져오고 (Fetch), 그 의미를 해석하고(Decode), 해석한 대로 실행(Execute)합니다. 이 세 단계를 끊임없이 반복하는 것이 CPU가 하는 일의 전부입니다.
메모리에는 명령어가 여러 개 저장되어 있습니다. CPU는 어디서부터 가져와야 할까요?
책을 읽을 때 손가락으로 줄을 짚듯이, CPU에도 지금 어디를 읽고 있는지 가리키는 장치가 있습니다. Program Counter(PC)라는 레지스터입니다. CPU는 PC가 가리키는 주소에서 명령어를 읽어온 뒤, PC를 다음 주소로 한 칸 옮깁니다.
보통 PC는 한 칸씩 순서대로 증가하지만, 명령어 집합의 JUMP와 JZ 명령어는 PC를 직접 바꿔 반복문이나 조건 분기를 가능하게 합니다.
| 주소 | 이진수 | 어셈블리 |
|---|---|---|
| 0 | 01100001 | LDI R0, 1 |
| 1 | 01100110 | LDI R1, 2 |
| 2 | 00010001 | ADD R0, R1 |
| 3 | 10010101 | STORE 5 |
| 4 | 11000010 | JUMP 2 |
| 5 | 00000000 | 데이터 |
가져온 명령어는 01100011 같은 이진수일 뿐입니다. CPU 안의
제어 장치가 이 이진수를 해석해, 레지스터와 메모리, ALU 같은
각 부품에 무엇을 할지 알리는 신호를 보냅니다.
제어 장치가 신호를 보내면 실제 연산이 수행됩니다. 예를 들어 ADD R0, R1이라면,
제어 장치가 ALU에 덧셈 신호를 보내고 MUX가 R0과 R1의 값을 선택합니다. ALU가 두
값을 더한 결과가 R0에 저장되고 Zero Flag가 갱신됩니다. 연산 명령어(ADD, SUB
등)는 ALU에서, 데이터 이동 명령어(LOAD, STORE
등)는 레지스터와 메모리 사이에서 실행됩니다. 실행이 끝나면 PC가 다음 주소로
증가하고, 다시 Fetch로 돌아갑니다.
이 부품들을 하나로 조립한 폰 노이만 시뮬레이터에서 Fetch-Decode-Execute 사이클을 한 단계씩 실행해봅시다.
가져오고, 해석하고, 실행하고, 다시 가져옵니다. CPU는 전원이 켜져 있는 동안 이 Fetch-Decode-Execute 사이클을 끝없이 반복합니다. 웹을 검색하든 게임을 하든, CPU 입장에서는 PC가 가리키는 명령어를 하나씩 처리하는 같은 사이클이 반복될 뿐입니다.
다음 글에서는 이 사이클의 한가운데에서 이진수 명령어를 해석해 각 부품에 신호를 보내는 제어 장치를 자세히 들여다봅시다.