909 Devlog

[컴퓨터 구조] - CPU의 구조와 기능 본문

Computer Science/컴퓨터 구조

[컴퓨터 구조] - CPU의 구조와 기능

구공구 2023. 10. 7. 07:20
728x90

👋 본 글은 "컴퓨터 구조론" 책을 읽고 요약, 정리한 글입니다.


책 구매 링크에서 책을 확인하실 수 있습니다.

 

2장에서는 컴퓨터의 핵심 요소인 CPU의 구조와 동작 원리에 대하여 설명한다.

CPU는 기억장치에 저장되어 있는 프로그램 코드인 명령어들을 실행함으로써 프로그램 수행이라는 컴퓨터의 기본적인 기능을 수행하는데, 그를 위하여 CPU가 수행해야 하는 세부적인 동작들을 순서대로 나열하면 다음과 같다.

 

  1. 명령어 인출(Instruction fetch, IF) : 기억장치로부터 명령어를 읽어온다
  2. 명령어 해독(Instruction decode, ID) : 수행해야 할 동작을 결정하기 위하여 명령어를 해독한다
    • ➡️ 위 2가지는 모든 명령어들에 대하여 공통적으로 수행
  3. 데이터 인출(Data fetch) : 명령어 실행을 위하여 데이터가 필요한 경우, 기억장치 혹은 I / O 장치로부터 그 데이터를 읽어온다
  4. 데이터 처리(Data process) : 데이터에 대한 산술적 혹은 논리적 연산을 수행한다
  5. 데이터 저장(Data store) : 수행항 결과를 저장한다
    • ➡️ 명령어에 따라 필요한 경우에만 수행

 

이번 챕터에서는 위 동작들을 수행하기 위한 CPU의 내부 구성요소들을 살펴본 다음에, 명령어 실행 과정의 분석을 통해 CPU의 동작 원리를 설명하고, 명령어의 실행 속도를 높이기 위한 주요 기술인 파이프라이닝의 원리와 명령어 형식에 대해 분석한다

 

🎯 1. CPU의 기본 구조


CPU의 내부 구성 요소는 다음 그림과 같다

  • ALU(Arithmetic and Logical Unit : 산술논리연산장치)
    • 각종 산술 연산들과 논리 연산들을 수행하는 회로들로 이루어진 하드웨어 모듈
    • 산술 연산 : +, -, x, % 등
    • 논리 연산 : AND, OR, NOT 등
  • 레지스터
    • CPU 내부에 위치한 액세스 속도가 가장 빠른 기억장치
    • 내부 회로가 복잡해 비교적 큰 공간을 차지하기 때문에 CPU 내부에 포함할 수 있는 레지스터들의 수가 제한됨
    • 특수 목적용 레지스터들과 적은 수의 일반 목적용 레지스터들만이 포함됨
  • 제어 유닛
    • 명령어를 인출한 후에 제어 유닛이 작동됨(명령어 해독)
    • 프로그램 코드를 해석하고, 그것을 실행하기 위한 제어 신호들을 순차적으로 발생하는 하드웨어 모듈
    • 명령어 실행에 필요한 정보들의 전송 통로(주소, 데이터, 제어 버스)와 방향을 지정
    • CPU 내부 요소들과 시스템 구성요소들의 동작 시간 결정
    • CPU가 제공하는 명령어 수가 많아지면 내부 회로가 복잡해짐
      • 위 문제를 해결하기 위해 제어 유닛의 동작을 소프트웨어로 처리하는 방법인 마이크로프로그래밍이 등장
      • 그러나 마이크로프로그래밍은 명령어 실행 시간이 길어짐
    • 따라서 최근에는 RISC(Reduced Instruction Set Computer) 설계 개념 사용 (명령어 수 줄이고 단순화)
  • CPU 내부 버스
    • ALU와 레지스터들 간의 데이터 이동을 위한 데이터 선들과 제어 유닛으로부터 발생되는 제어 신호 선들로 구성된 내부 버스
    • 외부의 시스템 버스들과는 직접 연결되지 않으며, 반드시 버퍼 레지스터들 혹은 시스템 버스 인터페이스 회로를 통하여 시스템 버스와 접촉

🎯 2. 명령어 실행


CPU가 한 개의 명령어를 실행하는 데 필요한 전체 과정을 명령어 사이클이라 부른다

명령어 사이클에는

  • CPU가 기억장치로부터 명령어를 읽어오는 명령어 인출(인출 사이클) 단계와
  • 인출된 명령어를 실행하는 명령어 실행(실행 사이클) 단계로 이루어진다

명령어 사이클은 CPU가 프로그램을 실행한 순간부터 전원을 끄거나 회복 불가능한 오류가 발생되어 중단될 때까지 반복하여 수행됨

 

명령어를 실행하기 위한 기본적인 CPU 내부 레지스터들을 살펴보면 다음과 같다

  • 프로그램 카운터 (Program Counter : PC)
    • 다음에 인출할(읽어 올) 명령어의 주소를 가지고 있는 레지스터
    • 각 명령어가 인출된 후에는 자동적으로 일정 크기(한 명령어 길이)만큼 증가
    • 분기(branch) 명령어가 실행되는 경우에는 목적지 주소로 갱신
  • 누산기 (Accumulator : AC)
    • 데이터를 일시적으로 저장하는 레지스터
    • 레지스터의 길이는 CPU가 한 번에 처리할 수 있는 데이터 비트 수(단어 길이)와 동일
  • 명령어 레지스터 (Instruction Register : IR)
    • 가장 최근에 인출된 명령어 코드가 저장되어 있는 레지스터
  • 기억장치 주소 레지스터 (Memory Address Register : MAR)
    • PC에 저장된 명령어 또는 데이터가 저장된 주소가 시스템 주소 버스로 출력되기 전에 일시적으로 저장되는 레지스터
  • 기억장치 버퍼 레지스터 (Memory Buffer Register : MBR)
    • 기억장치로부터 읽힌 명령어(IF) 또는 데이터(DF) 혹은 기억장치에 쓰일 데이터를 일시 저장하는 레지스터

 

📌 2 - 1. 인출 사이클

CPU는 각 명령어 사이클의 시작 단계에서 PC가 가리키는 기억장치의 위치로부터 명령어를 인출해 온다. 그 후 CPU는 PC의 내용을 1 증가시킴으로써 명령어들을 기억장치에 저장되어 있는 순서대로 읽어올 수 있도록 해준다.

이를 마이크로 연산(CPU 클록의 각 주기동안 수행되는 기본적인 동작)으로 표현하면 다음과 같다.

t (CPU 클록의 주기) 동작 비고
t0 MAR <- PC PC의 내용을 내부 버스를 통해 MAR로 보냄
t1 MBR <- M[MAR], PC <- PC + 1 Memory의 MAR번지의 값이 MBR로 적재, PC = PC + 1(ins_size)
t2 IR <- MBR MBR에 저장된 명령어가 레지스터인 IR로 이동

