Pv_log

4. CPU 본문

Develop Study/Computer Architecture

4. CPU

Priv 2023. 3. 19. 21:03


 

 

1. ALU와 제어장치

ALU는 CPU 내부에서 계산을 담당하고, 제어장치는 명령어를 읽고 해석하는 역할을 담당한다.

 

1.1) ALU

ALU는 피연산자와 수행할 연산을 가지고 계산을 수행한다.

ALU는 레지스터를 통해 피연산자를 받아들이고, 제어장치로부터 수행할 연산을 알려주는 제어 신호를 받아들인다.

이렇게 받아들인 피연산자, 제어 신호를 가지고 ALU는 산술 연산, 논리 연산 등을 수행한다.

ALU가 수행한 연산의 결과는 특정 숫자, 문자, 메모리 주소가 될 수도 있다.

이 값들은 일시적으로 레지스터에 저장된다.

이는 CPU가 메모리에 접근하는 속도보다 레지스터에 접근하는 속도가 압도적으로 빠르기 때문이다.

ALU는 연산 결괏값과 함께 플래그를 내보낸다.

플래그는 연산 결과에 대한 추가적인 정보를 내보내야 할 때 사용된다.

가령, 이진수의 음수, 양수를 구분하기 위한 수단이나 레지스터의 용량보다 연산 결괏값이 더 커서 오버플로우가 발생했음을 알려주는 수단 등으로 사용된다.

이 플래그들은 플래그 레지스터에 저장된다.

플레그 레지스터는 다음과 같이 구성되어 있다.

 

1.2) 제어장치

제어장치는 제어 신호를 보내고, 명령어를 해석하는 부품이다.

제어 신호는 컴퓨터 부품을 관리, 작동하기 위한 일종의 전기 신호이다.

제어장치가 받아들이는 정보는 다음과 같이 다양하다.

  • 클럭 신호: 클럭은 컴퓨터의 모든 부품들이 동작하는 데 사용되는 시간 단위이다. 이 주기에 맞춰 데이터가 다른 레지스터로 전달되거나, ALU가 연산을 수행하는 등의 활동이 벌어진다.
  • 해석할 명령어: CPU가 처리할 명령어들은 명령어 레지스터에 저장된다. 제어장치는 이 레지스터에서 명령어를 가져와 해석한 뒤, 제어 신호를 발생시켜 컴퓨터가 수행할 내용을 알려준다.
  • 플래그 값: 플래그 레지스터에 저장되는 플래그를 가져와 이를 참고하여 제어 신호를 발생시킨다.
  • 시스템 버스(제어 버스): 제어 신호는 입출력장치처럼 CPU 외부 장치들도 발생시킬 수 있다. 제어 버스는 제어장치가 제어 신호를 전달할 때 사용하는 통로이다.

제어장치가 메모리에 저장된 값에 접근하기 위해서는 메모리로 제어 신호를 보내고, 입출력장치에 접근하기 위해서는 입출력장치로 제어 신호를 보내는 방식이다.

제어장치가 CPU 내부에 전달하는 제어 신호는 ALU에 전달하는 신호와 레지스터에 전달하는 신호로 나눠진다.

 


 

2. 레지스터

프로그램 속 명령어, 데이터는 실행 전후에 항상 레지스터에 저장되기 때문에 레지스터에 저장된 값을 잘 파악하면 프로그램의 실행 흐름도 파악할 수 있다.

 

2.1) 핵심 레지스터 8가지

핵심 레지스터 8가지는 CPU 내부에 존재하는 다양한 레지스터들 중 가장 중요한 역할을 하는 레지스터들이다.

종류는 다음과 같다.

  • 프로그램 카운터
  • 명령어 레지스터
  • 메모리 주소 레지스터
  • 메모리 버퍼 레지스터
  • 플래그 레지스터
  • 범용 레지스터
  • 스택 포인터
  • 베이스 레지스터

 

- 프로그램 카운터

