일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- #MINT64 #Sqix
- Find
- KASAN
- Overwatch League SaberMetrics
- C++11
- #IntelManual #segment Descriptor #세그먼트 디스크립터 #MINT64 #Sqix
- linux
- Network
- libtins
- #Best of the Best #OS #MINT64 #Sqix
- ftz
- Sqix
- 오버워치 세이버메트릭스
- 인터럽트
- #IntelManual
- FTZ 레벨2
- vi 외부 명령어
- 오버워치
- >
- #
- BEST of the BEST
- vi
- libpcap
- #Qt Creator
- command
- vim
- Today
- Total
Sqix
64bit 멀티코어 OS 제작하기 [2] - 1 : 운영 모드와 레지스터 본문
이번 글에서는 운영체제의 다섯 가지 운영 모드(리얼 모드, 보호 모드, IA-32e 모드, 시스템 관리 모드, 가상 8086 모드)와 레지스터, 메모리 관리 기법에 대해서 알아봅니다.
1. 운영 모드
64bit OS가 지원하는 운영 모드는 총 5가지입니다. 여기에는 위에서 말씀드린 리얼 모드, 보호 모드, IA-32e 모드, 시스템 관리 모드, 가상 8086 모드가 있습니다.
우리가 만들 OS에서 필수적으로 지원해야 하는 모드는, 위 5개의 모드들 중 리얼 모드, 보호 모드, IA-32e 모드입니다.
● 리얼 모드
리얼 모드는 프로세스가 처음 동작할 때 진입하는 모드입니다. 어떤 상태에 있는 프로세서건 상관없이 전원이 켜지거나, 혹은 리셋되는 모든 프로세서는 모두 리얼 모드로 진입하게 됩니다.
리얼 모드는 16비트 프로세서와 동일하게 동작하고, 바이오스의 여러 기능들을 사용할 수 있습니다.
Real Mode의 특징
* 사용 가능한 RAM이 1MB 미만입니다.
* 가상 메모리 혹은 GDT가 지원되지 않습니다.
* 보안 메커니즘이 지원되지 않습니다.
* CPU operand 길이가 16bit 이하입니다.
* 메모리 어드레싱 모드가 제한적입니다.
* 64kb 이상의 메모리에 접근하려면 세그먼트 레지스터를 이용하여 복잡한 작업을 수행해야 합니다.
* 디바이스 드라이버를 제작하지 않아도 됩니다.
* 레지스터 크기가 작기 때문에 메모리 엑세스가 빠르게 이루어집니다.
* Low Level API를 지원합니다.
● 보호 모드
리얼 모드에서 64비트 모드(IA-32e)로 전환하기 위해서 거쳐가야 하는 모드입니다. 각 최대 4GB의 지정 가능한 메모리를 가진 여러 가상 주소 공간을 사용할 수 있고, 현재 OS의 필수 기능이라고 할 수 있는 멀티태스킹, 보안, 세그멘테이션, 페이징 기능을 하드웨어적으로 지원합니다. Real Mode에서만 BIOS 인터럽트가 작동하기 때문에, 보호 모드에서는 대부분의 BIOS 인터럽트를 사용할 수 없게 됩니다.
● IA-32e 모드
IA-32e 모드는 32비트 호환 모드와 64비트 모드로 나뉘어집니다. 우리는 64비트 모드의 OS를 개발하기 때문에, 주로 64비트 모드에 대해서 살펴보게 될 것입니다.
※ 운영 모드 사이의 관계와 운영 모드 간 전환
자세한 전환 과정은 각각의 코드를 작성하면서 보다 자세하게 다루게 될 것이니, 여기서는 각 모드별로 전환을 할 수 있는 경우에 대해서만 다룹니다.
[가상 8086 모드]
EFLAG REG ↑↑ || EFLAG REG
VM 비트를 1로 || || VM 비트를 0으로
설정 || ↓↓ 설정
[ 보호 모드 ]
CR0 REG의 CR0 REG의 PG 비트 1로 설정
PE 비트를 1로 설정 CR4 REG의 PAE 비트 1로 설정
IA32_EFER MSR REG의 LME 비트를 1로 설정
↗↙ ↖↘
CR0 REG의 IA32_EFER MSR 레지스터의
PE 비트를 0으로 설정 LME 비트를 0으로 설정
RESET
[ 전원 ] -> [ 리얼 모드 ] < R E S E T - - - - [IA-32e 모드]
====================================================================================================================
↑↑ ||
SMI 인터럽트 발생 || || 인터럽트 핸들링 완료
|| ↓↓
[시스템 관리 모드]
2. 운영 모드와 레지스터
● 범용 레지스터
범용 레지스터는 32비트, 64비트에 모두 있으며, 기본적으로 8개의 레지스터를 공통적인 용도로 가지고 있고, 64비트(IA-32e) 모드에서는 추가적으로 R8~R15의 레지스터를 가지고 있습니다. 32비트에서는 앞에 E를, 64비트에서는 앞에 R을 붙여 구분하고, 16비트에서는 아무런 접두사가 붙지 않습니다.
기본적으로 가지고 있는 레지스터들에 대해 알아봅시다.
AX : 산술 연산을 수행할 때 누산기로 이용.
BX : 데이터의 주소를 저장할 때 포인터로 이용.
CX : 루프 혹은 문자열의 카운터로 이용.
DX : I/O의 주소를 지정할 때 사용되며, 산술 연산 수행 시 보조 레지스터로 이용.
SI : 문자열에 관련된 작업을 수행하게 될 경우, Source String의 Index로 이용.
DI : 문자열에 관련된 작업을 수행하게 될 경우, Destination String의 Index로 이용.
SP : 스택 포인터(Stack Pointer)
BP : 스택에서 데이터에 접근할 때, 데이터의 베이스 포인터로 이용(Base Pointer).
위 레지스터들의 접두사로 E를 붙이게 되면 보호 모드, R을 붙이게 되면 IA-32e 모드에서 이용됩니다.
또한, IA-32e 모드에서 추가된 R8~R15 레지스터는 필요 상황에 따라 다양하게 이용할 수 있습니다.
레지스터가 각 운영 모드와 관련이 있다고 하지만, 그렇다고 해서 모든 운영 모드에 따라 레지스터가 별개로 존재하는 것은 아닙니다. 이렇게 된다면 운영 모드의 개수 * 모든 레지스터의 개수만큼 레지스터가 있어야 하는데, 이는 비효율적입니다.
그래서 범용 레지스터는 가장 큰 사이즈의 레지스터를 기준으로 이를 공유해서 사용합니다. 가령 IA-32e 레지스터 중 RAX가 있다고 하면 여기에서 EAX로 사용되는 경우 RAX의 절반 사이즈를 EAX로 사용하게 됩니다.
한가지 특이사항이 더 있는데, IA-32e모드의 기본 오퍼랜드 크기는 32비트, 기본 어드레스 크기는 64비트로 설계되어 있습니다. 따라서 RIP의 기본 어드레스는 64비트 주소를 표현할 수 없기 때문에 새로운 표현 방식이 필요하게 되었습니다. 그것이 바로 RIP 상대 주소라는 새로운 방식입니다.
기본 오퍼랜드 사이즈만을 이용한다면, 32비트이기 때문에 위,아래로 2GB 단위밖에 표현할 수 없습니다. 따라서 프로세서 제조사에서는 jmp 명령어에 예외를 두어서 분기 명령 시에는 오퍼랜드 사이즈를 64비트로 하여 전체 어드레스 범위에서 이동할 수 있도록 하였습니다.
● 세그먼트 레지스터
세그먼트 레지스터는 주소 영역을 다양하게 구분하는 역할을 합니다. 크기는 16비트로, CS, DS, SS, ES, FS, GS 총 6개로 구성됩니다. 운영 모드마다 세그먼트 레지스터의 역할은 조금씩 차이가 있는데, 리얼 모드(16bit)에서는 고정 크기의 주소 영역을 지정하는 역할만 하고, 보호 모드(32bit)와 IA-32e(64bit)에서는 접근 권한, 세그먼트의 시작 어드레스와 크기를 지정하는데 사용됩니다. 이를 통해 커널 영역을 보호하는 기능을 구현할 수 있습니다.
각 세그먼트의 역할은 다음과 같습니다.
- CS : 코드 영역을 가리키는 레지스터로, jmp나 int 관련 명령으로만 변경이 가능합니다.
- DS : 데이터 영역을 가리키는 레지스터로, 데이터 이동 명령으로 값을 변경할 수 있으며 데이터 영역에 접근할 때 임시로 사용됩니다.
- ES : 데이터 영역을 가리키는 레지스터로, 데이터 이동 명령으로 값을 변경할 수 있으며 문자열과 관련된 작업을 처리할 때 임시로 사용됩니다.
- FS : 데이터 영역을 가리키는 레지스터로, 데이터 이동 명령으로 값을 변경할 수 있습니다.
- GS : 데이터 영역을 가리키는 레지스터로, 데이터 이동 명령으로 값을 변경할 수 있습니다.
- SS : 스택 영역을 가리키는 레지스러로, 데이터 이동 명령으로 값을 변경할 수 있으며 SP, BP 레지스터를 통해 스택 접근을 할 시 임시로 사용됩니다.
● 컨트롤 레지스터
컨트롤 레지스터는 운영 모드를 바꾸고 기능을 제어하는 레지스터입니다. x86에서는 CR0 ~ CR4까지 5개의 레지스터가, x86_64에서는 CR5가 추가되어 총 6개의 컨트롤 레지스터가 존재합니다.
각 레지스터의 역할은 다음과 같습니다.
-CR0 : 운영모드를 제어하는 레지스터로, 리얼모드 <-> 보호 모드 간 전환하는 역할과 캐시, 페이징 기능 등을 활성화시킵니다.
-CR1 : 프로세서에 의해 예약되는 레지스터
-CR2 : 페이지 폴트 발생 시 발생한 선형(논리) 주소가 저장되는 레지스터
-CR3 : 페이지 디렉토리의 물리 주소와 캐시에 관련된 기능을 설정하는 레지스터
-CR4 : 프로세스에서 지원하는 확장 기능을 제어하는 레지스터로, 페이지 크기를 늘리거나 메모리 영역을 확장시키는데 사용됩니다.
-CR8 : Task 우선순위에 있는 레지스터의 값을 제어하는 레지스터로, 외부 인터럽트를 걸러주는 역할을 합니다. IA-32e 모드에서만 접근이 가능합니다.
각 레지스터들의 구조는 다음과 같습니다.
(출처 : http://egloos.zum.com/miooim/v/48142)
다음 글에서는 메모리 관리 기법에 대해서 알아보겠습니다.
'MINT64 OS ' 카테고리의 다른 글
64bit 멀티코어 OS 제작하기 [3] - 3 : 부트로더 화면 제어 (0) | 2018.05.14 |
---|---|
64bit 멀티코어 OS 제작하기 [3] - 2 : 가장 기초적인 부트 로더 제작 (0) | 2018.05.14 |
64bit 멀티코어 OS 제작하기 [3] - 1 : 부트로더와 makefile (0) | 2018.05.14 |
64bit 멀티코어 OS 제작하기 [2] - 2 : 메모리 관리 기법 (0) | 2018.05.10 |
64bit 멀티코어 OS 제작하기 [1] : 환경 설정 (0) | 2018.05.07 |