4장 CPU의 작동 원리

04-1 ALU와 제어장치

CPU의 구성

  • ALU: 계산을 담당
  • 제어장치: 명령어를 읽어 들이고 해석
  • 레지스터: 작은 임시 저장 장치

ALU

Input

  • 피연산자: 레지스터를 통해 받는 연산의 대상
  • 제어 신호: 수행할 연산에 대한 정보

Output

  • 계산 결괏값, 플래그
  • 연산 수행의 결과는 특정 데이터일 수도, 메모리 주소가 될 수 있다.
  • 결괏값은 바로 메모리에 저장되지 않고 일시적으로 레지스터에 저장
    • CPU가 메모리에 접근하는 속도 < CPU가 레지스터에 접근하는 속도
  • 플래그(flag)
    • 연산 결과에 대한 추가적인 정보
    • 부호 플래그, 제로 플래그, 캐리 플래그 등
    • 플래그 레지스터에 저장
  • 오버플로우(overflow): 연산결과가 연산을 담을 레지스터보다 큰 상황

제어장치

  • 제어 신호를 내보내고, 명령어를 해석하는 부품
    • 제어신호: 컴퓨터 부품들을 관리하고 작동시키기 위한 일종의 전기 신호

Input

  1. 클럭 신호
    • 클럭(clock): 컴퓨터의 모든 부품을 움직이는 시간 단위
    • 컴퓨터의 모든 부품은 클럭 신호에 맞춰 작동
      • 하지만 모든 부품이 한 클럭마다 작동하는 것은 아님
  2. 해석해야 할 명령어
    • 명령어 레지스터에 저장된 명령어
    • 명령어를 받아 해석한 뒤, 제어 신호를 발생시켜 컴퓨터 부품들에 수행해야할 내용을 전달
  3. 플래그 레지스터 속 플래그 값
    • ALU 연산에 대한 추가적인 상태 정보
  4. 제어버스로 전달된 제어 신호
    • 입출력장치를 비롯한 CPU 외부 장치가 발생시킨 제어 신호도 포함

Output

  • CPU 외부에 전달하는 제어 신호
    • 입출력장치: 입출력장치의 값을 읽거나 새로운 값을 쓸 때
    • 메모리: 메모리에 저장된 값을 읽거나 새로운 값을 쓸 때
  • CPU 내부에 전달하는 제어 신호
    • ALU: 수행할 연산을 지시하기 위해
    • 레지스터: 레지스터 간에 데이터롤 이동시키거나 저장된 명령어를 해석하기 위해

04-2 레지스터

반드시 알아야 할 레지스터

많은 CPU가 공통으로 포함하는 레지스터들

프로그램 카운터

PC(Program Counter) 혹은 IP**(Instruction Pointer)**: 메모리에서 가져올 명령어의 주소를 저장

명령어 레지스터

IR(Instruction Register): 읽어들인 명령어를 저장하는 레지스터

메모리 주소 레지스터

MAR(Memory Address Register): 메모리의 주소를 저장하는 레지스터

CPU가 주소 버스로 내보낼 값이 거치는 곳

메모리 버퍼 레지스터

MBR(Memory Buffer Register) 혹은 MDR**(Memory Data Register)**: 메모리와 주고받을 값(데이터와 명령어)을 저장하는 레지스터

CPU가 데이터 버스로 주고 받을 값이 거치는 곳

범용 레지스터

GPR(General Purpose Register): 데이터와 주소를 모두 저장할 수 있는 레지스터

플래그 레지스터

FR(Flag Register): ALU 연산 결과, CPU 상태에 대한 부가적인 정보 저장

스택 포인터

SP(Stack Pointer): 스택에 마지막으로 저장된 값의 위치(꼭대기)를 가리키는 레지스터. 스택 주소 지정 방식에 사용

베이스 레지스터

BR(Base Register): 변위 주소 지정 방식에 사용

메모리에 저장된 프로그램을 실행하는 과정

  1. 프로그램이 저장된 처음 메모리 주소(ex. 1000)이 프로그램 카운터에 저장됨
  2. 해당 메모리 주소가 메모리 주소 레지스터에 저장됨
  3. 해당 메모리 주소(1000)가 주소 버스, 제어 신호(메모리 읽기)가 제어 버스를 통하여 메모리에 전달
  4. 1000에 저장된 값이 데이터 버스를 통해 메모리 버퍼 레지스터에 전달되어 저장됨
  5. 1000이 저장된 프로그램 카운터가 1001로 증가함
  6. 메모리 버퍼 레지스터에 저장된 값이 명령어 레지스터로 저장됨

