혼공컴운

[혼공컴운] 4장. CPU의 작동 원리

게으른 the lazy 2024. 7. 14. 16:19

https://namu.wiki/w/CPU

4. CPU의 작동 원리

  • CPU의 작동 원리에 대해서는 이미 1장에서 살펴보았지만,
  • 이번 4장에서 보다 자세히 알아본다.
  • 좀 어렵다.
  • 안전띠 꽉 매라고, 친구들.

4.1 ALU와 제어장치


4.1.1 ALU

  • ALU는 이렇게 생겼다.

출처: https://huimang2.github.io/etc/computer-architecture

  • 인터넷에서 ALU를 찾아보면 많은 그림들이 나오는데,

  • 이 그림이 책의 그림과 가장 비슷해보인다.

  • 레지스터로부터 피연산자(오퍼랜드)를,

  • 제어장치로부터 제어신호를 받아서,

  • 무언가 연산한 후에,

  • 상태 플래그를 상태 레지스터로,

  • 연산 결과를 누산기로 보낸다.

  • 상태 플래그는 아래의 정보들을 담고 있다.

    1. 부호 플래그: 연산 결과가 양수인지 음수인지?
    2. 제로 플래그: 연산 결과가 0인지 아닌지?
    3. 캐리 플래그: 연산 중 올림수나 빌림수가 발생했는지?
    4. 오버플로수 플래그: 오버플로우가 발생했는지?
    5. 인터럽트 플래그: 작업 도중 인터럽트가 발생했는지?
    6. 슈퍼바이저 플래그: 커널 모드인지 사용자 모드인지?

4.1.2 제어장치

  • 1장에서 제어장치를 사람의 팔에 비유했었는데,

  • 이번 절을 읽어보면 중추 신경계로 보는 것이 더 맞을 것 같다.

  • 뭐 그냥 다 한다.

  • 제어장치가 받아들이는 정보

    1. 클럭 신호: 작업을 수행하는 최소 시간 단위이다. 4.2 GHz니 하는 것들이다. 이 시간 단위에 맞춰서 일을 한다.
    2. 명령어: 명령어 레지스터로부터 명령어를 받는다. 이 명령어를 해석하고 제어 신호를 발생시켜 다시 여기저기 일을 시킨다.
    3. 플래그: 플래그 레지스터로부터 플래그 값을 받는다.
    4. 제어 신호: 제어버스로부터 제어 신호를 받는다.
  • 제어장치가 보내는 신호

    1. CPU 내부 부품인 레지스터와 ALU로 보내는 신호도 있고,
    2. CPU 외부 부품인 메모리와 입출력 장치에 보내는 신호도 있다.

4.2 레지스터

  • CPU는 하나의 부품이 아니라 ALU, 제어장치, 레지스터의 조합이다.
  • 이 중 레지스터는 CPU가 작업할 정보를 담고 있는 공간이다.
  • 레지스터는 사실 종류가 꽤 많다.
  • 각각의 역할이 있다.

출처: https://foxtrotin.tistory.com/144

  1. 프로그램 카운터
    • 메모리에서 읽을 명령어의 주소가 담겨있다.
    • 기본적으로 메모리에서 순차적으로 명령어를 가져오므로,
    • 한 번 가져올 때마다 일정한 값이 증가하는데,
    • 때에 따라서는 건너뛰기도 한다.
    • 자세한 내용은 뒤에서 살펴본다.
  2. 명령어 레지스터
    • 프로그램 카운터가 갖고 있던 주소에서 가져온 명령어를 여기에 저장한다.
    • 이 명령어를 해석해서 제어 신호를 내보낸다.
  3. 메모리 주소 레지스터
    • CPU가 읽을 주소를 주소 버스로 보낼 때 여기를 거친다.
  4. 메모리 버퍼 레지스터
    • 메모리와 주고받을 값, 즉 데이터와 명령어를 저장하는 레지스터이다.
    • 데이터 버스로 주고받은 값은 여기를 거친다.
  • 이쯤에서 1장에서 소개한 영상을 한번 더 보면 도움이 될 것이다.
  • 12분쯤부터 보면 된다.

  • 아직 안 끝났다.
  1. 범용 레지스터
    • 이름이 역할을 담고 있다.
    • 다용도실이다.
    • 현대의 대부분 CPU는 범용 레지스터를 갖고 있다고 한다.
  2. 플래그 레지스터
    • 앞에서 말했다.
  • 이제 끝났다.