프로그램 카운터는 PC라고도 부르며, 메모리에 읽어 들일 명령어의 주소를 저장한다.

명령어 포인터, IP라고 부르는 경우도 있다.

 

- 명령어 레지스터

명령어 레지스터는 IR이라고도 부르며, 해석할 명령어를 저장하는 레지스터이다.

명령어 레지스터 속에 있는 명령어는 제어장치가 읽고, 해석된 뒤 제어 신호로 보내진다.

 

- 메모리 주소 레지스터

메모리 주소 레지스터는 MAR이라고도 부르며, 메모리의 주소를 저장하는 레지스터이다.

CPU가 읽으려는 주소 값을 주소 버스로 보낼 때 메모리 주소 레지스터를 거친다.

 

- 메모리 버퍼 레지스터

메모리 버퍼 레지스터는 MBR이라고도 부르며, 메모리와 주고받을 값(데이터, 명령어)을 저장하는 레지스터이다.

메모리에 쓰거나 메모리에서 읽고 싶은 값은 이 메모리 버퍼 레지스터를 거쳐서 전달된다.

 

- 범용 레지스터

범용 레지스터는 일반적인 상황에서 자유롭게 사용할 수 있는 레지스터이다.

데이터, 주소를 모두 저장할 수 있는 레지스터이며, 대다수의 CPU가 범용 레지스터를 장착하고 있다.

 

- 플래그 레지스터

연산 결과, CPU 상태에 대한 부가적인 정보(플레그)를 저장하는 레지스터이다.

 

2.2) 특정 레지스터를 사용한 주소 지정 방식: 스택 주소 지정 방식

스택 주소 지정 방식은 스택, 스택 포인터를 사용하여 주소를 지정한다.

자료구조 때 언급되는 스택과 동일하다.

후입선출 구조를 가지고 있으며, CPU 내에 있는 스택 포인터가 스택의 꼭대기 주소를 저장하고 있는 방식이다.

여기서 스택은 메모리 안에 존재한다.

메모리 안에 스택처럼 사용할 수 있는 영역이 정해져 있는데, 이를 '스택 영역'이라고 부른다.

 

2.3) 특정 레지스터를 사용한 주소 지정 방식: 변위 주소 지정 방식

변위 주소 지정 방식은 명령어 구조 중 오퍼랜드 필드의 값(변위)과 특정 레지스터 값을 더해서 유효 주소를 찾는 방식이다.

변위 주소 지정 방식을 사용하기 위해서는 명령어의 구조가 '연산 코드', '레지스터 필드', '오퍼랜드 필드'로 구성되어야 한다.

어떤 레지스터의 값이랑 더해야 하는지 알아야 하기 때문이다.

변위 주소 지정 방식은 상대 주소 지정 방식과 베이스 레지스터 주소 지정 방식 등으로 다시 나뉜다.

 

- 상대 주소 지정 방식

오퍼랜드, 프로그램 카운터의 값을 더해 유효 주소를 얻는 방식이다.

프로그램 카운터에는 명령어의 주소가 들어있고, 오퍼랜드에는 상대 주소가 들어간다.

이를 공식으로 표현하면 프로그램 카운터의 주소 + 오퍼랜드의 상대 주소 == 메모리의 접근 주소가 된다.

 

- 베이스 레지스터 주소 지정 방식

오퍼랜드, 베이스 레지스터의 값을 더해 유효 주소를 얻는 방식이다.

연산 방식은 상대 주소 지정 방식과 유사하다.

다만 베이스 레지스터는 '기준 주소'를 저장하는 레지스터이다.

즉, 기준 주소에서 오퍼랜드에 저장된 값만큼 떨어진 주소의 값을 읽어내는 방식이다.

어떻게 보면 절대 주소를 사용한다고 볼 수 있다.

 


 

3. 명령어 사이클, 인터럽트

CPU가 명령어 하나를 처리하는 흐름을 명령어 사이클이라고 부른다.