명령어 인출에는 세 개의 CPU 클록 주기만큼의 시간이 걸리며, 위 사이클을 그림으로 보면 다음과 같다.

 

📌 2 - 2. 실행 사이클

CPU는 실행 사이클 동안에 명령어 코드를 해독하고, 그 결과에 따라 필요한 연산을 수행

CPU가 수행하는 연산들의 종류

  • 데이터 이동 : CPU와 기억장치 간 혹은 I / O 장치 간 데이터 이동
  • 데이터 처리 : 데이터에 대하여 산술 혹은 논리 연산 수행
  • 데이터 저장 : 연산 결과 데이터 혹은 입력장치로부터 읽어 들인 데이터를 기억장치에 저장
  • 프로그램 제어 : 프로그램의 실행 순서 결정

실행 사이클에서 수행되는 마이크로 연산들은 명령어연산코드(op code) (연산코드 + 오퍼랜드)에 따라 결정됨

연산코드 오퍼랜드 (addr)
  • 연산코드(operation code : op code)
    • CPU가 수행할 연산을 지정
  • 오퍼랜드(operand)
    • 명령어 실행에 필요한 데이터가 저장된 주소 (addr)

위에서 언급한 CPU가 수행하는 4가지 연산들을 예시를 통해 자세하게 알아보자

 

예 1) LOAD addr 명령어 (데이터 이동) : 기억장치에 저장되어 있는 데이터를 CPU 내부 레지스터인 AC로 이동하는 명령어

t(주기) 동작 비고
t0 MAR <- IR(addr) IR에 적재된 명령어의 오퍼랜드를 MAR을 통해 기억장치로 전달
t1 MBR <- M[MAR] addr이 지정하는 기억 장소로부터 데이터를 인출, MBR에 저장
t2 AC <- MBR MBR에 저장된 값을 AC에 적재

 

예 2) ADD addr 명령어 (데이터 처리) : 기억장치에 저장된 데이터를 AC 레지스터의 내용과 더하고 그 결과를 다시 AC에 저장하는 명령어

t(주기) 동작 비고
t0 MAR <- IR(addr) IR에 적재된 명령어의 오퍼랜드를 MAR을 통해 기억장치로 전달
t1 MBR <- M[MAR] addr이 지정하는 기억 장소로부터 데이터를 인출, MBR에 저장
t2 AC <- AC + MBR MBR의 값과 AC 레지스터의 값을 더하고 그 결과를 AC에 저장

위 마이크로 연산들의 정보 흐름은 다음과 같다

 

예 3) STA addr 명령어 : AC 레지스터의 내용을 기억장치에 저장하는 명령어

t(주기) 동작 비고
t0 MAR <- IR(addr) 데이터를 저장할 기억 장소의 주소를 MAR로 보냄
t1 MBR <- AC 저장할 데이터를 MBR로 이동
t2 M[MAR] <- MBR MBR의 값을 기억장치의 MAR주소에 저장

 

예 4) JUMP addr 명령어 : 오퍼랜드(addr)가 가리키는 위치의 명령어로 실행 순서를 변경하는 분기 명령어

t(주기) 동작 비고
t0 PC <- IR(addr) IR에 적재된 명령어의 오퍼랜드를 PC로 적재

다음 명령어 인출 사이클에서 그 주소의 명령어가 인출되므로, 분기가 발생

위와 같이 다른 위치의 명령어로 실행 순서를 바꾸도록 해주는 명령어를 분기 명령어라고 한다.

 

위 명령어들을 어셈블리 프로그램 이용하여 자세하게 나타내보면 다음과 같다.

 

편의상 실제로는 2진수로 저장되어 있는 기계 코드를 10진수로 표현했고

연산코드에 임의의 정수를 가정하였다

LOAD : 1, STORE : 2, ADD : 5, JUMP : 8

주소 명령어 기계 코드
100 LOAD 250 1 250
101 ADD 251 5 251
102 STA 251 2 251
103 JUMP 170 8 170

즉, 기계 코드의 첫 숫자는 연산 코드를 의미하고, 나머지 세 숫자들은 오퍼랜드로서 기억장치의 주소를 나타낸다.

 

위 프로그램들을 단계별로 분석하면 다음과 같다.

 

(LOAD 250)

단계 1 : 100번지의 첫 번째 명령어 코드가 인출되어 IR에 저장

단계 2 : 250번지의 데이터를 AC로 이동 (PC = PC + 1 = 101)

왼쪽은 모든 명령어에 실행되는 인출 사이클이고, 오른쪽은 LOAD 명령어에 맞는 실행 사이클이다

 

(ADD 251)

단계 3 : 두 번째 명령어가 101번지로부터 인출되어 IR에 저장

단계 4 : AC의 내용과 251번지 내용을 더하고, 결과를 AC에 저장 (PC의 내용은 102로 증가 (PC = PC + 1))

 

(STA 251)

단계 5 : 세 번째 명령어가 102 번지로부터 인출되어 IR에 저장

단계 6 : AC의 내용이 251 번지에 저장 (PC의 내용은 103으로 증가 (PC = PC + 1))

 

(JUMP 170)

단계 7 : 네 번째 명령어가 103 번지로부터 인출되어 IR에 저장

단계 8 : 분기된 목적지 주소, 즉 IR 하위 부분(170)이 PC로 적재 (다음 명령어 인출 사이클에서는 170번지의 명령어 인출)

📌 2 - 3. 인터럽트 사이클

인터럽트란? : 프로그램 실행 중에 CPU의 현재 처리 순서를 중단시키고, 다른 동작을 수행하도록 요구하는 시스템 동작을 말한다

 

외부로부터 인터럽트 요구가 들어오면 CPU는 원래의 프로그램 수행을 중단하고, 요구된 인터럽트를 위한 서비스 프로그램을 먼저 수행한다. 이런 프로그램을 인터럽트 서비스 루틴이라고 부른다

 

인터럽트 서비스 루틴(Interrupt Service Routine : ISR)

  • 인터럽트를 처리하기 위하여 수행되는 프로그램 루틴

인터럽트가 들어왔을 때 CPU는

  • 어떤 장치가 인터럽트를 요구했는지 확인하고, 해당 ISR을 호출
  • 서비스가 종료된 다음에는 중단되었던 원래 프로그램의 수행 계속

CPU 인터럽트 처리의 세부 동작

  • 현재의 명령어 실행을 끝낸 즉시, 다음에 실행할 명령어의 주소(PC의 내용)를 스택(stack)에 저장 -> 일반적으로 스택은 주기억장치의 특정 부분
  • ISR을 호출하기 위하여 그 루틴(ISR)의 시작 주소를 PC에 적재, 이때 시작 주소는 인터럽트를 요구한 장치로부터 전송되거나, 미리 정해진 값으로 결정

 