4.2.1 주소 지정 방식

  • 3장에서 주소를 지정하는 여러 방식에 대해 말했는데,
  • 레지스터를 이용해서도 주소를 지정할 수 있다.
  • 좀 특별한 방식들이다.

  • 스택 주소 지정 방식

    • 스택 포인터는 메모리의 스택영역의 맨 위를 가리키는 레지스터이다.
    • 스택은 책을 쌓는 것과 같다. 가장 위의 데이터만 접근할 수 있다.
  • 변위 주소 지정 방식

    • 이 방식에서는 명령어가 연산코드, 레지스터 주소, 오퍼랜드로 구성되는데,
    • 여기서 오퍼랜드는 "레지스터에 담긴 주소에서 어디로 몇 칸 떨어진 데이터를 읽을지"를 지정한다.
    • 여기서 레지스터는 프로그램 카운터일 수도 있고
    • 베이스 레지스터라는 또 다른 레지스터일 수도 있다.
    • 프로그램 카운터와 베이스 레지스터의 차이가 궁금해졌다.
    • 프로그램 카운터는 한 번 명령어를 읽은 후에 증가하고,
    • 베이스 레지스터는 증가하지 않는 것일까?

4.2.2 확인 문제

  1. 연산 결과 혹은 CPU 상태에 대한 부가 정보를 저장하는 레지스터는?
    • 플래그 레지스터
  2. 메모리에서 가져올 명령어의 주소를 저장하는 레지스터는?
    • 프로그램 카운터
  3. 데이터와 주소를 모두 저장할 수 있는 레지스터는?
    • 범용 레지스터
  4. 해석할 명령어를 저장하는 레지스터는?
    • 명령어 레지스터

4.3 명령어 사이클과 인터럽트

  • 명령어 사이클은 다소 추상화된 개념이다.
  • CPU가 하는 일은 크게 3단계이다: 읽고, 실행한다.
  • 이 과정을 명령어 사이클이라고 부른다.
  • 사람으로 치자면,
    • 메일을 읽고, 지시사항을 수행한다.
    • 공문을 읽고, 자료를 만든다.
    • 상사에게 업무지시를 받고, 문서를 작성한다.
  • 그런데 이 일들은 동시에 일어날 수 있다.
    • 메일을 읽고 있는데 상사가 부른다면?
    • 자료를 만들고 있는데 메일이 왔다면?
    • 지시사항을 수행하려는데 새로운 공문이 왔다면?
  • 방해공작이 들어왔다. 즉 인터럽트가 들어왔다.
  • "아 모르겠고 난 무조건 먼저 하던 걸 할거임"이라고 할 수도 있겠지만,
  • 만약 나중에 들어온 일이 더 중요하고 시급한 일이라면?
  • 효율적인 스케쥴링이 필요하다.

  • 인터럽트는 두 종류가 있다.

  • 동기 인터럽트synchronous interrupt

    • CPU가 발생시키는 인터럽트
    • 명령어를 수행하다가 예상치 못한 상황에 마주쳤을 때
    • 프로그래밍 상의 오류 등에 의해 발생
    • 코딩 중 "예외"라고 부르는 것이 여기에 해당됨
  • 비동기 인터럽트asynchronous interrupt

    • 주로 입출력장치에 의해 발생하는 인터럽트
    • 키보드, 마우스로부터 어떤 입력이 들어왔을 때
    • 프린터가 작업을 완료했음을 알릴 때 등
    • 주로 하드웨어에 의해 발생하여, 하드웨어 인터럽트라고도 부름
  • 하드웨어 인터럽트 처리 순서는 다음과 같다.

    1. 입출력장치가 CPU에 인터럽트 요청 신호를 보냄
    2. CPU가 실행 사이클 종료 후 인터럽트 여부를 확인
    3. 인터럽트 요청이 왔다면, 인터럽트 플래그를 통해 인터럽트를 받아도 되는 상황인지 확인
    4. 인터럽트를 받을 수 있는 상황이라면 CPU가 하던 일을 백업
    5. CPU가 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행
    6. 인터럽트 서비스 루틴 실행이 끝나면 4의 백업을 가져와서 작업 재개
  • 3에서 인터럽트를 받아도 되는 상황인지를 판단한다고 했는데,

  • 경우에 따라서는 인터럽트가 들어와도 무시할 수 있다.

    1. CPU가 임계 구역에 진입했을 때, 데이터 불일치 방지를 위해 인터럽트 무시
      • 임계 구역critical section이란 여러 개의 스레드나 프로세스가 공유 자원에 동시에 접근할 수 있는 코드 영역
      • 이 구역은 하나의 스레드/프로세스만 실행되어야 하므로 인터럽트를 무시할 수 있음
      • 이라고 윤쌤이 알려줬음
    2. 하드웨어 장치 관리 중일 때
    3. 운영체제의 핵심 프로세스가 실행되는 동안
    4. 디바이스 드라이버가 하드웨어와 직접 상호작용하는 동안
    5. 메모리 할당, 해제 등의 메모리 관리 작업 중일 때
  • CPU가 인터럽트를 받아들이기로 했다면 인터럽트를 처리하기 위한 프로그램을 실행한다.

  • 이것을 인터럽트 서비스 루틴이라고 부른다.

출처: https://blog.skby.net/인터럽트-interrupt/

  • 인터럽트 벡터란 인터럽트 서비스 루틴을 식별하기 위한 정보이다.