이 명령어 사이클을 중간에 방해하여 흐름을 끊어버리는 것을 인터럽트라고 부른다.

 

3.1) 명령어 사이클

CPU가 명령어를 수행할 때는 일정한 주기가 존재한다.

이 주기를 명령어 사이클이라고 부른다.

명령어 사이클은 인출 사이클, 실행 사이클, 간접 사이클, 인터럽트 사이클로 나눠진다.

  • 인출 사이클: 메모리에 있는 명령어를 레지스터를 거쳐서 CPU가 읽을 수 있도록 가져오는 사이클.
  • 실행 사이클: 제어장치가 명령어 레지스터에 담긴 명령어를 해석하고 제어 신호를 발생시키는 사이클.
  • 간접 사이클: 간접 주소 지정 방식과 같이 메모리에 한 번 더 참조해야 하는 경우가 발생했을 때 진입하는 사이클.
  • 인터럽트 사이클: CPU가 최우선적으로 처리해야 하는 인터럽트가 발생했을 때 진입하는 사이클.

 

3.2) 인터럽트

CPU가 수행 중인 작업을 방해하여 일시 중단 시키는 신호를 인터럽트라고 한다.

즉, CPU가 최우선으로 처리해야 하는 다른 작업이 발생했을 경우 인터럽트가 발생한다.

인터럽트는 동기 인터럽트, 비동기 인터럽트로 나눠진다.

  • 동기 인터럽트(또는 예외): CPU에 의해 발생하는 인터럽트. 프로그램 오류와 같이 예외적인 상황이 있을 때 발생한다.
  • 비동기 인터럽트(또는 하드웨어 인터럽트): 입출력장치에 의해 발생하는 인터럽트.

 

- 동기 인터럽트(또는 예외)

CPU가 하던 일을 중단시키고 예외를 처리했다면, 다시 작업으로 복귀해야 할 것이다.

이때 '예외가 발생한 지점'으로 복귀하는지, '예외가 발생한 다음 지점'으로 복귀하는지에 따라 예외의 종류가 나뉜다.

  • 폴트: 예외가 발생한 지점으로 복귀한다. 보조기억장치에서 필요한 데이터를 메모리로 가져오기 위해 예외가 발생했다면, 이때 CPU는 폴트를 통해서 가져온 명령어부터(예외가 발생한 지점부터) 작업을 이어나간다.
  • 트랩: 예외가 발생한 다음 지점으로 복귀한다. 디버깅이 대표적인 트랩의 예시이다.
  • 중단: 프로그램을 강제로 종료해야 할 정도로 심각한 문제가 있을 때 발생하는 동기 인터럽트이다. 말 그대로 프로그램 자체가 죽는다.

 

- 비동기 인터럽트(또는 하드웨어 인터럽트)

입출력장치는 CPU보다 당연히 속도가 압도적으로 느리다.

그렇기 때문에 입출력장치의 명령을 처리할 때까지 CPU는 필연적으로 놀게 된다.

이때 하드웨어 인터럽트를 사용하면 입출력장치의 명령 처리가 끝났다는 것을 CPU에게 알려줄 수 있다.

즉, 하드웨어 인터럽트가 발생할 때까지 CPU는 무작정 휴무 상태에 빠지는 것이 아니라 다른 작업들을 처리하면서 시간을 아낄 수 있는 것이다.

비동기 인터럽트의 실행 과정은 다음과 같다.

  • 입출력장치가 CPU에 인터럽트 요청 신호를 전달한다.
  • CPU가 인터럽트 여부를 확인하면서 이 요청 신호를 포착한다.
  • CPU는 인터럽트 플래그를 통해 인터럽트가 발생할 수 있는 지를 검사한다.
  • 인터럽트를 발생시키기 위해 진행 중이던 작업물을 백업한다.
  • 인터럽트 벡터를 참조, 인터럽트 서비스 루틴을 실행한다.
  • 인터럽트 서비스 루틴이 끝나고 백업해 둔 작업물을 재개한다.

