본문 바로가기
CS 공부

컴퓨터 구조 개요와 CPU

by 나노다 2025. 1. 5.

컴퓨터가 이해하는 정보

컴퓨터는 크게 데이터와 명령어 두 가지를 이해하며 작동한다!! 

우리가 고급 언어로 코드를 짜면 이를 컴파일 또는 인터프리트하여 저급 언어로 변환하고,

이해한 코드를 바탕으로 작동하게 된다!!

고급 언어
우리가 이해할 수 있는 형태로 작성된 프로그래밍 언어들, C언어, JAVA, Python 등등
저급 언어
컴퓨터가 이해할 수 있는 형태의, 즉 0과 1의 이진 데이터를 바탕으로 쓰인 언어들, 기계어와 어셈블리어

1) 데이터

숫자, 문자, 이미지, 동영상 같은 정적인 정보

컴퓨터와 주고받는 정보 또는 컴퓨터 내부에 저장된 정보 등을 통칭

2) 명령어

컴퓨터를 실질적으로 움직이는 정보, 데이터는 명령어를 위한 일종의 재료인 셈이다!!

크게 연산 코드와 오퍼랜드로 구성된다!!

2-1) 연산 코드와 오퍼랜드

연산 코드 Opcode

수행할 연산이 담긴 부분, 연산자라 부르기도 함?!

연산 코드는 CPU마다 종류와 생김새가 다르지만, 일반적으로 아래 네 개가 대표적

  • 데이터 전송 : MOVE, STORE, LOAD(=FETCH), PUSH, POP 등등
  • 산술/논리 연산 : ADD, SUBTRACT, MULTIPLY, DIVIDE, INCREMENT, DECREMENT, AND, OR, NOT, COMPARE
  • 제어흐름 변경 : JUMP, CONDITIONAL JUMP, HALT, CALL, RETURN 등등
  • 입출력 제어 : READ(=INPUT), WRITE(=OUTPUT), START IO, TEST IO
JUMP와 CONDITIONAL JUMP
둘다 특정 주소로 실행 순서를 옮기라는 연산 코드지만, 후자는 특정 조건에 부합할 때 실행된다는 차이가 있다!!

 

오퍼랜드 Operand

연산에 사용될 데이터 또는 그 데이터가 저장된 위치(=유효 주소)가 담긴 부분, 피연산자라 부르기도 함?!

오퍼랜드는 아예 없을 수도 있고, 여러 개 있을 수도 있음

명령어 내에서 표현할 수 있는 데이터의 크기가 제한되기 때문에, 데이터 자체를 오퍼랜드에 담는 것이 녹록치 않음

때문에 오퍼랜드엔 유효 주소를 더 자주 보관하게 되고, 이를 주소필드라 부르기도 함

2-2) 명령어 주소 지정 방식

CPU가 명령어를 보고 연산에 사용될 데이터가 저장된 위치(=유효주소)를 찾는 방법들

 

즉시 주소 지정 방식 immediate addressing mode

  • 연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시
  • 명령어의 총 크기가 제한되기 때문에 데이터의 크기도 널널하진 않지만, 가장 연산이 빠름

직접 주소 지정 방식 direct addressing mode

  • 유효 주소를 오퍼랜드 필드에 직접적으로 명시 

간접 주소 지정 방식 indirect addressing mode

  • 유효 주소의 주소를 오퍼랜드 필드에 명시
  • 오퍼랜드에서 유효 주소의 주소 확인 -> 메모리에서 유효 주소 확인 -> 메모리에서 연산에 필요한 데이터 확인
  • 메모리 탐색 과정이 늘어나 연산 속도가 느린 편

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

  • 데이터가 저장된 레지스터를 오퍼랜드 필드에 명시
  • CPU는 메모리에 접근하는 것보다 레지스터에 접근하는 속도가 훨배 빠름 (바지 주머니 <-> 가방)

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

  • 레지스터에 데이터의 유효 주소를 저장하고, 그 레지스터를 오퍼랜드 필드에 명시