위와 같이 인터럽트 요구 신호를 검사하고, 현재의 PC 내용을 스택에 저장한 다음에, PC에 해당 ISR의 시작 주소를 적재하는 과정을 인터럽트 사이클이라고 부른다.

 

아래 그림은 기본적인 명령어 사이클에 인터럽트 사이클을 추가한 결과를 보여준다.

아래 그림에서 유의할 사항으로는 CPU가 인터럽트 사이클을 시작하기 전에, 인터럽트가 가능한 상태로 세트 되어 있는지를 먼저 확인한다는 것이다.

만약 중요한 프로그램이 실행 중이라 CPU가 인터럽트를 받지 못하도록 세트 되어 있다면 인터럽트 불가능 상태라고 부르고

그렇지 않은 경우라는 인터럽트 가능 상태라고 한다

 

 

인터럽트 사이클 동안 수행되는 동작들을 마이크로 연산으로 표현하면 다음과 같다

t(주기) 동작 비고
t0 MBR <- PC PC의 내용이 MBR로 보내짐
t1 MAR <- SP(스택 포인터), PC <- ISR 주소 SP 값이 MAR을 통해 버스로 나감, PC에는 ISR주소 적재
t1 M[MAR] <- MBR, SP <- SP - 1 MBR에 저장된 값을 스택에 저장, SP값 수정(TOS)

SP는 CPU 내부의 특수 목적용 레지스터 중 하나로서, 항상 스택의 최상위(Top Of Stack : TOS) 주소를 가리키는 레지스터이다.

일반적으로 스택은 주기억장치의 끝 부분이 사용되기 때문에, SP의 초기값은 주기억장치 마지막 주소로 세트 된다.

 

위에서 살펴봤던 어셈블리 프로그램

100 LOAD 250
101 ADD 251
102 STA 251
103 JUMP 170

에서 LOAD 250 명령어가 실행되는 동안에 인터럽트가 들어왔고, 현재 SP에는 999가 저장되어 있으며, 인터럽트 서비스 루틴의 시작 주소가 650번지라고 가정했을 때

인터럽트 사이클이 시작되기 전 상태와 인터럽트 사이클이 끝난 후 상태는 아래와 같다

달라진 점으로는 기억장치의 스택 부분인 999번지와 SP 레지스터가 추가되었다는 것이다.

인터럽트 요구 신호가 인식되어서 원래의 PC의 내용은 SP가 지정하는 스택의 최상위(999)에 저장되고 PC의 내용은 인터럽트 서비스 루틴의 시작주소인 650으로 변경되었으며 SP의 내용은 1이 감소되어 998이 된다.

(SP의 동작에 관한 내용은 2.4절에서 설명된다.)

 

이러한 인터럽트 사이클에서 유의해야 할 것이 있다.

LOAD 명령어가 실행된 결과로써 기억장치 250번지의 내용인 0004가 AC에 적재되어 있는데, 만약 인터럽트 서비스 루틴이 수행되는 동안에 AC의 내용이 바뀌게 된다면, 나중에 원래 프로그램의 다음 명령어인 ADD 명령어의 실행 결과에 문제가 생길 수도 있다.

따라서 인터럽트 서비스 루틴의 시작단계에서 레지스터들의 내용을 스택에 저장하였다가, 루틴의 마지막 단계에서 원래 프로그램으로 복귀하기 직전에 그들을 복원시켜 주는 절차가 필요하다.

 

또, 인터럽트 서비스 루틴이 수행되는 동안 다른 외부 장치로부터 인터럽트 요구를 발생할 수도 있는데, 이것을 다중 인터럽트라고 한다. 이를 처리한느 방법으로는 두 가지가 있다.

  1. CPU가 인터럽트 서비스 루틴을 수행하는 도중에는 새로운 인터럽트 요구가 들어오더라도 인터럽트 사이클을 수행하지 않도록 한다.
    • 즉, 이전에 언급했었던 인터럽트 불가능 상태인 것이다.
    • 이렇게 되면 지금 루틴을 처리하는 동안에 발생한 다른 인터럽트 요구는 대기상태로 있다가 CPU가 인터럽트 가능 상태로 바뀌면 동작한다.
  2. 인터럽트 요구들 간에 우선순위를 정하고, 우선순위가 낮은 인터럽트 요구를 처리하고 있는 동안에 우선순위가 더 높은 인터럽트 요구가 들어오면, 현재의 인터럽트 서비스 루틴의 수행을 중단하고 새로운 인터럽트를 처리하도록 하는 것이다.
    • 이 경우, PC의 내용을 저장하고 갱신하는 절차는 위에서 봤던 단일 인터럽트의 경우와 동일하지만 스택에는 원래의 주 프로그램으로 복귀하기 위한 주소와 첫 번째 인터럽트 서비스 루틴으로 복귀하기 위한 주소 또한 저장되어야 한다.

아래 그림은 인터럽트인 ISR X를 처리하는 도중에 우선순위가 더 높은 장치 Y로부터 인터럽트 요구가 들어와서 그 인터럽트 서비스 루틴을 먼저 처리하는 경우이다.

 

 

 

📌 2 - 4. 간접 사이클

명령어들 중에서는 포함하고 있는 주소가 데이터의 주소가 아니라 데이터가 저장된 기억 장소의 주소를 가리키는 명령어가 존재한다. (연산에서 사용될 데이터의 주소가 기억장치의 어떤 위치에 저장되어 있고, 명령어에 포함되어 있는 주소는 그 위치를 가리킴)

 

위와 같은 경우에 실행 사이클이 시작되기 전에, 그 데이터의 실제 주소를 기억장치로부터 읽어오는 과정이 먼저 수행되어야 한다. 이 과정을 간접 사이클이라고 하며, 인출 사이클과 실행 사이클 사이에 위치하게 된다.

 

간접 사이클은 항상 수행되는 것이 아니며, 명령어 내의 특정 비트가 1로 세트 된 경우에만(간접 주소지정 방식) 사용된다.

 

간접 사이클에서는 다음과 같은 마이크로 연산들이 수행된다

t(주기) 동작 비고
t0 MAR <- IR(addr) 명령어에 포함된 addr 주소를 MAR로 옮김
t1 MBR <- M[MAR] 주 기억 장치의 MAR번지에 저장되어 있는 값을 MBR로 옮김
t2 IR(addr) <- MBR MBR에 있는 값이 연산에 사용할 데이터가 있는 주소기 때문에 IR로 옮김

인출된 명령어의 주소 필드 내용을 이용하여 기억장치로부터 데이터의 실제 주소를 인출하여 IR의 주소 필드에 저장하는 과정임

🎯 3. 명령어 파이프라이닝


명령어 파이프라이닝 : CPU의 프로그램 처리 속도를 높이기 위하여 CPU 내부 하드웨어를 여러 단계로 나누어 동시에 처리하는 기술

 

📌 3 - 1. 2-단계 명령어 파이프라인