인터럽트 요청 신호란, CPU에게 인터럽트를 통해 명령어 사이클을 중단시켜도 되는지를 묻는 것이다.

인터럽트 요청 신호가 들어오면 CPU는 플래그 레지스터에 있는 인터럽트 플래그를 검사한다.

이 플래그가 활성화되어 있어야 인터럽트를 받아들일 수 있다.

플래그의 여부와 관계없이 무조건 받아들이는 인터럽트도 물론 존재한다.

이를 막을 수 없는 인터럽트라고 부른다.

인터럽트 서비스 루틴은 인터럽트를 처리하기 위한 기계어 코드 루틴을 말한다.

인터럽트 벡터는 인터럽트가 발생했을 때, 인터럽트를 처리할 수 있는 서비스 루틴들의 주소를 가진 공간이다.

CPU가 다양한 인터럽트 서비스 루틴들을 구분하기 위해 인터럽트 벡터를 사용한다.

CPU가 인터럽트를 처리하게 되면 기존에 실행하던 명령어들은 어떻게 될까?

당연하겠지만 인터럽트를 처리한다고 해서 이 명령어들을 다 날려버리면 안 될 것이다.

인터럽트가 발생하면 기존에 하던 일을 중단하고 스택 영역에 기존에 실행하던 작업물들을 저장한 뒤, 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행, 실행이 끝나면 스택 영역을 참조하여 다시 기존의 작업으로 복귀한다.

정리하면 다음과 같다.

  • 인터럽트 요청 신호: 인터럽트 발생을 알리는 신호.
  • 인터럽트 플래그: 인터럽트 요청을 승인할 것인지를 판단하는 플래그 레지스터.
  • 인터럽트 벡터: 인터럽트 서비스 루틴의 시작 주소를 담는 공간.
  • 인터럽트 서비스 루틴: 인터럽트를 처리하는 기계어 코드 루틴.

 


 

4. 클럭, 멀티 코어, 멀티 스레드

CPU의 속도와 관계가 있는 클럭, 멀티 코어, 멀티 스레드는 컴퓨터를 조립해 봤거나, CPU를 구매해 보았다면 누구나 접해본 용어일 것이다.

 

4.1) 클럭

클럭은 CPU, GPU와 같은 순차 회로에 가해지는 전기적 진동의 속도를 나타내는 단위이다.

클럭 속도는 Hz로 표현하며, '헤르츠'라고 읽는다.

클럭 속도는 '1초에 클럭이 몇 번 반복되는가'를 나타낸다.

컴퓨터 부품들은 '클럭 신호'에 맞춰서 동작한다.

CPU는 '명령어 사이클'이라는 흐름에 맞춰서 동작한다.

즉, 클럭 신호가 빠르게 반복되면 CPU의 명령어 사이클도 빨라지므로 결과적으로 명령어를 처리하는 속도가 올라가는 것이다.

 

4.2) 코어

클럭을 높이는 것만으로는 CPU의 성능을 높이는 데 한계가 있다.

대표적인 문제점이 발열로 인한 쓰로틀링이다.

코어를 늘리는 것도 CPU의 성능을 높이는 방법 중에 하나이다.

코어는 CPU 내부에서 '명령어를 실행/처리하는 부품'들을 의미한다.

ALU, 제어장치, 레지스터 등 CPU를 구성하는 다양한 부속품들을 '코어'라는 단위로 묶고, 그 코어의 수를 늘리는 것이다.

위 사진처럼 코어가 여러 개 존재하는 CPU는 멀티 코어 프로세서라고 부른다.

하지만 코어 수를 무작정 늘린다고 CPU의 연산 속도가 비례하여 올라가는 것은 아니다.

여러 개의 코어에 어떤 일들을 어떤 순서에 맞춰 분담할 것인지에 따라 성능이 달라지기 때문이다.

 

4.3) 스레드

스레드는 '실행 흐름의 단위'이다.