스택 주소 지정 방식

  • 스택 포인터의 정보를 바탕으로 스택에 대한 유효 주소를 찾는 방식

변위 주소 지정 방식

오퍼랜드 필드의 값(=변위)과 특정 레지스터의 값을 더해 유효 주소를 얻는 방식

대개 프로그램 카운터 또는 베이스 레지스터의 값을 더함

  • 상대 주소 지정 방식 : 변위와 프로그램 카운터의 값을 더해 유효 주소를 얻음, 예를 들어 변위가 -3이라면, 프로그램 카운터의 주소의 3번지 이전을 유효 주소로 지정
  • 베이스 레지스터 주소 지정 방식 : 변위와 베이스 레지스터의 값(=기준 주소)을 더해 유효 주소를 얻음, 예를 들어 변위가 100이면, 기준 주소로부터 100번지 떨어진 주소를 유효 주소로 지정

컴퓨터의 네 가지 핵심 부품

  • CPU : 곧곧 자세히 알아보자!
  • 주기억장치(메모리) : ROM, RAM(일반적으로 메모리라 하면 RAM을 가리킴)
  • 보조기억장치 : USB, SD카드, CD-ROM, HDD, SSD 등등
  • 입출력장치 : 키보드, 마우스, 마이크, 스피커, 모니터, 등등

이 핵심 부품들은 메인보드(=마더보드)에 모여있고, 시스템 버스를 통해 서로 연결됨

시스템 버스
버스는 정보를 주고 받는 통로를 의미함!! 버스 중에서도 시스템 버스는 컴퓨터의 척추같은 존재!!

CPU

Central Processing Unit

메모리에 저장된 명령어를 읽어 들이고, 해석하고, 실행하는 부품 (=컴퓨터의 두뇌)

정말 복잡하고 다양한 부품이 있지만, 대표격인 ALU와 제어장치, 레지스터를 알아보도록 하자!!

1) 산술논리연산장치 ALU

Arithmetic and Logical Unit 산술 연산과 논리 연산을 하는 계산기

계산을 위한 정보로 레지스터로부터 피연산자를 받고, 제어장치로부터 제어신호를 받음

계산의 결과 값을 레지스터로 내보내고, 플래그를 플래그 레지스터란 특수 레지스터로 내보냄

가산기, 보수기, shifter, 오버플로우 검출기 등등의 회로가 있음

플래그 flag

연산 결과에 대한 부가 정보들

  • 부호 플래그 : 연산 결과가 음수면 1로, 양수면 0으로 표현
  • 제로 플래그 : 연산 결과가 0이면 1로, 0이 아니면 0으로 표현
  • 캐리 플래그 : 연산 중 올림수나 빌림수가 발생했다면 1로, 발생하지 않았다면 0으로 표현
  • 오버플로우 플래그 : 연산 결과로 오버플로우가 발생했다면 1로, 발생하지 않았다면 0으로 표현
  • 인터럽트 플래그 : 인터럽트가 가능하다면 1로, 불가능하다면 0으로 표현
  • 슈퍼바이저 플래그 : 커널 모드로 실행 중이라면 1로, 사용자 모드로 실행 중이라면 0으로 표현
오버플로우 overflow
연산 결과의 크기가 저장할 레지스터의 크기보다 큰 경우
인터럽트 interupt
CPU가 명령어를 처리하는 정해진 흐름(=명령어 사이클)을 방해하는 신호
CPU가 꼭 주목해야하는 상황일 때, 즉 우선적으로 처리해야 할 다른 작업이 생겼을 때 발생
동기 인터럽트 (=예외 execption)
CPU가 예기치 못한 상황을 접했을 때, 유효 주소에 도달했는데 원하는 값이 없다든지, 디버깅을 한다든지, 실행할 수 없는 명령어가 있다든지 등등. 폴트, 트랩, 중단, 소프트웨어 인터럽트 등이 있음
비동기 인터럽트 (=하드웨어 인터럽트)
주로 입출력장치에 의해 발생, 문제라기보단 알림과 같은 역할, 예를 들어 프린터가 입출력 작업을 완료한 경우 CPU에 알려주는 것, 키보드를 누르거나 마우스를 클릭하거나 등의 입력이 들어온 경우 등등, 일반적으로 입출력 장치의 작업은 CPU보다 느림. 이에 CPU가 마냥 기다리거나 작업 완료를 매번 체크하는 건 비효율적이기 때문에, 다른 작업을 처리하고 있다가 인터럽트를 통해 입출력 장치의 작업 완료를 확인

