컴퓨터 구조 요약 - 8. 중앙 처리 장치

8.1. 개요(Introduction)

컴퓨터에서 데이터 처리 동작을 수행하는 부분을 중앙 처리 장치(CPU)라고 한다. CPU는 주 요소는 다음과 같다.

  1. 명령어 실행에 필요한 중간 데이터를 저장하는 레지스터 집합
  2. 명령어를 실행하기 위한 마이크로 연산을 수행하는 ALU
  3. 정보 전송 및 ALU 수행 동작을 제어하는 제어 장치

8.2. 범용 레지스터 구조(General Regiser Organization)

포인터, 계산 중간 값 등을 저장하기 위해서 기억 장소가 필요하다. 이때 메모리를 호출하는 것은 시간이 많이 걸린다. 메모리 접근은 마이크로 연산에서 대부분의 시간을 소요하기 때문이다.

따라서 프로세서 레지스터에 저장하는 것이 효율적이다. 많은 수의 레지스터들을 버스에 연결하고, 빠른 접근 시간을 지닌 로컬(local) 메모리로 사용하는 것이 가장 효율적이다.

8.3. 스택 구조(Stack Organization)

스택(또는 last-in, first-out; LIFO)은 가장 나중에 메모리에 저장된 내용이 가장 먼저 꺼내지도록 하는 저장 장치이다. 리턴 주소 저장, 역 Polish 표기, 산술식의 계산 등에 활용될 수 있다.

8.3.1. 레지스터 스택(Register Stack)

스택은 메모리의 일부분에 놓일 수도 있고, 제한된 수의 메모리 워드나 레지스터들로 구성될 수도 있다. 아래 그림은 독립적으로 존재하는 64워드의 메모리 스택이다.

8.3.2. 메모리 스택(Memory Stack)

스택은 아래 그림과 같이 RAM 메모리의 일부분에 할당될 수도 있다.

8.4. 명령어 형식(Instruction Formats)

명령어 형식에는 여러 필드가 있을 수 있으며, 가장 흔한 필드는 다음과 같다.

  1. 수행할 연산을 명시한 연산 코드 필드
  2. 메모리 혹은 레지스터의 주소를 지정한 주소 필드
  3. 피연산자나 유효 주소가 결정되는 방법을 나타내는 모드 필드

명령어 형식에서 주소 필드의 숫자는 컴퓨터 레지스터의 구성에 좌우된다. CPU 구조는 아래 3가지 형식 중 하나이거나 복합적으로 섞인 형태이다.

  1. 단일 누산기 구조 - 단일 프로세스 레지스터 AC가 ALU와 연결되어 명령어 수행
  2. 범용 레지스터 구조 - 메모리 접근보다 빠르게 접근 가능한 레지스터를 처리 장치에 많이 두어 명령어 수행
  3. 스택 구조 - 레지스터 스택, 메모리 스택을 활용하여 명령어 수행

위의 구조에 따라 3-주소, 2-주소, 1-주소, 무주소 명령어 등이 있다. 이는 ADD, MUL와 같은 명령어 뒤에 나오는 주소의 개수이다.

메모리와 CPU 사이의 통신을 할 때, LOAD와 STORE 명령어만 쓸 수 있는 RISC 명령어 형식도 있다.

8.5. 어드레싱 모드(Addressing Modes)

피연산자가 지정되는 방법은 명령어의 어드레싱 모드에 의해 결정된다. 간접 주소, 인덱스드 어드레싱, 베이스 레지스터 모드 등 다양하다.

8.6. 데이터 전송과 처리(Data Transfer and Manipulation)

컴퓨터는 광범위한 명령어 집합을 가지고 있다. 대부분의 명령어는 다음 중의 한 가지로 분류된다.

  1. 데이터 전송 명령어 - LOAD, PUSH …
  2. 데이터 처리 명령어 - 산술(INCREMENT, …), 논리(OR, …), 시프트(ROTATE RIGHT, …)
  3. 프로그램 제어 명령어 - BRANCH, CALL …

8.7. 프로그램 제어(Program Control)

데이터 전송/처리 명령어는 어떤 정보에 대해 동작하는 데 비해, 프로그램 제어 명령어는 프로그램 카운터(PC)의 값을 바꾼다.

8.7.1. 상태 비트 조건(Status Bit Conditions)

상태 비트는 조건 코드(condition code)나 플래그(flag) 등으로도 불린다. 8비트 기본 컴퓨터에서 사용되는 플래그는 다음과 같다.

  1. C 비트는 ALU의 출력 캐리가 1이면 1이고, 0이면 0이다.
  2. S 비트는 ALU의 연산 결과에서 부호 비트(가장 높은 자리의 비트)가 1이면 1이고, 0이면 0이다.
  3. Z 비트는 ALU의 연산 결과 비트가 모두 0이면 1이고, 아니라면 0이다.
  4. V 비트는 C8, C9의 exclusive-OR 결과가 1이면 1이고, 아니라면 0이다. 오버플로우를 감지한다.

8.7.2. 조건부 분기 명령어(Conditional Branch Instructions)

8.7.3. Subroutine Call and Return

어떤 프로그램이 서브프로그램을 부를 경우 아래의 동작이 수행된다.

  1. 현재 프로그램 카운터의 값(return address)을 어떤 위치(주로 스택; 레지스터 등)에 기억시켜 놓는다.
  2. 프로그램 수행이 서브루틴의 시작으로 가게 한다.

8.7.4. 프로그램 인터럽트(Program Interrupt)