명령어를 실행하는 하드웨어를 인출 단계실행 단계라는 두 개의 독립적인 파이프라인 모듈로 분리

두 단계들에 동일한 클록을 인가하여 동작 시간을 일치시키면

  • 첫 번째 클록주기 : 인출 단계가 첫 번째 명령어를 인출
  • 두 번째 클록주기 : 인출된 첫 번째 명령어가 실행 단계로 보내져서 실행되며, 그와 동시에 인출 단계는 두 번째 명령어를 인출
  • 세 번째 클록 주기 : 인출된 두 번째 명령어가 실행 단계로 보내져서 실행되며, 그와 동시에 인출 단계는 세 번째 명령어를 인출
  • 네 번째 클록 주기 : 인출된 세 번째 명령어가 실행 단계로 보내져서 실행됨

이와 같이 다음에 실행될 명령어를 미리 인출하는 것은 명령어 선인출 혹은 인출 중복이라 부름

 

2-단계 파이프라인을 이용하면 이론적으로는 명령어 처리 속도가 두 배 향상되지만, 일반적으로는 인출 단계와 실행 단계의 처리 속도가 차이가 나기 때문에 실제로 두 배만큼 빨라질 수 없음 (T 실행단계 > T 인출단계)

따라서 파이프라인의 단계 수를 증가시켜 각 단계의 처리 시간을 같게 함 (파이프라인 단계의 수를 늘리면 전체적으로 속도 향상이 더 높아짐)

 

📌 3 - 2. 4-단계 명령어 파이프라인

긴 파이프라인 단계를 세분하여, 각 단계들의 처리 시간이 거의 동일하도록 설계

  • 명령어 인출(IF) 단계 : 다음 명령어를 기억장치로부터 인출
  • 명령어 해독(ID) 단계 : 해독기를 이용하여 명령어를 해석
  • 오퍼랜드 인출(OF) 단계 : 기억장치로부터 오퍼랜드를 인출
  • 실행(EX) 단계 : 지정된 연산을 수행

이와 같이 4-단계 명령어 파이프라인으로 구성하면 각 단계에서 걸리는 시간들이 거의 같아질 수 있다.

 

파이프라인 단계의 수를 k, 실행할 명령어들의 수를 N이라 가정하고, 각 파이프라인 단계가 한 클럭 주기씩 걸린다고 가정한다면

 

파이프라인에 의한 전체 명령어 실행 시간 : Tk = k + (N - 1)

즉, 첫 번째 명령어를 실행하는데 k 주기가 걸리고, 나머지 (N - 1)개의 명령어들은 각각 한 주기씩만 소요

 

파이프라인 되지 않은 경우 N개의 명령어들의 실행 시간 : T1 = k * N

 

따라서 파이프라인에 의한 속도 향상 식은 Sp = T1 / Tk = k * N / k + (N - 1)

k * N / k + (N - 1)
속도 향상 계산 예시
4-단계 파이프라인 일 때 명령어에 따른 속도 향상 비교

위에서 살펴보았던 것처럼 파이프라이닐을 통해 속도 향상을 얻을 수 있지만 문제점이 존재한다.

  • 모든 명령어들이 파이프라인 단계들을 모두 거치지는 않는다.
    • 어떤 명령어에서는 오퍼랜드를 인출할 필요가 없지만, 파이프라인의 하드웨어를 단순화시키기 위해서는 모든 명령어가 네 단계들을 모두 통과하도록 해야 한다. (결과적으로 시간이 불필요하게 소모됨)
  • 파이프라인의 클록은 처리 시간이 가장 오래 걸리는 단계를 기준으로 결정된다.
    • 보완방법 : 각 단계를 더욱 작게 분할하는 슈퍼파이프라이닝으로 해결 (명령어 파이프라인의 단계를 더욱 잘게 분할하여 처리 속도를 높여주는 기술)
  • IF 단계와 OF 단계가 동시에 기억장치를 액세스하는 경우에, 기억장치 충돌이 일어나면 지연이 발생한다.
    • 보완방법 : CPU 내부 캐시를 명령어 캐시와 데이터 캐시로 분리
  • 조건 분기(conditional branch) 명령어가 실행되면, 미리 인출하여 처리하던 명령어들이 무효화된다.

분기 발생에 의한 성능 저하의 최소화 방법

  • 분기 예측(branch prediction)
    • 분기가 일어날 것인지를 예측하고, 그에 따라 명령어를 인출하는 확률적 방법
    • 분기 역사 표(branch history table)를 이용하여 최근의 분기 결과를 참조
  • 분기 목적지 선인출(prefetch branch target)
    • 조건 분기가 인식되면, 분기 명령어의 다음 명령어뿐만 아니라 분기의 목적지 명령어도 함께 인출하는 방법(조건 확인 후, 유효 명령어 결과를 선택)
  • 루프 버퍼 사용(loop buffer)
    • 파이프라인의 명령어 인출 단계에 포함되어있는 작은 고속 기억장치인 루프 버피에 가장 최근 인출된 n개의 명령어들을 순서대로 저장해 두는 방법
  • 지연 분기(delayed branch)
    • 분기 명령어의 위치를 재배치함으로써 파이프라인의 성능을 개선하는 방법

 

조건 분기 명령어에서 사용하는 조건들은 CPU 내부의 상태 레지스터에 저장되어있다.

각 조건의 상태를 나타내는 비트를 플래그라고 부르는데, CPU는 실행 사이클 동안에 조건 분기 명령어가 지정하는 플래그의 값을 검사하여 분기 여부를 결정하게 된다. 각각의 조건들은 다음과 같다

  • 부호(S) 플래그 : 직전에 수행된 산술연산 결괏값의 부호 비트를 저장
  • 제로(Z) 플래그 : 연산 결괏값이 0이면, 1
  • 올림수(C) 플래그 : 덧셈이나 뺄셈에서 올림수(carry)나 빌림수(borrow)가 발생한 경우로 1세트
  • 동등(E) 플래그 : 두 수를 비교한 결과가 같게 나왔을 경우에 1로 세트
  • 오버플로우(V) 플래그 : 산술 연산 과정에서 오버플로우가 발생한 경우에 1로 세트
  • 인터럽트(I) 플래그 : 인터럽트 가능 상태면 0, 인터럽트 불가능 상태면 1로 세트
  • 슈퍼바이저(P) 플래그 : CPU 실행 모드가 슈퍼바이저 모드면 1로, 사용자 모드이면 0으로 세트

아래 그림에서 SR이 상태 레지스터

 

📌 3 - 3. 슈퍼스칼라

슈퍼스칼라는 CPU의 처리 속도를 더욱 높이기 위하여 내부에 두 개 혹은 그 이상의 명령어 파이프라인을 포함시킨 구조를 말한다.

다음은 2-way 슈퍼스칼라의 예시이다.