2) 제어장치 Control Unit

제어 신호를 발생시키고, 명령어를 해석하는 장치

제어 신호

컴퓨터 부품들을 관리하고 작동시키기 위한 전기 신호, 대표적으로 읽기와 쓰기 신호가 있음

  • 메모리 읽기 신호 : CPU가 메모리에 저장된 값을 읽고 싶을 때 메모리에게 보내는 신호
  • 메모리 쓰기 신호 : CPU가 메모리에 값을 저장하고 싶을 때 메모리에게 보내는 신호

2-1) 제어 장치가 받는 정보

명령어 레지스터란 특수 레지스터에게 해석할 명령어를 받고,

플래그 레지스터에게 플래그를 받아 명령어를 올바르게 해석

제어 버스로부터 주변 장치가 보낸 제어 신호를 받음 

마더보드의 클럭 생성기 clock generator로부터 클럭 신호도 받음!!

클럭 신호 clock
컴퓨터의 모든 부품을 일정 박자(=클럭 주기)에 맞춰 움직일 수 있게 하는 시간 단위

2-2) 제어 장치가 내보내는 정보

CPU 내부에 전달하는 신호와 외부에 전달하는 신호가 있다!!

전자는 레지스터에게 레지스터의 다음 행동을 지시하는 제어 신호와 (값을 이동시켜라, 저장해라 등등)

ALU에게 수행할 연산을 지시하는 제어 신호가 있고 (더해라, 빼라, 비교해라 등등),

후자는 메모리와 입출력 장치에게 메모리나 장치를 읽어라, 써라, 테스트해라 등등의 지시를 하는 제어 신호가 있다!!

3) 레지스터 Register

CPU 내부에 있는 임시 저장 장치

프로그램 속 명령어와 데이터는 실행 전후로 레지스터에 저장됨

하나의 CPU엔 다양한 레지스터가 있고, 각각의 역할이 다름

프로그램 카운터

메모리에서 다음으로 읽어들일 명령어의 주소를 저장함 (=명령어 포인터 Instruction Pointer)

일반적으론 프로그램 카운터의 값이 증가함에 따라 프로그램이 순차적으로 실행될 수 있게 되는데, 특정 메모리 주소로 실행 흐름을 이동하는 명령어를 실행 하거나, 인터럽트가 발생할 경우엔 이 순서가 깨짐

메모리 주소 레지스터

읽어들일 메모리의 주소를 저장함, CPU가 읽어 들이려는 주소를 주소 버스로 보내기 전 거침

메모리 버퍼 레지스터

메모리와 주고 받을 데이터와 명령어를 저장함, CPU가 정보를 데이터 버스로 주고받을 때 거침

명령어 레지스터

방금 메모리에서 읽어 들인 명령어를 저장함, 얘를 제어장치가 해석함

플래그 레지스터

연산 결과 또는 CPU 상태에 대한 부가적인 정보를 저장

범용 레지스터

다양하고 일반적인 상황에서 자유롭게 사용

보통 여러 개 존재하고, 주소, 데이터, 명령어 등등 다양한 값을 담을 수 있음

스택 포인터

스택이 어디까지 차 있는지에 대한 표시를 저장(=스택의 꼭대기를 가리키는 정보)

스택은 메모리 내부에 스택을 위해 미리 내정된 스택 영역에 저장됨

베이스 레지스터

주소 지정에서 활용할 기준 주소를 저장


명령어 사이클

프로그램 속 명령어들이 반복 실행되는 일정한 주기