프로그램 인터럽트는 정상적인 프로그램의 진행을 벗어 나게 하는 여러 문제가 발생 했을 때, 이를 해결하기 위해 현재 프로그램에서 벗어나 다른 서비스 프로그램을 수행한 후 돌아오는 것이다.

인터럽트는 다음 요건을 제외하면 서브루틴과 비슷하다.

  1. 소프트웨어 인터럽트를 제외하고는, 명령어의 수행에 의한 것이 아니라, 내/외부적인 신호에 의해 프로그램의 진행이 바뀐다.
  2. 서비스 프로그램의 주소는 명령어의 주소 필드에 있는 것이 아니라, 하드웨어에 의해 결정된다.
  3. 인터럽트에서는 프로그램 카운터만이 아니라 CPU의 상태 정보도 대피시킨다.

어떤 기종에서는 인터럽트 시 서비스 프로그램을 항상 일정한 위치에서 시작하게 한다. 이는 어떤 요인이 인터럽트를 발생하게 했는가를 조사하고, 그에 대한 서비스를 해준다.

인터럽트 요인이 발생했을 때, CPU의 다음과 같은 상태를 확인하고 저장한다. 3번은 저장하지 않을 수도 있다.

  1. 프로그램 카운터의 내용
  2. 상태 조건의 내용(모든 상태 비트 조건의 집합은 program status word; PSW 라고도 한다)
  3. 모든 레지스터의 내용

8.7.4.1. 인터럽트의 형태(Types of Interrupts)

아래와 같이 3가지 형의 인터럽트이 존재 한다. 외부, 내부 인터럽트는 하드웨어 신호에 의해 발생한다.

  1. 외부 인터럽트 - 입출력, 타이밍 장치 등에 의해 발생
  2. 내부 인터럽트 혹은 트랩(trap) - 오버플로, 0으로 나눔 등에 의해 발생
  3. 소프트웨어 인터럽트 - supervisor call와 같이 프로그래머에 의해 프로그램상의 원하는 위치에서 발생

8.8. 간소화된 명령어 집합 컴퓨터(Reduced Instruction Set Computer, RISC)

명령어 집합 수에 따라 복잡한 명령어 집합 컴퓨터(complex instruction set computer, CISC), 간소화된 명령어 집합 컴퓨터가 있다. x86(CISC)은 내부적으로 RISC를 병행하여 사용한다.

8.8.1. CISC의 특징(CISC Characteristics)

CISC 구조의 기본적인 목표는 모든 고급 언어 문장들에 대해 각각 하나의 기계 명령어가 대응 되도록 하는 것이다.

  1. 많은 명령어, 몇몇 명령어는 특별한 동작을 수행하며 자주 사용되지 않음
  2. 다양한 어드레싱 모드
  3. 가변 길이 명령어 형식
  4. 메모리의 피연산자를 처리하는 명령어
  5. 마이크로 프로그램된 제어 선호

8.8.2. RISC의 특징(RISC Characteristics)

RISC 구조의 목표는 컴퓨터의 명령어 집합을 간소화하여 실행 시간을 줄이는 것이다.

  1. 적은 명령어
  2. 적은 어드레싱 모드
  3. 고정 길이 명령어 형식으로 디코딩 간단
  4. 메모리 참조는 LOAD, STORE 명령어에서만 가능하고 나머지는 CPU 레지스터 안에서 수행
  5. 하드와이어된 제어를 선호

8.8.2.1. 중첩된 레지스터 윈도우(Overlapped Register Windows)

프로시저의 호출과 복귀는 고급 언어 프로그램에서 자주 나타나며, 기계어 명령어로 번역되면 일련의 명령어를 만들어낸다.
호출의 경우 레지스터 값을 저장하고, 프로시저에서 사용될 파라미터를 전달하며, 프로시저를 수행하도록 서브루틴을 호출하는 명령어들이 생성된다.
복귀의 경우 레지스터 값을 복구하고, 결과를 호출한 프로그램에게 전달하며, 서브루틴으로부터 복귀하는 명령어들이 생성된다.

그런데, 레지스터의 값을 저장하고 복구하는 일과 파라미터와 결과를 전달하는 일은 시간이 많이 걸리는 동작이다. 따라서 몇몇 컴퓨터에서는 이러한 동작을 없애기 위해, 다수의 레지스터 묶음 가지고서 각 프로시저에게 하나씩의 레지스터 묶음을 할당한다.

RISC 프로세서는 중첩된 레지스터 윈도우를 사용하는데, 프로시저 호출이 있을 때 마다 레지스터 파일로부터 레지스터 묶음으로 이루어진 새 윈도우를 할당한다.
호출은 포인터 값을 증가시킴으로써 새 윈도우를 활성화시키고, 복귀는 포인터 값을 감소시킴으로써 이전 윈도우를 활성화시킨다.
그리고 인접한 프로시저들의 윈도우는 파라미터와 결과 전달을 위해 레지스터를 중첩시켜 공유한다.

예를 들어, 프로시저 A가 프로시저 B를 호출한다면, 프로시저 A는 R26에서 R31까지의 공통 레지스터에 프로시저 B를 위한 파라미터를 저장한다. 프로시저 B는 레지스터 R32에서 R41까지를 지역 변수를 위해 사용한다.

프로시저 B가 복귀할 때에는 계산한 결과를 R26~R31에 저장하고, 이것을 프로시저 A의 레지스터 윈도우로 전달한다.

댓글남기기