프로그래밍을 해보면 알 수 있겠지만, 작성한 소스 코드들은 항상 '실행 흐름'을 가진다.

그 실행 흐름은 언어에 따라 조금씩 달라지겠지만, 'main 스레드'를 기준으로 하여 시작된다.

흔히 볼 수 있는 main( ) 메서드를 떠올려 보면 된다.

스레드는 하드웨어적 스레드소프트웨어적 스레드로 나눠진다.

위에서 언급한 main 스레드는 소프트웨어적 스레드에 해당한다.

소프트웨어적 스레드는 하나의 프로그램 안에서 독립적으로 실행되는 단위를 의미한다.

하드웨어적 스레드는 CPU 입장에서 정의된 스레드의 개념이다.

하드웨어적 스레드는 하나의 코어 안에서 독립적으로 실행되는 단위를 의미한다.

편의상 이론적으로 CPU를 살펴볼 때는 '1 코어 1 스레드'를 기준으로 한다.

즉, 명령어를 실행하는 코어가 1개, 1번에 1개의 실행 흐름(스레드)만 감당할 수 있다는 것이다.

그렇다면 2 코어 4 스레드 CPU는 어떻게 될까?

일단 코어가 2개이므로, CPU는 동시에 2개 이상의 명령어를 처리할 수 있다.

또한 스레드가 4개이므로, 동시에 최대 4개의 명령어를 처리할 수 있다.

즉, 하나의 코어가 2개의 명령어 실행 흐름을 감당할 수 있다는 것이다.

이러한 구조의 CPU를 멀티 스레드 프로세서라고 부른다.

 

4.4) 멀티 스레드 프로세서

멀티 스레드 프로세서를 설계할 때 가장 핵심이 되는 부품이 바로 레지스터이다.

레지스터가 여러 개 존재한다면 CPU는 명령어 처리에 필요한 데이터들을 동시에 여러 개 가질 수 있다.

이는 ALU, 제어장치가 처리해야 하는 명령어들이 여러 개 존재할 수 있다는 것이므로 보다 효율적이다.

그렇다면 메모리의 시선으로 멀티 스레드 프로세서를 바라보게 된다면 어떻게 될까?

하드웨어 스레드의 구조가 어찌 되었든 간에, 메모리 입장에서는 동시에 여러 개의 명령어를 처리하는 CPU의 모습이 보일 것이다.

만약 2 코어 4 스레드 CPU라고 가정한다면, 작업 흐름(스레드)이 4개 존재하는 것이므로, 코어가 4개 존재하는 CPU와 별반 다를 바 없다.

이 때문에 하드웨어 스레드는 논리 프로세서라고도 부른다.

 


 

5. 명령어 병렬 처리

CPU의 하드웨어 성능을 향상하는 것도 중요하지만, 이 CPU를 어떻게 써먹을 것인지도 매우 중요하다.

최적화가 부족한 게임들이나 프로그램들을 언급할 때 "1번 코어만 죽어라고 갈구고 있어 성능이 안 나온다."라는 말을 종종 들었을 것이다.

 

5.1) 명령어 파이프라인

명령어가 처리되는 과정을 클럭 단위로 나눠보면 다음과 같다.

  • 명령어 인출
  • 명령어 해석
  • 명령어 실행
  • 결과 저장

CPU는 위의 4단계를 특별한 경우가 아닌 이상, 동시에 실행할 수 있다.

즉, A 명령어를 인출하는 동안, B 명령어를 해석할 수 있다는 것이다.

이처럼 명령어들을 겹쳐서 동시에 실행하는 기법을 명령어 파이프라이닝이라고 부른다.

명령어 파이프라이닝은 상당히 효율적으로 명령어를 처리할 수 있도록 만들어주지만, 그에 따른 위험도 따른다.

데이터 위험, 제어 위험, 구조적 위험이 그것이다.

 

- 데이터 위험