슈퍼스칼라 프로세서 유의할 점으로는 동시에 처리할 명령어들이 서로 간에 영향을 받지 않고 독립적으로 실행될 수 있어야 한다. 즉, 두 명령어들 사이에 데이터 의존성(한 명령어를 실행한 다음에, 그 결괏값을 보내주어야 다음 명령어의 실행이 가능한 관계)이 존재하지 않아야 한다.

 

슈퍼스칼라에 의한 속도향상을 분석해 보면

 

단일 파이프라인에 의한 실행 시간 : T1 = k + N - 1

m-way 슈퍼스칼라에 의한 실행 시간 : Tm = K + N - m / m

속도향상 : m(k + N - 1) / N + m(k - 1)

슈퍼스칼라의 속도 저하(Sp < m) 요인으로는

  • 명령어들 간의 데이터 의존 관계
  • 하드웨어(ALU, 레지스터 등) 이용에 대한 경합 발생
    • 동시 실행 가능한 명령어의 수 < m
  • 해결책
    • 명령어 실행 순서 재배치 : 명령어들 간의 데이터 의존성 제거
    • 하드웨어 추가(중복) 설치 : 기억장치 / 레지스터에 대한 경합 감소

 

 

📌 3 - 4. 듀얼-코어 및 멀티-코어

CPU 코어 : 명령어 실행에 필요한 CPU 내부의 핵심(명령어 실행) 하드웨어 모듈 -> 슈퍼스칼라 모듈, ALU 및 레지스터 세트 등

 

멀티-코어 프로세서 : 하나의 칩에 여러 개의 CPU 코어들을 포함시킨 프로세서

  • 듀얼-코어 : 두 개의 CPU 코어 포함
  • 쿼드-코어 : 네 개의 CPU 코어 포함
  • 헥사-코어, 옥타-코어도 출시 중

이들은 칩-레벨 다중프로세서 혹은 단일-칩 다중프로세서라고도 부름

 

예를 들어 듀얼-코어 프로세서는

  • 단일-코어 슈퍼스칼라 프로세서에 비하여 2배의 속도 향상 기대
  • 코어들은 내부 캐시시스템 버스 인터페이스만 공유 (슈퍼스칼라의 명령어 파이프라인에 비해 독립성이 더 높음)
  • 코어 별로 독립적 프로그램 실행 : 멀티-태스킹 혹은 멀티-스레딩

 

멀티-태스킹 : 여러 CPU 코어들을 이용하여 독립적인 태스크 프로그램들을 동시에 처리하는 기술

멀티-스레딩 : 하나의 CPU 코어가 다수의 스레드들을 동시에 실행하는 기법

  • 스레드 : 독립적으로 실행될 수 있는 최소 크기의 프로그램 단위
  • 단일-스레드 모델 : 각 코어가 스레드를 한 개씩 처리
    • 처리 중의 스레드에 대한 시스템 상태, 데이터 및 주소 정보를 레지스터 세트(RS)에 저장
  • RS : 프로그램 카운터(PC), 스택 포인터(SP), 상태 레지스터, 데이터 레지스터, 주소 레지스터 등으로 이루어진 레지스터 세트

멀티-스레드 모델

  • 각 코어는 두 개의 RS들을 포함하며, 스레드를 두 개씩 처리
  • 두 스레드들이 CPU 코어의 H / W 자원들 (ALU, 부동소수점유니트, 온-칩캐시, TLB 등)을 공유
  • 처리 중의 각 스레드에 대한 시스템 상태, 데이터 및 주소 정보는 서로 다른 레지스터 세트(RS)에 저장

멀티-스레딩 기능을 가진 듀얼-코어 프로세서 : 두 개의 물리적 프로세서(코어)들이 네 개의 논리적 프로세서(RS)들로 구성되어 있다.

 

🎯 4. 명령어 세트


명령어 세트 : CPU를 위하여 정의되어 있는 명령어들의 집합

명령어 세트 설계를 위해 결정되어야 할 사항들

  • 연산 종류 : CPU가 수행할 연산들의 수와 종류 및 복잡도
  • 명령어 형식 : 명령어의 길이, 오퍼랜드 필드들의 수와 길이 등
  • 주소지정 방식 : 오퍼랜드의 주소를 지정하는 방식
  • 데이터 형태 : 연산이 수행될 데이터들의 형태, 데이터의 길이(비트 수), 수의 표현 방식 등

📌 4 - 1. 연산의 종류

어떤 컴퓨터든 반드시 수행할 수 있어야 하는 기본적인 연산들이 있는데, 그들을 분류하여 설명하면 다음과 같다.

  • 데이터 전송 : 레지스터와 레지스터 간, 레지스터와 기억장치 간, 혹은 기억장치와 기억장치 간에 데이터를 이동하는 동작
  • 산술 연산 : 덧셈, 뺄셈, 곱셈 및 나눗셈과 같은 기본적인 산술 연산들
  • 논리 연산 : 데이터의 각 비트들 간에 대한 AND, OR, NOT 및 XOR 연산
  • 입출력 (I / O) : CPU와 외부 장치들 간의 데이터 이동을 위한 동작들
  • 프로그램 제어 : 명령어 실행 순서를 변경하는 연산들 (분기, 서브루틴 호출)

산술 연산과 논리 연산, 입출력은 각각 3, 3, 7장에서 설명하고, 프로그램 제어들 중에 분기는 이전에 살펴봤으니 이번에는 서브루틴 호출에 대해 살펴본다

 

서브루틴 호출을 위한 명령어들

  • CALL 명령어 : 현재의 PC 내용을 스택에 저장하고, 서브루틴의 시작 주소로 분기하는 명령어 (서브루틴을 호출하는 명령어)
  • RET 명령어 : CPU가 원래 실행하던 프로그램으로 복귀시키는 명령어

CALL 및 RET 명령어를 마이크로 연산으로 자세하게 분석해 보자

CALL X 명령어에 대한 마이크로 연산

t(주기) 동작 비고
t0 MBR <- PC PC의 주소를 TOS에 저장하기 위해 MBR로 값을 이동함
t1 MAR <- SP, PC <- X SP번지에 저장하기 위해 MAR로 값을 이동. PC는 X값
t2 M[MAR] <- MBR, SP <- SP - 1 M의 MAR번지에 MBR값 저장, 1스택 쌓였기 때문에 SP-1

현재의 PC 내용(서브루틴 수행 완료 후에 복귀할 주소)을 SP가 지정하는 스택의 최상위에 저장

만약 주소지정 단위가 바이트이고, 저장될 주소는 16비트라면, SP <- SP - 2로 변경

 

RET 명령어의 마이크로 연산

t(주기) 동작 비고
t0 SP <- SP + 1 SP의 값을 증가시켜 복귀 주소가 저장된 스택 위치를 가리킴
t1 MAR <- SP 복귀 주소를 스택으로부터 인출
t2 PC <- M[MAR] PC에 적재