일반적으로 인출과 실행 사이클이 반복됨

  • 인출 사이클 : 메모리에 저장된 값을 CPU 내부로 가져오는 사이클
  • 실행 사이클 : 가져온 값을 실행하는 사이클
  • 간접 사이클 : 인출 이후 메모리 접근이 더 필요한 경우 실행되는 사이클 (간접 주소 지정 방식 등등)
  • 인터럽트 사이클 : 실행 사이클 후 인터럽트 요청이 있다면 실행되는 사이클

CPU의 성능을 향상시키기 위한 방법

1) 클럭 신호

컴퓨터 부품들은 클럭 신호에 맞춰 움직이고, CPU는 명령어 사이클에 맞춰 명령어들을 실행

클럭 주기가 빠르게 반복되면 그만큼 컴퓨터 작동이 빨라짐

클럭 속도는 헤르츠 단위(=Hz)로 측정, 헤르츠는 1초에 클럭이 반복되는 횟수

하지만 필요 이상으로 클럭을 높이면 발열 및 안정성 문제 관리가 필요해짐(=오버클러킹 overclocking)

2) 코어 수

코어 : 명령어를 실행하는 부품

전통적으론 CPU 자체가 명령어를 실행하는 부품이었으나, 오늘날의 CPU엔 이 역할을 하는 부품이

여러 개 존재할 수 있게 됐고, 이것들을 코어라 부르며, 코어가 여러 개인 CPU를 멀티코어 프로세서라 함!!

다만 꼭 코어 수에 비례해 처리 속도가 빨라지진 않음!! 사람이 많다고 조별 과제가 잘 끝나진 않지요?!

처리해야할 작업량이 코어 별로 적절히 분배되지 않는 등등의 문제가 있다!!

3) 스레드 수

스레드 : 실행 흐름의 단위

3-1) 하드웨어적 스레드

하나의 코어가 동시에 처리하는 명령어의 단위

하나의 코어가 여러 명령어를 수행할 수 있는 CPU라면 멀티 스레드 프로세서라 부름!!

두개 코어가 각각 두개씩 명령어를 수행할 수 있다면 2코어 4스레드 CPU

하나의 명령어를 수행하기 위한 레지스터의 세트 보유 수를 스레드 수로 여김

3-2) 소프트웨어적 스레드

하나의 프로그램에서 독립적으로 실행되는 흐름 단위

1코어 1스레드 CPU도 소프트웨어적으론 멀티 스레드가 가능!! 때문에 두 개념을 분리하는 것이 좋음!!

4) 명령어 병렬 처리 기법

하나의 명령어가 처리되는 절차를 명령어 인출 - 명령어 해석 - 명령어 실행 - 결과 저장이라 가정!!

4-1) 명령어 파이프라인

CPU가 여러 명령어들을 겹쳐 동시에 실행하는 것

 

파이프라인 위험 Pipeline Hazard

  • 데이터 위험 : 명령어 간에 의존성이 있어서, 단순히 병렬로 처리가 어려운 상황, 명령어 A가 완료돼야만 명령어 B를 실행할 수 있는 경우
  • 제어 위험 : 프로그램 카운터가 갑작스레 변해버려 성능 향상에 실패하는 경우, JUMP 등 실행 흐름이 바뀌어 순차적인 파이프라인 구조가 무너지는 경우
  • 구조적 위험 : 서로 다른 명령어가 같은 CPU 부품에 접근하려 하는 경우

4-2) 슈퍼 스칼라

CPU 내부에서 여러 개의 명령어 파이프라인을 운영하는 구조, 멀티 스레드 프로세서에서 가능

이론적으론 파이프라인 개수에 비례해 CPU 성능이 증가하지만,

파이프라인 위험도도 함께 증가하기 때문에, 실질적으론 완전 비례하진 않음

4-3) 비순차적 명령어 처리

파이프라인의 중단을 방지하기 위해 명령어를 합법적으로 새치기시키는 병렬 처리 기법

다른 명령어에 의존성을 갖는 명령어를 뒤로 미루고, 독립적인 명령어를 파이프라인에서 우선적으로 처리

전체 프로그램 실행 흐름에는 영향이 없는 순서 변경만 가능하다!!