CPU 속 프로그램 카운터는 꾸쭌히 증가하며, 특정 명령어로 인해 순차적인 실행흐름이 끊어질 수 있음

ex) 점프, 특정 주소로 이동 등

특정 레지스터를 이용한 주소 지정 방식(1): 스택 주소 지정 방식

스택: 메모리 안에 존재하는 스택 영역에 존재

스택 포인터는 스택의 꼭대기를 가리킨다. 즉 스택에서 어느 주소까지 데이터가 채워져 있는지를 나타냄

스택 주소 지정 방식은 명령어의 오퍼랜드 필드에 스택 주소를 담는 방식

특정 레지스터를 이용한 주소 지정 방식(2): 변위 주소 지정 방식

변위 주소 지정 방식(displacement addressing mode): 명령어의 오퍼랜드 필드의 값(변위)과 특정 레지스터의 값을 더하여 유효 주소를 얻어내는 주소 지정 방식

오퍼랜드 필드의 주소와 어떤 레지스터를 더하는지에 따라 나뉘어짐

명령어의 값(PC)의 값과 멀면 오퍼랜드에 저장되어야 할 값이 커짐

상대 주소 지정 방식

상대 주소 지정 방식(relative addressing mode): 오퍼랜드 + 프로그램 카운터의 값(읽어들일 명령어의 주소) ⇒ 유효주소

따라서 지금 실행 중인 명령어의 주소를 기준으로 한 거리

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

베이스 레지스터 주소 지정 방식(base-register addressing mode): 오퍼랜드 + 베이스 레지스터의 값(기준 주소) ⇒ 유효주소

04-3 명령어 사이클과 인터럽트

명령어 사이클: 하나의 명령어를 처리하는 정형화된 흐름

인터럽트: 명령어를 처리해 나가는 흐름이 끊어지는 상황

명령어 사이클

명령어 사이클(instruction cycle): 프로그램 속 각각의 명령어들이 반복되며 실행되는 주기

인출 사이클(fetch cycle): 메모리에 있는 명령어를 CPU로 가지고 오는 단계

실행 사이클(execution cycle): CPU로 가져온 명령어를 실행하는 단계

간접 사이클(indirect cycle): 메모리 접근이 더 필요한 경우의 단계(간접 주소 지정 방식이라 주소를 가져온 경우 등)

인출 사이클과 실행 사이클의 반복 사이에서 경우에 따라 간접 사이클과 인터럽트 사이클이 실행된다.

인터럽트

인터럽트(Interrupt): CPU의 작업을 방해하고 중단시키는 신호

동기 인터럽트(synchronous interrupts)

  1. **예외(exception)**라고도 함
  2. CPU에 의해 발생하는 인터럽트
  3. ex) CPU가 실행하는 프로그래밍상의 오류

비동기 인터럽트(asynchronous interrupts)

  1. 하드웨어 인터럽트라고도 함
  2. 주로 입출력장치에 의해 발생하는 인터럽트
  3. ex) 작업을 끝낸 입출력장치가 CPU에 완료 알람을 보내는 경우

하드웨어 인터럽트

CPU의 명령을 수행하는 입출력장치가 작업의 완료를 알림

인터럽트가 발생하기 전까지 CPU는 다른 작업을 진행할 수 있음

하드웨어 인터럽트 처리 순서

  1. 입출력장치 → CPU 인터럽트 요청 신호 송신
  2. CPU는 실행 사이클이 끝나고 명령어를 인출하기 전 항상 인터럽트 여부를 확인
  3. CPU는 인터럽트 요청을 확인하고 인터럽트 플래그를 통해 현재 인터럽트를 수신할 수 있는 상태인지 확인
  4. CPU는 수신할 수 있으면 지금까지의 작업을 백업
  5. CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행
  6. 인터럽트 서비스 루틴 실행이 끝나면 4의 백업을 복구하여 실행 재개

인터럽트 요청 신호: 인터럽트를 발생시켜도 되는지 CPU에게 묻는 신호

인터럽트 플래그(interrupt flag): CPU가 하드웨어 인터럽트를 받아들일지, 무시할지를 결정하는 플래그 레지스터의 플래그

  • 막을 수 있는 인터럽트(maskable interrupt)
  • 막을 수 없는 인터럽트(non maskable interrupt): 일부 중요한 하드웨어 인터럽트(하드웨어 고장, 정전 등)는 플래그를 무시

인터럽트 서비스 루틴(Interrupt Service Routine): 인터럽트를 처리하기 위한 동작들로 이루어진 프로그램

  • **인터럽트 핸들러(Interrupt handler)**라고도 함