아래 그림은 위 서브루틴 수행 과정에서 스택의 변화를 보여준다.

📌 4 - 2. 명령어 형식

각 명령어에는 CPU에 의해 실행될 때 제공해야 할 모든 정보를 포함하고 있어야 하는데, 그들 중에서 가장 기본적인 요소는 다음과 같다.

  • 연산 코드 : 수행될 연산을 지정
  • 오퍼랜드 : 연산을 수행하는 데 필요한 데이터 혹은 데이터의 주소
    • 각 연산은 한 개 혹은 두 개의 입력 오퍼랜드들과 한 개의 결과 오퍼랜드를 포함
    • 데이터는 CPU 레지스터, 주기억장치, 혹은 I / O 장치에 위치
  • 다음 명령어 주소 : 현재의 명령어 실행이 완료된 후에 다음 명령어를 인출할 위치
    • 분기 혹은 호출 명령어와 같이 실행 순서를 변경하는 경우에 필요

각 명령어는 일련의 비트들에 의해 표현되고, 비트의 수는 정보들을 나타내는데 필요한 만큼 사용된다.

명령어를 구성하는 비트들은 용도에 따라 몇 개의 필드(명령어의 각 구성 요소들에 소요되는 비트들의 그룹)들로 나눌 수 있는데, 필드의 수와 배치 방식 및 각 필드에 포함되는 비트 수를 정의한 것을 명령어 형식이라 한다. 일반적으로 명령어의 길이는 단어(word)의 길이와 같다 (CPU에 따라 명령어의 길이가 단어의 두 배 혹은 그 이상일 수도 있음)

 

다음과 같이 16-비트 명령어가 세 개의 필드들로 구성된 경우를 고려해 보자

명령어 형식의 결정에서 고려할 사항들은 다음과 같다

  • 연산 코드 필드 길이 : 연산의 개수를 결정
    • 예) 4 비트 -> 2⁴ = 16 가지의 연산 정의 가능
    • 만약 연산 코드 필드가 5 비트로 늘어나면 32 가지 연산 정의 가능 -> 다른 필드의 길이가 감소
  • 오퍼랜드 필드의 길이 : 오퍼랜드의 종류에 따라 범위 결정
    • 데이터 : 표현 가능한 수의 범위 결정
    • 기억장치 주소 : CPU가 오퍼랜드 인출을 위하여 직접 주소를 지정할 수 있는 기억장치 용량 결정
    • 레지스터 번호 : 데이터 저장에 사용될 수 있는 레지스터의 개수 결정

예를 들어 위 그림에서 오퍼랜드 1은 레지스터 번호를, 오퍼랜드 2는 기억장치 주소를 지정하는 경우는

  • 오퍼랜드 1 : 4 비트 -> 16개의 레지스터 사용 가능
  • 오퍼랜드 2 : 8 비트 -> 기억장치의 주소 범위 : 0 ~ 255  번지

두 개의 오퍼랜드들을 하나로 통합(12비트)하여 사용하는 경우에는

  • 오퍼랜드가 2의 보수로 표현되는 데이터라면, 표현 범위는 : -2048(-2¹¹) ~ +2047(2¹¹ - 1)
  • 오퍼랜드가 기억장치 주소라면, 2¹² = 4096개의 기억장치 주소들 지정 가능

 

그래서 오퍼랜드의 수에 따른 명령어를 분류해 보자면

  • 1-주소 명령어 : 오퍼랜드를 한 개만 포함하는 명령어 (다른 한 오퍼랜드는 묵시적으로 AC(누산기)가 됨)
    • 예) ADD X ➡️ AC <- AC + M[X]
  • 2-주소 명령어 : 두 개의 오퍼랜드를 포함하는 명령어
    • 예) ADD R1, R2 ➡️ R1 <- R1 + R2
  • 3-주소 명령어 : 세 개의 오퍼랜드들을 포함하는 명령어
    • 예) ADD R1, R2, R3 ➡️ R1 <- R2 + R3

1-주소 명령어의 예

길이가 16비트인 1-주소 명령어에서 연산 코드가 5 비트인 경우 명령어 형식을 정의하고, 주소지정 가능한 기억장치 용량을 결정하라

명령어 형식 : 

주소지정 가능한 기억장치 용량 : 2¹¹ = 2048 단어 = 4096 바이트

 

2-주소 명령어의 예

2-주소 명령어 형식을 사용하는 16-비트 CPU에서 연산코드가 5 비트이고, 레지스터의 수는 8(2³ = 8)개 이다.

(a) 두 오퍼랜드들이 모두 레지스터 번호인 경우와

(b) 한 오퍼랜드는 기억장치 주소인 경우의 명령어 형식을 정의하라

3-주소 명령어의 예

3-주소 명령어 형식을 사용하는 16-비트 CPU에서 연산 코드가 4 비트이고, 3개의 오퍼랜드들은 레지스터 번호를 가진다. 각 필드는 4비트씩 할당할 수 있다.

 

위에서 살펴봤던 명령여 형식은 프로그램의 길이에 직접적인 영향을 미친다.

X = (A + B) X (C - D)를 통해 직접 확인해 보자

 

이 예시에서는 다음과 같은 니모닉스를 가진 명령어들을 사용하기로 한다

ADD 덧셈
SUB 뺄셈
MUL 곱셈
DIV 나눗셈
MOV 데이터 이동(레지스터와 기억장치 간)
LOAD 기억장치로부터 데이터를 읽어 AC에 적재
STOR AC의 내용을 기억장치에 저장

1-주소 명령어를 사용한 프로그램

단, M[A]는 기억장치 A번지의 내용, T는 기억장치 내 임시 저장장소의 주소

니모닉스 동작
LOAD A AC <- M[A]
ADD B AC <- AC + M[B]
STOR T M[T] <- AC
LOAD C AC <- M[C]
SUB D AC <- AC - M[D]
MUL T AC <- AC * M[T]
STOR X M[X] <- AC

프로그램의 길이 = 7

 

2-주소 명령어를 사용한 프로그램

니모닉스 동작
MOV R1, A R1 <- M[A]
ADD R1, B R1 <- R1 + M[B]
MOV R2, C R2 <- M[C]
SUB R2, D R2 <- R2 - M[D]
MUL R1, R2 R1 <- R1 * R2
STOR X, R1 M[X] < -R1

프로그램의 길이 = 6

 

3-주소 명령어를 사용한 프로그램

니모닉스 동작
ADD R1, A, B R1 <- M[A] + M[B]
SUB R2, C, D R2 <- M[C] - M[D]
MUL X, R1, R2 M[X] <- R2 * R2

프로그램의 길이 = 3

 

프로그램의 길이가 짧아진다는 장점이 있지만, 명령어 자체의 길이(비트 수)가 증가하고 명령어 해독 과정이 복잡해진다는 단점도 있다.

 

📌 4 - 3. 주소지정 방식

