레지스터는 무엇이고
어떠한 종류들이 있을까?
레지스터 (Register)
--
레지스터는
CPU 내부에 있는 고속의 소형 저장 장치로,
주로 데이터와 명령어를 일시적으로 저장하는 데 사용된다.
CPU가 명령어를 처리하고 연산을 수행하는 데 필수적인 요소로,
CPU 내부의 데이터 처리를 빠르게 수행할 수 있도록 도와준다.
프로그램 속 명령어와 데이터는 실행 전/후로 반드시 레지스터에 저장된다.
따라서 레지스터에 저장된 값만 잘 관찰해도 해당 프로그램의 실행 흐름을 파악할 수 있다.
CPU 내부에는 다양한 레지스터들이 존재하고 각자 다른 역할을 가지고 있다.
레지스터들은 CPU마다 이름, 크기, 종류가 매우 다양하고,
사용하는 CPU의 제조사 홈페이지나 공식 문서 등에서 사용하는 레지스터들의 정보를 확인할 수 있다.
최소한 알아둬야 할 8가지 레지스터 (다양한 CPU들이 공통으로 포함하고 있는 레지스터)
- 프로그램 카운터 (PC, Program Counter)
- 명령어 레지스터 (IR, Instruction Register)
- 메모리 주소 레지스터 (MAR, Memory Address Register)
- 메모리 버퍼 레지스터 (MBR, Memory Buffer Register)
- 플래그 레지스터 (FR, Flag Register)
- 범용 레지스터 (General-Purpose Registers)
- 스택 포인터 (SP, Stack Pointer)
- 베이스 레지스터 (BP, Base Pointer)
--
프로그램 카운터 (PC, Program Counter)
--
프로그램 카운터는
메모리에서 가져올 명령어의 주소를 저장하는 레지스터로,
다음에 실행할 명령어의 메모리 주소를 저장하는 레지스터다.
이는
명령어를 순차적으로 실행하기 위해 사용되는 레지스터로,
각 명령어가 실행된 후 자동으로 다음 명령어 주소로 업데이트(수정)된다.
즉, 프로그램의 흐름 제어에서 중요한 역할을 하는 레지스터다.
프로그램 카운터를 "명령어 포인터 (IP, Instruction Pointer)"라고도 부르는 CPU가 있다.
--
명령어 레지스터 (IR, Instruction Register)
--
명령어 레지스터는
해석할 명령어를 저장하는 레지스터로,
방금 메모리에서 가져온 명령어를 저장하는 레지스터다.
(= 현재 실행 중인 명령어를 저장한다.)
이는
메모리에서 가져온 명령어가 일시적으로 저장되는 레지스터로,
디코딩(해석) 및 실행 준비를 하는 용도로 사용된다.
제어장치는 "명령어 레지스터"에 저장된 명령어를 가져와서 해석한 뒤에 제어 신호를 전달하게 된다.
--
메모리 주소 레지스터 (MAR, Memory Address Register)
--
메모리 주소 레지스터는
말 그대로 메모리의 주소를 저장하는 레지스터로,
CPU가 읽어 들이고자 하는 메모리의 주소 값을 "주소 버스"로 전달할 때 해당 레지스터를 거치게 된다.
즉, 메모리의 데이터를 읽거나 사용할 때 필요한 해당 메모리의 주소를 저장하는 레지스터로,
CPU가 메모리에 접근할 때, 접근할 메모리의 주소를 해당 레지스터에 저장 후 해당 레지스터를 통해 메모리로 접근하게 된다.
정리
CPU는 하드웨어 설계상 직접 메모리에 접근할 수가 없기 때문에
꼭 레지스터와 같은 중간 매개체를 이용해서 접근해야 한다.
그래서 CPU는 접근해야 할 메모리 주소를 메모리 주소 레지스터에 저장하고
해당 레지스터를 이용하여 메모리에 접근한다.
이해를 위해 비유를 하자면
어머니(CPU)는 가래떡집에 가래떡을 주문해야 한다.
해당 떡집의 전화번호는 알지만 전화기를 사용할 줄 모른다.
그래서 해당 전화번호를 아들(레지스터)에게 알려주고 아들을 통해서 가래떡을 주문시킨다.
위 비유를 다시 해석하면
CPU가 특정 메모리에 접근하고자 할 때 해당 메모리 주소를 메모리 주소 레지스터에 저장하고,
바로 해당 레지스터를 이용하여 메모리에 접근한다.
--
메모리 버퍼 레지스터 (MAR, Memory Address Register)
--
메모리 버퍼 레지스터는
메모리와 주고받을 값(데이터 or 명령어)을 저장하는 레지스터로,
CPU와 메모리 사이에서 데이터를 주고받을 때 사용되는 레지스터다.
이 말은, 메모리에 저장하고 싶은 값이나 메모리로부터 가져올 값은 항상 메모리 버퍼 레지스터를 거지게 된다는 의미로
CPU와 메모리 간의 데이터 전송을 위한 필수적인 중간 매개체(레지스터)다.
"메모리 주소 레지스터"와 "메모리 버퍼 레지스터"
CPU가 어떠한 값을 메모리에 저장하려고 한다.
해당 메모리 주소는
메모리 주소 레지스터에 주소를 저장 후 해당 레지스터를 이용하여 주소 버스로 전달
해당 메모리 값은
메모리 버퍼 레지스터에 값을 저장 후 해당 레지스터를 이용하여 데이터 버스로 전달
--
중간 점검 (흐름 살펴보기)
--
CPU로 실행해야 할 프로그램이 메모리의 0x015 ~ 0x030까지 저장되어 있다.
(여기서 0x015 ~ 0x030 메모리는 데이터가 아닌 명령어가 저장되어 있는 메모리를 가리킨다.)
프로그램은 처음부터 순서대로 수행된다.
1. 프로그램을 처음부터 실행하기 위해 "프로그램 카운터"에 프로그램의 처음 주소를 저장한다.
프로그램 실행 시 초기 "프로그램 카운터"의 값은
하드웨어적(하드웨어에 의해 설정된 위치 or 리셋 백터로부터)으로 자동 설정이 된다.
즉, 메모리 주소 레지스터나 다른 레지스터를 통해 주소를 받아오는 것이 아니다.
2. 0x015 주소에 담긴 값을 가져오기(접근) 위해 먼저 "메모리 주소 레지스터"에 해당 주소를 저장한다.
(주소 버스로 전달하기 위해서)
3. 메모리 읽기를 위한 "제어 신호"와 "메모리 주소 레지스터"의 값을 각 "제어 버스"와 "주소 버스"를 통해 메모리로 전달
아무리 "메모리 주소 레지스터"와 "제어 신호"를 주소 버스, 제어 버스에 동시에 전달했다고 해도
현재 제어 버스로 전달한 제어 신호가 주소 버스로 보낸 정보에 동기화가 되는 것인가?
각 버스로 전달된 정보들은 3가지 요소를 통해 동기화가 이루어진다. (3가지 모두 적용)
동기화와 제어
CPU 내부에서는 명령어 사이클의 각 단계가 "클럭 신호"에 의해 동기화되므로
CPU는 클럭 신호에 맞춰 각 단계를 정확하게 수행하게 된다.
즉, 특정 클럭 주기 동안에 전달(수행)하는 것들은 동기화가 된다.
메모리 컨트롤러
메모리 컨트롤러는 메모리와 CPU 사이의 데이터 흐름을 관리하는 것으로
각 버스를 통해 전달된 정보는 메모리 컨트롤러에 의해 처리된다.
그래서 버스를 통해 전달된 정보들이 연관된 것임을 인지할 수 있다.
명령어 사이클의 순차적 처리
CPU는 명령어 사이클을 순차적으로 처리한다.
순차적 처리라는 것은
CPU가 각 단계에서 필요한 작업을 정확한 순서와 타이밍에 맞춰 수행하도록 보장하는 것이다.
그래서 각 단계는 다음 단계로 자연스럽게 이어지며, 이를 통해 전체 프로세스가 조율된다.
4. 접근한 값은 "데이터 버스"를 통해 "메모리 버퍼 레지스터로 전달된다.
전달 후, "프로그램 카운터"는 증가하여 다음 명령어를 읽어 들일 준비를 한다.
프로그램 카운터는
값(명령어)을 인출(가져오는)하는 단계에서 (메모리 버퍼 레지스터에 저장된 이후)
다음 명령어의 주소를 준비하기 위해 미리 프로그램 카운터의 주소를 증가시킨다.
이때 프로그램 카운터를 증가시키는 이유는
우선 해당 단계에서는 이미 메모리에서 읽어올 데이터가 "메모리 버퍼 레지스터"에 저장되었기 때문에
더는 "프로그램 카운터"에 저장된 주소를 사용할 필요가 없기 때문이다.
이렇게 함으로써 CPU가 명령어의 순차적인 흐름을 유지할 수 있기도 하다.
프로그램 카운터의 증가
일반적으로 "프로그램 카운터"는 고정된 크기(1, 4, 8 byte)만큼 증가된다.
이는 일반적으로 프로그램의 코드(명령어)는 메모리의 연속된 공간에 저장되기 때문이다.
그래서 고정된 크기로 증가시키면 자동으로 다음 메모리의 주소를 가리키게 된다.
다만 아주 예외적으로 명령어 메모리 공간이 비연속적으로 배치되는 경우가 존재한다.
이러한 경우에는 "분기 명령어"를 사용하여 특정 주소로 설정하거나,
상대적인 위치로 이동시켜서 비연속적인 명령어 배치를 처리해야 한다.
5. "메모리 버퍼 레지스터"에 저장된 값은 "명령어 레지스터로 이동하게 된다.
"명령어 레지스터"에 값이 저장되면 "제어장치"는 "명령어 레지스터"에 담긴 명령어를 해석하고 제어 신호를 발생
"메모리 버퍼 레지스터"로 수행해야 할 명령어를 가져왔으면 해당 명령어를 이제 실행시켜야 하므로
지금 수행해야 하는 명령어를 저장하는 "명령어 레지스터"로 전달하게 된다.
그리고 제어장치는 "명령어 레지스터"에 명령어를 수행하기 위해 해석 후 해당 명령어에 알맞은 제어 신호를 발생시킨다.
해당 명령을 모두 수행하고 나면 다시 처음으로 돌아와서 다음 수행해야 하는 명령어를 다시 인출(가져오는)하는 과정부터 다시 반복한다.
해당 과정을 명령어 메모리의 끝까지 반복하고 나면 끝난다.
위의 전체적인 과정은
메모리 중에서 명령어가 저장된 메모리에 접근하여
해당 명령어들을 하나씩 CPU로 가져와서 수행하는 과정을 반복하는 간단한 과정이다.
--
범용 레지스터 (General-Purpose Registers)
--
범용 레지스터는
말 그대로 다양하고 일반적인 상황에서 자유롭게 사용할 수 있는 다목적 레지스터로,
데이터나 주소를 모두 저장할 수 있는 레지스터다.
즉, 어떠한 값이 저장된 공간의 주소를 저장할 수 있고, 피연산자, 연산 결괏값 등 다목적으로 범용성이 좋은 레지스터다.
다목적으로 사용하는 레지스터기 때문에
일반적으로 CPU 안에는 여러 개의 범용 레지스터들이 존재하며
요즘 CPU는 모두 범용 레지스터를 가지고 있다.
--
플래그 레지스터 (FR, Flag Register)
--
플래그 레지스터는
ALU 연산을 통해 나온 결과에 따른 플래그를 저장하는 레지스터로,
연산 결과 상태를 나타내는 플래그 비트를 저장한다.
이는 연산 결과 또는 CPU 상태에 대한 부가적인 정보를 저장하는 것이다.
--
스택 포인터 (SP, Stack Pointer)
--
스택 포인터는
"스택 주소 지정 방식"에서 사용되며,
현재 스택의 최상단(최신) 위치를 가리키는 레지스터다.
스택 주소 지정 방식은
"스택"과 "스택 포인터"를 이용한 주소 지정 방식으로
스택을 활용하여 메모리의 특정 위치에 접근하는 방식이다.
스택은
선입후출(LIFO) 방식이므로 가장 최근에 저장한 값부터 꺼낼 수 있는 구조다.
이때 스택의 최상단을 가리키는 레지스터가 "스택 포인터"다.
위 그림처럼
스택 포인터는 스택 공간에서 항상 최단산 위치를 가리키므로
스택에 몇 개의 데이터가 쌓여있는지도 알 수 있다.
스택 구조는 알겠는데
스택이라는 것은 어디에 있는 것이며, 어떻게 구현하는 것일까?
스택은 일반적으로 메모리 안에 존재한다.
즉, 메모리 공간에 스택처럼 사용할 수 있는 영역이 따로 정해져 있으며,
해당 영역을 "스택 영역"이라고 부르고 스택처럼 사용하게 된다.
중요!!
사실 물리적인 메모리는 따로 "스택용", "힙용" 이렇게 저장 공간이 나눠져 있지 않고
모두 동일한 저장 공간이다.
다만 사람들이 메모리 공간 중에서 특정 공간을 "스택용", 힙용" 이렇게 사용하기로 암묵적으로 약속을 했고,
이 약속한 방식 대로 해당 메모리 공간을 소프트웨어(운영체제, 컴파일러 등)가 제어하여,
해당 메모리 공간을 스택처럼 데이터를 처리하고 관리할 수 있는 것이다.
--
베이스 레지스터 (BP, Base Pointer)
--
베이스 레지스터를 알기 전에
우선 변위 주소 지정 방식 (Displacement Addressing Mode)에 대해서 알아야 한다.
변위 주소 지정 방식은
연산 코드와 오퍼랜드로 이루어져 있는 명령어에서
오퍼랜드의 값(변위 or 즉시 값)과 특정 레지스터의 값(기본 주소)을 더하여 유효 주소를 얻어내는 주소 지정 방식이다.
각 필드의 값
- 레지스터 필드의 값 : 기본 주소로 사용되며, 해당 주소가 메모리의 시작 주소나 특정 영역의 기준이 되는 주소
- 오퍼랜드 필드의 값 : 변위(Offset)로 사용되며, 기본 주소에 더해져 최종적으로 접근할 메모리 주소를 결정
변위(Offset, 오프셋)는
메모리 주소를 계산할 때 사용되는 값을 의미하며
기본 주소로부터 상대적인 위치를 나타내는 값이다.
(기본 주소로부터 얼마나 떨어져 있나)
그래서 "변위 주소 지정 방식"을 사용하는 명령어는 아래와 같은 필드로 구성되어 있다.
여기서 "변위 주소 지정 방식"은
오퍼랜드 필드에 어떤 레지스터(주소)를 더하는지에 따라서
- 상대 주소 지정 방식
- 베이스 레지스터 주소 지정 방식
등으로 나뉘게 된다.
상대 주소 지정 방식 (Relative Addressing Mode)
상대 주소 지정 방식은
오퍼랜드와 "프로그램 카운터"의 값을 더하여 유효 주소를 얻는 방식이다.
베이스 레지스터 주소 지정 방식 (Base-Register Addressing Mode)
베이스 레지스터 주소 지정 방식은
오퍼랜드와 "베이스 레지스터"의 값을 더하여 유효 주소를 얻는 방식이다.
베이스 레지스터는
메모리 주소를 계산하는 데 사용되는 레지스터로
"기준이 되는 주소"를 저장하고 있는 레지스터다.
여기서 기준이 되는 주소는
일반적으로 메모리의 특정 데이터 영역이나 세그먼트의 시작 주소를 의미한다.
이 또한 상대 주소 지정 방식과 동일하지만
레지스터 필드에 어떠한 레지스터를 사용하냐만 다르다.
상대 주소 지정 방식은
프로그램 카운터를 사용하므로 다음에 실행할 명령어의 주소를 기준으로 하고
베이스 레지스터 주소 지정 방식은
베이스 레지스터를 사용하는데 해당 레지스터는
프로그래머 or 프로그램에 의해서 필요한 메모리 주소를 담아서 해당 주소를 기준으로 한다.
즉, 상황에 따라 원하는 주소를 기준 주소로 사용할 수 있다.
--
'CS > 컴퓨터 구조' 카테고리의 다른 글
[CPU 성능 향상] 클럭, 멀티코어, 멀티스레드 (0) | 2024.08.26 |
---|---|
[CPU 작동 원리] 명령어 사이클과 인터럽트 (0) | 2024.08.25 |
[CPU 작동 원리] ALU와 제어장치 (0) | 2024.08.23 |
[명령어] 명령어의 구조 ( 연산 코드, 오퍼랜드, 주소 지정 방식 ) (0) | 2024.08.22 |
[명령어] 고급 언어와 저급 언어 ( 컴파일, 인터프리터 ) (0) | 2024.08.21 |