인터럽트 벡터(interrupt vector): 인터럽트 서비스 루틴을 식별하기 위한 정보

CPU는 하드웨어 인터럽트 요청을 보낸 대상으로부터 데이터 버스를 통해 인터럽트 벡터를 전달받음

CPU는 인터럽트 벡터를 통해 특정 인터럽트 서비스 루틴의 시작 주소를 알 수 있음

CPU가 인터럽트를 처리한다: 인터럽트 서비스 루티능ㄹ 실행하고, 본래 수행하던 작업으로 다시 되돌아온다.

CPU가 인터럽트를 처리하기 전, 프로그램 카운터 값 등 인터럽트 처리 이후 작업을 재개하기 위해 필요한 모든 내용을 스택에 백업함

예외의 종류

  1. 인터럽트
    1. 동기 인터럽트(예외)
      1. 폴트(fault)
        • 예외를 처리한 직후 예외가 발생한 명령어부터 실행을 재개
        • ex) 명령어를 처리하기 전 보조기억장치에서 필요한 데이터를 불러옴
      2. 트랩(trap)
        • 예외를 처리한 직후 예외가 발생한 명령어의 다음 명령어부터 실행을 재개
        • ex) 디버깅
      3. 중단(abort)
        • CPU가 실행중인 프로그램을 강제로 중단시킬 수밖에 없는 심각한 오류 발견
      4. 소프트웨어 인터럽트(software interrupt)
        • 시스템 호출 발생
  2. 비동기 인터럽트(하드웨어 인터럽트)

의문

  1. 제로플래그는 왜 필요할까?

    1. 연산 결과가 0인지 아주 빠르게 알기 위해..?
    2. 비교할 때 편하다.
      1. CPU가 두 값을 비교할 때, 뺄셈을 한다.
      2. 5와 5를 비교했을 때 연산 결과로 제로플래그가 나오면 “아 둘은 같군”이라고 판단함
  2. IR은 있는데, 데이터 레지스터는 없나?

    1. GPR이 그 역할을 함
  3. 명령어 데이터를 MBR→ IR 순서를 거치지 않고 바로 IR로 저장하면 안되나?

    1. 확장성, 타이밍, 예외처리를 위해 완충 역할(버퍼/캐시)로서 MBR이 필요
    2. 메모리에서 값이 딱 한 사이클에 깨끗하게 오지 않는다.
      1. 그럼 메모리에서 값이 여러 사이클에 온다고 하면 MBR이 다 받아서 한번에 IR로 넘겨줌
  4. 상대 주소 지정 방식과 베이스 레지스터 주소 지정 방식의 차이는 뭐지?

    1.  상대 주소 = 코드 기준(PC) 이동, 베이스 주소 = 데이터 기준(베이스 레지스터) 이동.
    2. 여기서 코드는 메모리에 저장된 프로그램의 명령어들
  5. 스택 주소 지정방식은 스택에 데이터가 스택에 저장되어 있을 때 사용하나? 그럼 스택에 저장된 데이터는 뭐지?

    1. 로컬/리턴주소/레지스터 백업 등 호출 프레임을 다룰 때 사용
  6. 레지스터 별로 크기 차이가 다를까?

    대부분의 레지스터는 CPU의 “비트 크기”와 같음. 플래그 레지스터는 상태 표시만 하므로 더 작을 수 있음

  7. 베이스 레지스터 주소 지정방식과 레지스터 간접 주소 지정 방식의 차이. 왜 굳이 더하게 만들었을까?

    1. 연속된 데이터 접근에 최적화. 순서대로 1000, 1004, 10008에 접근해야 한다면
      1. 레지스터 간접 주소 지정 방식은 1000, 1004, 1008을 오퍼랜드 필드에 넣어야함
      2. 베이스 레지스터 주소 지정 방식은 BR에 1000을 넣어두고 오퍼랜드만 +0, +4, +8로 바꿔주면 됨.
      3. 훨씬 짧고 빨라지며 명령어 크기도 줄어든다.
    2. 프로그램의 메모리 주소가 500, 504, 508로 바뀐다면?
      1. 레지스터 간접 주소 지정 방식이면 3개를 다 바꾸어야 함.
      2. 베이스 레지스터 주소 지정 방식이면 베이스 레지스터를 ‘현재 프로그램이 올라간 시작 주소’로 해두면 어느 위치에서든 같은 동작을 하게 됨 ⇒ 위치 독립 코드(Position Independent Code)