주소지정 방식 : 명령어 실행에 필요한 오퍼랜드의 주소(데이터)를 결정하는 방식

 

위에서 살펴보았던 n-주소 명령어를 사용하여 명령어의 길이가 늘어나면 오퍼랜드 필드의 수와 각 필드의 비트의 수가 증가될 수 있지만, 일반적으로 명령어 비트의 수는 CPU가 처리하는 단어의 갈이와 같도록 제한된다.

이와 같이 제한된 수의 명령어 비트들을 사용자 혹은 프로그래머로 하여금 다양한 방법으로 오퍼랜드를 지정하고 더 큰 용량의 기억장치를 사용할 수 있도록 하기 위해 여러 가지 주소지정 방식들이 제안되어 있다.

 

주소지정 방식을 설명하기 위해 아래와 같은 표기들을 사용한다.

  • EA : 유효 주소, 즉 데이터가 저장된 기억장치의 실제 주소
  • A : 명령어 내의 주소 필드 내용 (오퍼랜드 필드의 내용이 기억장치 주소인 경우)
  • R : 명령어 내의 레지스터 번호 (오퍼랜드 필드의 내용이 레지스터 번호인 경우)
  • (A) : 기억장치 A 번지의 내용
  • (R) : 레지스터 R의 내용

주소지정 방식은 다음처럼 여러 가지 방법이 있다.

주소지정 방식에 따라 유효 주소인 EA가 결정되며, EA는 실제 데이터를 읽어오기 위한 주소로 사용된다.

주소지정 방식이 복잡해질수록 EA를 결정하는 데 걸리는 시간이 길어진다.

  • 직접 주소지정 방식
  • 간접 주소지정 방식
  • 묵시적 주소지정 방식
  • 즉시 주소지정 방식
  • 레지스터 주소지정 방식
  • 레지스터 간접 주소지정 방식
  • 변위 주소지정 방식
    • 상대 주소지정 방식
    • 인덱스 주소지정 방식
    • 베이스 레지스터 주소지정 방식

하나씩 살펴보자

 

직접 주소지정 방식(direct addressing mode)

  • 오퍼랜드 필드의 내용이 유호 주소가 되는 방식 EA = A
  • 장점 : 데이터 인출을 위하여 한 번의 기억장치 액세스만 필요
  • 단점 : 연산 코드를 제외하고 남은 비트들만 주소 비트로 사용될 수 있기 때문에 직접 지정할 수 있는 기억장소의 수가 제한 (만약 연산코드가 4비트, 오퍼랜드가 12비트라면 기억장소는 4096개가 최대임)

간접 주소지정 방식(indirect addressing mode)

  • 오퍼랜드 필드에 기억장치 주소가 저장되어 있지만, 그 주소가 가리키는 기억 장소에 데이터의 유효 주소를 저장해 두는 방식 EA = (A)
  • 명령어 형식에 간접비트(I) 필요
    • 만약 I = 0 이면, 직접 주소지정 방식
    • 만약 I = 1 이면, 간접 주소지정 방식

  • 다단계 간접 주소지정 방식
    • EA = ( ( (A) ) )
  • 장점 : 최대 기억장치용량이 단어의 길이에 의하여 결정 ➡️ 주소지정 가능한 기억장치 용량 확장 (단어 길이가 n 비트라면, 최대 2ⁿ 개의 기억 장소 주소지정 가능)
  • 단점 : 실행 사이클 동안에 두 번의 기억장치 액세스가 필요
    • 첫 번째 액세스 : 주소 인출
    • 두 번째 액세스 : 그 주소가 지정하는 기억 장소로부터 실제 데이터 인출

묵시적 주소지정 방식(implied addressing mode)

  • 명령어 실행에 필요한 데이터의 위치가 묵시적으로 지정되는 방식
  • 장점 : 명령어 길이가 짧다
  • 단점 : 종류가 제한된다
  • 예) shift 명령어 : 누산기의 내용을 좌측으로 시프트, PUSH R1 명령어 : 레지스터 R1의 내용을 스택에 저장 (누산기, 스택이 묵시적)

즉시 주소지정 방식

  • 데이터가 명령어에 포함되어 있는 방식 (오퍼랜드 필드의 내용이 연산에 사용할 실제 데이터)
  • 용도 : 프로그램에서 레지스터나 변수의 초기 값을 어떤 상수값으로 세트 하는 데 사용
  • 장점 : 데이터를 인출하기 위하여 기억장치를 액세스 할 필요가 없음 (주기억장치는 레지스터에 비해 약 1000배 느리기 때문에 장점)
  • 단점 : 상수값의 크기가 오퍼랜드 필드의 비트 수에 의해 제한됨

레지스터 주소지정 방식(register addressing mode)

  • 연산에 사용될 데이터가 내부 레지스터에 저장되어 있는 경우, 명령어의 오퍼랜드가 해당 레지스터를 가리키는 방식 EA = R
  • 주소지정에 사용될 수 있는 레지스터들의 수 = 2k 개 (k는 R 필드의 비트 수)
  • 장점 : 오퍼랜드 필드의 비트 수가 적어도 된다, 데이터 인출을 위하여 기억장치 액세스가 필요 없다
  • 단점 : 데이터가 저장될 수 있는 공간이 CPU 내부 레지스터들로 제한 (만약 R이 4비트라면 16개의 공간이 최대)

레지스터 간접 주소지정 방식

  • 오퍼랜드 필드(레지스터 번호)가 가리키는 레지스터의 내용을 유효 주소를 사용하여 실제 데이터를 인출하는 방식
  • 장점 : 주소지정 할 수 있는 기억장치 영역이 확장 (레지스터의 길이가 16비트라면, 주소지정 영역은 2¹⁶ = 64K 단어)
  •  

변위 주소지정 방식(displacement addressing mode)

  • 직접 주소지정과 레지스터 간접 주소지정 방식의 조합 EA = A + (R)
  • 사용되는 레지스터에 따라 여러 종류의 변위 주소지정 방식 정의
    • PC ➡️ 상대 주소지정 방식(relative addressing mode)
    • 인덱스 레지스터(IX) ➡️ 인덱스 주소지정 방식(indexed addressing mode)
    • 베이스 레지스터(BR) ➡️ 베이스-레지스터 주소지정 방식(base-register addressing mode)

변위 주소지정 방식 - 상대 주소지정 방식

  • 프로그램 카운터(PC)를 레지스터로 사용 (주로 분기 명령어에서 사용) EA = A + (PC) (단, A는 2의 보수)
  • PC의 내용과 명령어 내 오퍼랜드를 더하여 유효주소를 결정하는 주소지정 방식
  • 값이 아닌 명령어를 읽어오는 것이 목적
  • A > 0 : 앞 방향으로 분기 (JUMP 명령어가 450 번지에 있고 (JUMP 명령어가 인출된 후에는 PC가 증가되어 451을 가리키는 중), A가 21이면 472 번지로 점프 )
  • A < 0 : 뒷 방향으로 분기 (JUMP 명령어가 450 번지에 있고 (JUMP 명령어가 인출된 후에는 PC가 증가되어 451을 가리키는 중), A가 -50이면 401 번지로 점프)
  • 장점 : 전체 기억장치 주소가 명령어에 포함되어야 하는 일반적인 분기 명령어보다 적은 수의 비트만 있으면 된다
  • 단점 : 분기 범위가 오퍼랜드 필드의 길이에 의해 제한된다

