오늘은 CPU의 구조와 명령어 실행 사이클에 대해서 알아보겠습니다.
1. CPU의 구조
1) 프로그램 수행 동작
CPU는 기억장치에 저장되어 있는 프로그램 코드인 명령어를 실행함으로써 프로그램 수행이라는 기본적인 기능을 수행합니다.
프로그램을 수행할때의 세부적인 동작을 순서대로 나열해보겠습니다.
- 명령어 인출: 기억장치로부터 명령어를 읽어옴
- 명령어 해독: 수행해야 할 동작을 결정하기 위해 명령어를 해독
- 데이터 인출: 명령어 실행을 위해 데이터가 필요한 경우, 데이터를 기억장치나 I/O 장치로부터 데이터를 가져옴
- 데이터 처리: 데이터에 대한 산술적 혹은 논리적 연산 수행
- 데이터 저장: 수행한 결과를 저장
명령어 인출과 해독은 모든 명령어들에 공통된 동작입니다. 나머지 3가지 동작은 명령어에 따라 수행됩니다.
2) CPU의 기본 구조
CPU는 다음 사진과 같이 산술논리연산장치(ALU), 레지스터세트, 제어 유니트로 구성되어 있습니다.
ALU는 각종 산술 연산들과 논리 연산들을 수행하는 회로들로 이루어진 하드웨어 모듈입니다.
산술연산은 덧셈, 뺄셈, 곱셈, 나눗셈을 뜻하고 논리연산은 AND, OR, NOT 연산 등이 있습니다.
산술논리연산장치(ALU): 산술 및 논리 연산들을 수행하는 회로들로 이루어진 하드웨어 모듈
레지스터는 CPU 내부에 위치한 기억장치이며, 액세스 속도가 컴퓨터의 기억장치들 중에서 가장 빠릅니다.
하지만 내부가 복잡하고 비교적 큰 공간을 차지하기 때문에 많은 수의 레지스터를 CPU에 포함시키기는 어렵다는 단점이 있습니다.
레지스터(register): CPU 내부 기억장치로서 액세스 속도가 기억장치들 중에서 가장 빠름
제어 유니트는 프로그램 코드(명령어)를 해석하고, 그것을 실행하기 위한 제어 신호들을 순차적으로 발생하는 하드웨어 모듈입니다.
명령어 실행에 필요한 각종 정보들의 전송 통로와 방향을 지정해주고, CPU 내부 요소들과 시스템 구성 요소들의 동작 시간을 결정해줍니다.
제어신호들의 종류와 발생 시간은 명령어 마다 다르기 때문에 CPU가 제공하는 명령어들의 수가 많아질수록 제어 유니트의 내부 회로는 더욱 복잡해집니다. 이를 해결하기 위한 방법으로 마이크로프로그래밍과 RISC가 있는데 이건 나중에 다뤄보겠습니다.
제어 유니트(control unit): 인출된 명령어를 해독하고, 그 실행을 위한 제어신호들을 순차적으로 발생하는 하드웨어 모듈
CPU 내부버스는 데이터와 제어 신호들의 전송통로 입니다. 이 버스는 ALU, 레지스터들 간의 데이터 이동을 위한 데이터, 주소선들과 제어 유니트로부터 발생되는 제어신호들을 전송하는 선들로 구성되어있습니다. 이러한 내부 버스 선들은 외부의 시스템 버스와는 직접 연결되지 않으며, 반드시 버퍼 레지스터 혹은 인터페이스 회로를 통해 시스템 버스와 접속합니다.
CPU 내부버스: CPU 내부 구성요소들 간의 정보 전송 통로
2. 명령어 실행
1) 명령어 사이클
CPU는 명령어를 인출하여 실행함으로써 작업을 수행합니다. CPU가 한 개의 명령어를 실행하는데 필요한 전체 과정을 명령어 사이클이라고 부릅니다. 그리고 명령어 사이클은 CPU가 기억장치로부터 명령어를 읽어오는 명령어 인출과 인출된 명령어를 실행하는 명령어 실행으로 나눌 수 있습니다. 이는 각각 인출 사이클과 실행 사이클로 부릅니다.
명령어 사이클(instruction cycle): 한 명령어를 실행하는데 필요한 전체 과정, 명령어 인출단계와 명령어 실행 단계로 나눠짐
명령어를 실행하기 위해 필요한 CPU 내부 레지스터들을 살펴보겠습니다.
- 프로그램 카운터(PC)
- 다음에 인출될 명령어의 주소를 가지고 있는 레지스터
- 각 명령어가 인출된 후에는 자동적으로 1씩(혹은 명령어 길이에 해당하는 주소 단위의 수만큼) 증가
- 분기 명령어가 실행되는 경우에는 목적지로 주소 갱신 - 누산기(AC)
- 데이터를 일시적으로 저장하는 레지스터
- 누산기의 비트 수는 CPU가 한 번에 연산 처리할 수 있는 데이터 비트의 수, 즉 단어 길이와 같음 - 명령어 레지스터(IR)
- 가장 최근에 인출된 명령어를 저장 - 기억장치 주소 레지스터(MAR)
- 프로그램 카운터(PC)에 저장된 명령어 주소가 시스템 주소 버스로 출력되기 전에 일시적으로 저장되는 주소 레지스터
- MAR의 출력선들이 주소버스선들과 직접 접속 - 기억장치 버퍼 레지스터(MBR)
- 기억장치에 저장될 데이터 혹은 기억장치로 부터 읽혀진 데이터가 일시적으로 저장
- MBR의 입출력선들은 데이터버스 선들과 직접 접속
그림으로 보면 다음과 같습니다.
2) 인출 사이클
기억장치의 저장된 위치로부터 명령어를 읽어오는 과정을 인출 사이클이라고합니다.
인출 사이클에서 각 단계별로 수행되는 동작을 마이크로 연산으로 표현하면 다음과 같습니다.
인출 사이클(fetch cycle): CPU가 기억장치의 지정된 위치로부터 명령어를 읽어오는 과정
마이크로-연산(micro-operation): CPU 클록의 각 주기 동안 수행되는 기본적인 동작
t0 : MAR <- PC
t1 : MBR <- M[MAR], PC <- PC + 1
t2 : IR <- MBR
여기서 M[]은 메모리를 뜻하며 기억장치와 상호작용하는것을 나타냅니다.
M[MAR] <- MBR은 MBR의 데이터를 MAR이 가르키는 주소의 기억장치에 저장하겠다는 뜻이고,
MBR <- M[MAR] 은 기억장치에서 MAR이 가리키는 주소의 데이터를 MBR로 가져오겠다는 뜻입니다.
해당 과정을 그림을 통해 나타내 보겠습니다.
t0 : 현재 PC 내용을 CPU 내부 버스를 통하여 MAR로 보냅니다. MAR은 시스템 주소버스를 통해 주소를 기억장치로 보냅니다.
t1 : 기억장치의 주소에서 명령어를 가져오고 MBR로 적재합니다. 이 과정에서 PC의 내용에 1을 더하여 다음 명령어의 주소를 가르키게 합니다.
❉ 각 기억장치 주소가 바이트(8비트) 단위로 지정되고 명령어 길이는 16비트라면, 한 명령어는 두개의 주소에 걸쳐서 저장되며, PC에는 2가 더해지게 됩니다.
t2 : MBR에 저장되어 있는 명령어 코드가 명령어 레지스터인 IR로 이동하며 인출 사이클이 종료됩니다.
3) 실행사이클
실행 사이클에서는 CPU가 인출된 명령어 코드를 해독하고 그 결과에 따라 필요한 연산을 수행합니다.
CPU가 수행하는 연산은 크게 네가지로 분류할 수 있습니다.
- 데이터 이동: CPU와 기억장치 간 혹은 I/O장치 간 데이터 이동
- 데이터 처리: 데이터에 대하여 산술 혹은 논리 연산
- 데이터 저장: 연산결과 혹은 입력장치로 부터 받은 데이터 저장
- 데이터 제어: 프로그램의 실행순서를 결정
각 연산을 좀 더 자세하게 알아보겠습니다.
3.1) 데이터 이동
데이터 이동을 알아보기 위해, 데이터 이동 명령어 LOAD addr을 알아보겠습니다.
마이크로 연산으로는 다음과 같습니다.
to : MAR <- IR(addr)
t1 : MBR <- M[MAR]
t2 : AC <- MBR
t0 : 명령어 레지스터 IR에 적재된 명령어의 주소를 MAR을 통해 기억장치로 보냅니다.
t1 : 주소가 지정하는 장소에서 데이터를 가져오고 MBR에 저장합니다.
t2 : 가져온 데이터를 AC로 적재함으로써 명령어가 종료됩니다.
3.2) 데이터 저장
STA addr 명령어를 통해 알아보겠습니다.
마이크로-연산은 다음과 같습니다.
t0 : MAR <- IR(addr)
t1 : MBR <- AC
t2 : M[MAR] <- MBR
t0 : 명령어 레지스터 IR에 적재된 명령어의 주소를 MAR을 통해 기억장치로 보냅니다.
t1 : 데이터를 일시적으로 저장하는 AC에서 MBR로 데이터를 저장합니다.
t2 : MBR의 데이터를 MAR의 주소에 저장합니다.
3.3) 데이터 처리
ADD addr로 알아보도록 하겠습니다.
t0 : MAR <- IR(addr)
t1 : MBR <- M[MAR]
t2 : AC <- AC + MBR
t0 : 명령어 레지스터 IR에 적재된 명령어의 주소를 MAR을 통해 기억장치로 보냅니다.
t1 : 기억장치로부터 데이터를 가져와 MBR에 적재합니다.
t2 : MBR의 데이터와 AC가 가지고 있는 데이터를 ALU에서 더하고, 다시 AC에 저장합니다.
3.4) 프로그램 제어
일반적으로 명령어는 프로그램 카운터에 의해 순서가 자동으로 결정됩니다. 하지만 순차적 실행이 아닌, 전혀 다른 위치에 있는 명령어를 실행해야 하는 경우도 있습니다. 이럴때 실행 순서를 바꾸도록 해주는 명령어를 분기 명령어라고 합니다.
예시로는 JUMP addr가 있습니다.
단 한주기만에 완료됩니다.
t0 : PC <- IR(addr)
t0 : IR의 주소를 PC로 적재시키면서 다음 명령어의 순서가 변경됩니다.
4) 인터럽트 사이클
대부분의 컴퓨터들은 프로그램 처리 중에 CPU로 하여금 순차적인 명령어 실행을 중단하고 다른 프로그램을 처리할 수 있도록 하는 메커니즘을 제공합니다. 이를 인터럽트라고 합니다. CPU는 인터럽트 요구가 들어오게 되면, 원래의 프로그램 수행을 중단하고 인터럽트를 처리하기 위한 프로그램을 먼저 수행합니다. 여기서 수행하는 프로그램을 인터럽트 서비스 루틴이라고 합니다. 인터럽트 서비스 루틴이 종료되면
원래의 프로그램으로 복귀하여 그 수행을 계속합니다.
인터럽트(interrupt): CPU로 하여금 현재 진행중인 프로그램 처리를 중단하고 다른 프로그램을 처리하도록 요구하는 메커니즘
인터럽트 서비스 루틴(ISR) : 인터럽트 요구를 처리해주기 위해 수행하는 프로그램 루팅
인터럽트 요구를 확인하기 위해, CPU는 각 명령어의 실행사이클을 종료하고 다음 명령어를 위한 인출사이클을 시작하기 전에, 인터럽트 요구가 들어와서 대기중인지 검사해야 합니다. 만약 들어왔다면 다음과 같은 동작을 시작합니다.
- 다음에 실행할 명령어의 주소를 가리키는 현재의 PC 내용을 스택에 저장(끝나면 복귀하기 위해)
- 인터럽트 서비스 루틴 호출을 위해, 그 루틴의 시작 주소를 PC에 적재.
✻ 루틴의 시작 주소는 인터럽트를 요구한 장치로부터 전송되거나 미리 정해진 값으로 결정
이처럼 인터럽트 요구 신호를 검사하고, 위와 같은 동작을 수행하는 과정을 인터럽트 사이클 이라고 합니다.
또한 인터럽트 사이클을 받을 수 있는 상태를 인터럽트 가능 상태, 받을 수 없는 상태를 인터럽트 불가능 상태라고 말합니다.
인터럽트 사이클(interrupt cycle): 인터럽트 요구가 들어왔는지 검사하고, 그 처리에 필요한 동작들을 수행하는 과정
인터럽트 사이클 동안 수행되는 동작을 마이크로-연산으로 표현하면 다음과 같습니다.
t0 : MBR <- PC
t1 : MAR <- SP, PC <- ISR의 시작 주소
t2 : M[MAR] <- MBR, SP <- SP - 1
SP는 CPU는 CPU 내부에 있는 특수 목적용 레지스터들 중의 하나인 스택포인터를 의미합니다. 스택 포인터는 항상 스택의 최상위 주소를 가리킵니다. 일반적으로 스택으로는 주기억장치의 끝 부분이 사용되기에 SP의 초깃값은 주기억장치의 마지막 주소로 세트됩니다.
t0 : PC의 내용이 MBR로 보내집니다.
t1 : SP의 내용이 MAR을 통하여 주소버스로 나가게 되며, PC에는 인터럽트 서비스 루틴의 시작 주소가 적재됩니다.
t2 : 이때 MAR은 SP의 주소를 저장하고 있습니다. MBR에 저장되어 있던 원래의 PC 내용을 스택에 저장하며, 동시에 SP의 내용을 1 감소시켜 TOS의 주소를 수정합니다.
현재 PC의 값을 MBR에 복사하고, SP가 가리키는 메모리 위치에 이 PC 값을 저장하고 인터럽트가 끝났을때 다시 꺼내와 쓰려고 하는동작입니다.
인터럽트 서비스 루틴의 명령어들이 실행되고 있는중간에 다른 외부 장치가 인터럽트 요구를 발생할 수도 있습니다.
이를 다중 인터럽트라고 합니다. 다중 인터럽트를 처리하는 방법은 두가지가 있습니다.
다중 인터럽트(multiple interrupt): 인터럽트 서비스 루틴을 수행하고 있는 동안 다른 장치로부터 인터럽트 요구가 들어오는 경우
첫번째 방법은 먼저 들어온것을 처리하고 다음것을 실행하는 방법입니다.
인터럽트 불가능 상태일때는 CPU가 인터럽트 요구 신호를 검사하지 않도록 하고, 첫번째 인터럽트가 종료된 후에 인터럽트 가능 상태로 바뀌며 진행합니다.
두번쨰 방법은 인터럽트 요구들 간에 우선순위를 정하는것 입니다.
우선순위가 높은 인터럽트 요구가 들어오면, 현재의 인터럽트 서비스 루틴의 수행을 중단하고 새로운 인터럽트를 처리하도록 합니다. 이경우에 PC의 내용을 저장하는 절차도 위와 동일합니다.
5) 간접 사이클
ADD 명령어와 같이 데이터에 대한 연산을 수행하는 경우에, 연산에서 사용될 데이터의 주소가 기억장치의 어떤 위치에 저장되어 있고, 명령어에 포함되어 있는 주소는 그 위치를 가리키는 경우가 있습니다. 명령어가 직접 주소를 사용하지 않고 간접 주소를 사용하면 발생하는 사이클인데, 쉽게 설명하면 체육복 3반에 있대서 갔는데 1반에 있는, 일을 두번해야 하는 상황인겁니다. 이런 상황에서 실행 사이클이 시작되기전에, 그 데이터의 실제 주소를 기억장치로부터 읽어오는 과정이 먼저 수행되어야 하고 이를 간접사이클이라고 합니다.
간접사이클(indirect cycle) : 실행 사이클에서 사용될 데이터의 실제 주소를 기억장치로부터 읽어오는 과정
간접사이클은 인출사이클과 실행사이클 사이에 위치하며, 명령어 내의 특정 비트가 1로 세트된 경우에만 수행됩니다.
마이크로-연산으로 표시하면 다음과 같습니다.
t0 : MAR <- IR(addr)
t1 : MBR <- M[MAR]
t2 : IR(addr) <- MBR
데이터 이동연산과 비슷하지만 마지막에 AC가 아닌 IR(addr)로 저장하는것에서 차이를 보이고 있습니다.
난이도가 갑자기 확 어려워진 느낌입니다.
이해하고 글을 작성하다보니까 단원을 잘 나눴다고 생각했는데도 시간이 많이 걸렸네요
그래도 다 쓰고나니까 뿌듯한건 좋습니다
'CS > 컴퓨터 구조' 카테고리의 다른 글
[컴퓨터 구조] 명령어 파이프라이닝 (0) | 2025.04.02 |
---|---|
[컴퓨터 구조] 컴퓨터의 발전 과정 (2) | 2025.03.26 |
[컴퓨터 구조] 컴퓨터의 기본 구조, 정보의 표현과 저장, 시스템의 구성 (1) | 2025.03.25 |