명령어 간 데이터 의존성에 의해 발생하는 데이터 위험은 명령어들끼리 서로의 작업을 요구하여 제대로 된 명령어 처리가 불가능해지는 상황을 말한다.

  • 명령어 1: R1 레지스터에 R2 레지스터의 값과 R3 레지스터의 값을 더한 결과를 저장한다.
  • 명령어 2: R4 레지스터에 R1 레지스터의 값과 R5 레지스터의 값을 더한 결과를 저장한다.

위와 같이 명령어 2개가 존재한다고 가정하면, 명령어 2는 명령어 1과 동시 실행이 불가능하다.

이 경우에는 명령어 파이프라이닝을 사용할 수 없게 된다.

 

- 제어 위험

제어 위험은 분기 등으로 인해 프로그램 카운터가 갑작스럽게 변화할 경우 발생한다.

프로그램 카운터는 '현재 실행 중인 명령어의 다음 주소'로 갱신되는 것이 기본적이다.

그런데 만약 프로그램 실행 흐름이 갑자기 바뀌게 된다면 프로그램 카운터의 값도 바뀌어야 한다.

이렇게 되면 프로그램 카운터의 값을 기반으로 하여 명령어 파이프라인에 미리 가져와 처리 중이던 명령어들은 헛수고가 되어버린다.

이 제어 위험에 대응할 수 있도록 프로그램이 어디로 분기할 것인지를 미리 예측해 해당 주소를 인출하는 기술을 분기 예측이라고 부른다.

 

- 구조적 위험 (또는 자원 위험)

명령어 파이프라이닝이 이루어지는 과정에서 서로 다른 명령어들이 동시에 ALU, 제어장치 등을 사용하고자 하면 구조적 위험이 발생한다.

즉, 한정된 자원을 과도하게 요구하는 상황이라고 보면 된다.

 

5.2) 슈퍼 스칼라

명령어 파이프라이닝은 1개의 명령어 파이프라인으로도 구현할 수 있지만, 여러 개의 파이프라인을 사용하면 훨씬 더 효과적이다.

이처럼 여러 개의 명령어 파이프라인을 활용하는 명령어 파이프라이닝 구조를 슈퍼 스칼라라고 부른다.

슈퍼 스칼라 구조로 이루어진 CPU를 슈퍼 스칼라 프로세서라고 부른다.

또한 멀티 스레드 프로세서는 슈퍼 스칼라를 구현할 수 있다.

동시에 여러 명령어를 인출, 해석, 실행할 수 있는 구조이기 때문이다.

다만 슈퍼 스칼라 프로세서는 여러 개의 파이프라인을 사용하므로 데이터 위험, 자원 위험, 제어 위험에서 더더욱 자유롭지 못하다.

 

5.3) 비순차적 명령어 처리

비순차적 명령어 처리는 OoOE라는 약어로 자주 언급된다.

명령어들도 일종의 우선순위가 존재한다.

명령어 파이프라이닝, 슈퍼 스칼라 기법들은 명령어들을 순차적으로 처리하기 때문에 명령어의 우선순위가 아무리 높더라도 자신의 순번을 기다려야 하는 단점이 존재한다.

  • 명령어 1: 메모리 100번지에 값 '1' 저장
  • 명령어 2: 메모리 101번지에 값 '2' 저장
  • 명령어 3: 메모리 100번지의 값과 메모리 101번지의 값을 더한 결과를 메모리 102번지에 저장
  • 명령어 4: 메모리 103번지에 값 '3' 저장

위와 같은 명령어들이 존재한다고 가정해 보자.

순차적 명령어 처리 기법을 기준으로 본다면, 명령어 1, 명령어 2가 실행되어야 명령어 3을 실행할 수 있고, 명령어 4는 명령어 3 다음에 실행될 것이다.

그런데 명령어 4는 명령어 3 뒤에 실행될 필요가 없는 명령어이다.

단순하게 값을 메모리에 저장하는 것일 뿐이지, 명령어 3의 연산 과정에는 관여하지 않기 때문이다.