변위 주소지정 방식 - 인덱스 주소지정 방식

  • 인덱스 레지스터의 내용과 변위 A를 더하여 유효 주소를 결정 EA = (IX) + A
    • 인덱스 레지스터(IX) : 인덱스 값을 저장하는 특수 레지스터
  • 주요 용도 : 배열 데이터 액세스
  • 자동 인덱싱 : 명령어가 실행될 때마다 인덱스 레지스터의 내용이 자동적으로 증가 혹은 감소
    • 이 방식이 사용된 명령어가 실행되면 아래의 두 연산이 연속적으로 수행됨
    • EA = (IX + A)
    • IX <- IX + 1

아래 그림처럼 배열이 500번지부터 시작하고, 명령어의 주소필드에 500이 포함되어 있을 때 인덱스 레지스터의 내용 3을 조합해 배열의 4번째 데이터에 액세스 한다.

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

  • 베이스 레지스터의 내용과 변위 A를 더하여 유효주소를 결정 EA = (BR) + A
  • 주요 용도 : 프로그램의 위치 지정(변경)에 사용
    • 다중프로그래밍(CPU 하나가 여러 개의 프로그램을 동시에 서비스하는 경우) 환경에서 프로그램 코드 및 데이터를 다른 위치로 이동시켜야 할 때, 분기 명령어나 데이터 액세스 명령어들의 주소 필드 내용을 바꿀 필요 없이, BR의 내용만 변경하면 된다.
  • 이 방식은 인덱스 주소지정 방식과 유사하지만 레지스터가 사용되는 방법에 있어서 차이점이 있다. 베이스 레지스터에는 기준이 되는 명령어의 주소가 저장된다. 이 방식은 주로 프로그램의 시작 위치를 지정하는 데 사용된다.

📌 4 - 4. 실제 상용 프로세서들의 명령어 형식

CISC(Complex Instruction Set Computer) 프로세서

  • 명령어들의 수가 많음
  • 명령어 길이가 일정하지 않음(명령어 종류에 따라 달라짐)
  • 주소지정 방식이 매우 다양함
  • 예) PDP 계열 프로세서, Intel Pentium 계열 프로세서

RISC(Reduced Instruction Set Computer) 프로세서

  • 명령어들의 수를 최소화
  • 명령어 길이를 일정하게 고정
  • 주소지정 방식의 종류를 단순화
  • 예) ATmega microcontroller, ARM 계열 프로세서

 

PDP 계열 프로세서

  • PDP-10 프로세서 : 고정 길이의 명령어 형식 사용
    • 단어의 길이 : 36비트, 명령어의 길이 36 비트
    • 연산 코드 = 9 비트 ➡️ 최대 512 종류의 연산 허용 (실제 365 개)

  • PDP-11 프로세서 : 다양한 길이의 명령어 형식들 사용
    • 연산 코드 = 4 ~ 16 비트
    • 주소 개수 : 0 ~ 4 개

PDP-11의 명령어 형식들

펜티엄 계열 프로세서

CISC 형식으로 분류되는 펜티엄 계열 프로세서들은 다양한 명령어 형식을 사용하고 있다. 이를 이해하기 위해 주조지정 방식들을 살펴본다

  • segmant : 기억장치 공간의 분류 단위
  • segment register : 이 레지스터로 세그먼트가 구분됨. 6개의 세그먼트 레지스터. 각각의 SR은 해당 세그먼트의 시작 주소를 가지고 있다
  • BR : 베이스 레지스터
  • IX : 인덱스 레지스터

펜티엄 계열 프로세서는 EA가 결정되면 해당 세그먼트의 시작 주소와 유효 주소를 더하여 실제 기억장치를 액세스 하는 데 사용되는 선형 주소(LA)를 생성한다.

  • 즉시 방식 : 데이터가 명령어에 포함
  • 레지스터 방식 : 유효 주소가 레지스터에 들어있음
  • 변위 방식 : 명령어에 포함된 변위 값과 세그먼트 레지스터 SR의 내용을 더하여 선형주소 LA를 생성
  • 베이스 방식 : 레지스터 간접 주소지정 방식과 동일
  • 변위를 가진 베이스 방식 : 어떤 레지스터든 베이스 레지스터로 사용. 반복계산에 유용
  • 변위를 가진 인덱스 방식 : 명령어가 IX에 더해질 변위값을 포함. 데이터 배열 순차 검색에 유용
  • 인덱스와 변위를 가진 베이스 방식 : 다 더하여 유효 주소 결정. 특정 지역 내의 데이터 배열을 액세스 하는 데 유용
  • 상대 방식 : 변위 값이 PC와 더해지고 그 값은 다음 명령어의 주소로 사용됨. 변위 값은 sign bit, word, 이중 word 등이 사용될 수 있다.

펜티엄 계열 프로세서의 명령어 형식은 다음과 같은 필드들을 포함하고 있다

  • Op Code (연산 코드) : 연산의 종류를 지정
  • MOD / RM : 주소지정 방식을 지정해 줌. 세 개의 필드들로 구성
  • SIB : MOD / RM 필드와 결합하여 주소지정 방식을 완성시켜 줌. 세 개의 필드들로 구성
  • Displacement (변위) : 변위 방식인 경우 부호화된 정수가 저장
  • Immediate (즉시) : 즉시 방식의 경우 데이터가 저장

 

ATmega Microcontroller 명령어 형식

  • ATmega128 microcontroller의 CPU 코어
    • 8-비트 CPU
    • 명령어의 길이 = 16 비트
    • 기억장치 액세스 명령어들(LOAD, STORE)은 32비트
    • RISC  프로세서
    • 특징
      • 연산 코드의 비트 수가 명령어에 따라 달라짐
      • 오퍼랜드의 위치가 유동적

ARM(Advanced RISC Machine) 계열 프로세서

  • 32-비트 RISC 프로세서
  • 개방형 아키텍처
  • 모바일 시스템용 프로세서로 널리 사용
  • 명령어 필드들
    • 분기조건 필드, 연산 필드, 오퍼랜드 필드 등
    • 조건 플래그 : N, Z, C, V
    • 레지스터 필드 : Rn, Rd, Rs
    • P, U, W 비트 : 주소지정 방식 결정
    • B 비트 : 연산처리 단위 결정(B = 1 = 바이트 혹은 0 = 단어)

728x90