하지만 순차적으로 명령어를 처리하면 여기서 오는 시간 낭비를 해결할 수 없다.

비순차적 명령어 처리 기법을 사용하면 다음과 같이 문제를 해결할 수 있다.

  • 명령어 1: 메모리 100번지에 값 '1' 저장
  • 명령어 2: 메모리 101번지에 값 '2' 저장
  • 명령어 4: 메모리 103번지에 값 '3' 저장
  • 명령어 3: 메모리 100번지의 값과 메모리 101번지의 값을 더한 결과를 메모리 102번지에 저장

이처럼 비순차적 명령어 처리 기법을 활용하려면 데이터 의존성이 어떻게 발생하는지를 판단할 수 있어야 한다.

 


 

6. CISC, RISC

뭐든지 최적화는 중요하다.

명령어 파이프라이닝, 슈퍼 스칼라 기법 등을 활용하기 위해서는 명령어가 파이프라이닝에 최적화되어 있어야 한다.

CPU는 ISA라는 언어를 사용하며, 그 성격에 따라 CISC, RISC로 언어의 종류가 구분된다.

 

6.1) 명령어 집합

CPU가 이해할 수 있는 명령어들의 모음을 명령어 집합 또는 명령어 집합 구조라고 부르며, ISA라는 약어로도 통한다.

CPU의 종류에 따라 이 ISA도 조금씩 달라진다.

CPU의 종류에 따라 어셈블리어의 종류도 달라진다거나, x86 기반의 프로그램은 ARM 환경에서는 동작하지 않는다는 말들을 들어보았을 것이다.

이와 같은 말이다.

ISA가 같은 CPU끼리는 서로 호환이 되지만, 그렇지 않으면 별도의 변환 작업이 필요하다.

ISA가 다르다는 것은 제어장치가 명령어를 해석하는 방법, 레지스터의 종류와 개수, 메모리 관리 방법 등이 다르다는 것과 동일한 의미이다.

 

6.2) CISC

CISC는 '복잡한 명령어 세트를 사용하는 컴퓨터'를 의미한다.

x86이 가장 대표적인 CISC 기반의 ISA이다.

CISC는 명령어의 형태, 크기가 다양한 가변 길이 명령어를 사용한다.

메모리에 접근하는 주소 지정 방식 또한 매우 다양하다.

CISC는 적은 수의 명령어로도 프로그램 실행이 가능하여 메모리 부담이 적었다.

하지만 이름에서도 알 수 있듯, 활용되는 명령어가 상당히 복잡하기 때문에 명령어의 크기, 실행 시간이 일정하지가 않다.

또한 여러 클럭 주기를 필요로 하여 명령어 파이프라인을 구현하는 데 큰 걸림돌이 된다.

 

6.3) RISC

CISC의 한계를 개선하기 위해 다음과 같은 원칙에 맞춰 개발된 언어가 RISC이다.

  • 명령어 파이프라인을 효율적으로 활용할 수 있도록 명령어의 길이, 수행 시간은 짧고 규격화되어 있어야 한다.
  • 활용도가 높은 명령어들을 작고 빠르게 만들어야 한다.

즉, RISC는 CISC와 다르게 고정 길이 명령어를 활용한다.

ARM이 대표적인 RISC 기반의 ISA이다.

메모리 접근 단순화 및 최소화, 레지스터 적극 활용 등의 방식을 사용하여 CISC보다는 보다 많은 명령을 요구하지만 명령어들이 1 클럭 내외로 설정되어 있어 명령어 파이프라이닝에 더 적합하다.

 


 


수고하셨습니다!


'Develop Study > Computer Architecture' 카테고리의 다른 글

6. 보조기억장치  (0) 2023.03.28
5. RAM  (0) 2023.03.26
3. 명령어  (0) 2023.03.12
2. 데이터  (0) 2023.03.12
1. 컴퓨터 구조  (0) 2023.03.11
0 Comments