시스템 디스크립터, System Descriptor 



세그먼트 디스크립터의 S 비트가 클리어 ( 0 ) 되어 있다면, 해당 디스크립터가 가리키는 세그먼트는 시스템 디스크립터다. 그렇다면 시스템 디스크립터는 무엇인가? Intel 문서에서는 다음과 같이 정의한다

 - LDT 세그먼트 디스크립터

 - TSS 디스크립터

 - Call - Gate 디스크립터

 - Interrupt - Gate 디스크립터

 - Trap - Gate 디스크립터

 - Task - Gate 디스크립터


이렇게 6가지다. 시스템 디스크립터에 대한 인텔의 설명은 아래와 같다.




해석하자면, " 시스템 디스크립터 타입은 두가지 종류로 나뉜다. 하나는 시스템 세그먼트를 가리키고 있는 시스템 세그먼트 디스크립터 (System Segment Descriptor)고, 다른 하나는 코드 세그먼트 내부에 존재하는 프로시저들을 가리키는 포인터들을 가지고 있거나, TSS의 세그먼트 셀렉터를 가리키고 있는 게이트 디스크립터(Gate Descriptor)로 나뉜다. "


위 표는, 타입 비트에 따른 시스템 세그먼트의 내용이 무엇을 의미하는지를 알려준다.

이제까지 우리는 논리 주소 변환 과정인 세그먼테이션에서 사용되는 디스크립터 테이블에 대해서 알아 보았다. 그렇다면 이제까지 우리가 알아 본 세그먼트 디스크립터는 어디에 존재할까?  




세그먼트 디스크립터 테이블, Segment Descriptor Table 이다.




세그먼트 디스크립터는, 세그먼트 디스크립터 테이블에 존재하며, 세그먼트 디스크립터 테이블은 GDTR, LDTR 레지스터가 각각 가리키고 있다.

간단하게 설명하자면, 각각의 내용은 테이블에 담겨 있으며, 해당 테이블은 프로세서에서 그 테이블만 가리키기 위해서 설정 해 놓은 레지스터가 가리키고 있는 것이다.

디스크립터 테이블에 대해서 알아보기 전에, 시스템에서 Memory - Management 를 위해서 사용하는 레지스터에 대해서 알아보자.






MEMORY - MANAGEMENT REGISTERs for GDT, LDT


프로세서는 4 종류의 메모리 관리용 레지스터를 제공한다. GDTR, LDTR, IDTR, TR 이 그것들 이다. 이 레지스터를 로드하고 저장하기 위해서 프로세서는 특별한 명령어를 제공한다. 이번 글에서는 GDT와 LDT를 위한 GDTR과 LDTR에 대해서만 알아본다.



GDTR, Global Descriptor Table Register



GDTR 레지스터는 Global Descriptor Table, GDT 의 32Bit의 Base Address 와 16Bit의 Table Limit을 포함하고 있다.
Base Address 는 선형 주소상의 GDT 시작 주소를 나타내며, Table Limit 은 GDT 의 한계 주소를 나타낸다.

프로세서는 GDT를 GDTR 로 Load 하고 Store 하기 위해서 각각 LGDT, SGDT 명령어를 제공한다. 프로세서가 리셋되거나 켜졌을때 GDTR의 Base Address 는 0으로, Table Limit은 0FFFFh 로 초기화되며 Protected - Mode 로 전환시 GDT 의 Base Address 와 Table Limit을 GDTR로 로드해야 한다.



LDTR, Local Descriptor Table Register


LDT는 GDT 내에 존재하는 LDT 세그먼트 디스크립터(2번 시스템 세그먼트 디스크립터)를 통해 접근할 수 있는 세그먼트다. LDT 세그먼트의 디스크립터는 반드시 GDT 내에 존재해야 한다. LDTR 레지스터는 Segment Selector, LDT의 Base Address, LDT의 Table Limit, LDT의 Segment Attributes 을 담고 있다.

Base Address는 LDT 세그먼트의 선형주소를, Table Limit은 한계 주소를 나타낸다. 

LLDT와 SLDT 명령어를 통해 LDTR에 LDT를 Load 하고, Store 할 수 있다. LLDT가 세그먼트 셀렉터를 LDTR로 로드할때 Basee Address, Table Limit, Descriptor Attributes 가 LDT 세그먼트 디스크립터로부터 자동적으로 로드된다. 

Task Switching이 발생하면 LDTR은 새로운 세그먼트 셀렉터와 디스크립터의 내용으로 자동적으로 채워진다. 하지만, 이전의 LDTR 내용은 저장되지 않는다. 컴퓨터 전원이 켜지거나, 리셋될때 LDTR의 Base Address는 0으로, Table Limit은 0FFFFh 로 초기화 된다.





그렇다면, 이들 GDTR 과 LDTR 은 어떻게 이용되는 것일까? 

다시 주제를 디스크립터 테이블, Descriptor Table 로 돌려보자.






GDTR은 GDT를 가리키는데 사용되고, LDTR은 LDT를 가리키는데 사용된다. 세그먼트 셀렉터의 TI 비트를 통해서 접근해야 할 메모리가 Global Descriptor Table ( 0 ) 에 존재하는지, Local Descriptor Table ( 1 ) 에 존재하는지를 결정한다.

각시스템은 반드시 한개의 GDT 를 정의해야 하며, 이렇게 정의된 GDT는 시스템에 존재하는 모든 프로그램과 태스크에 의해서 사용된다. 추가적으로 시스템은 한개, 혹은 그 이상의 LDT 를 정의할 수 있다. 예를들어 LDT 는 분리되어 동작하는 각 태스크마다 정의 될 수도 있고 모든 태스크들이 같은 LDT 를 공유할 수도 있다.

GDT 는 세그먼트가 아니다. (LDT 는 세그먼트다.) GDT 는 선형 주소내에 존재하는 Data Structure (For Segment Desciptor) 이며 GDT 의 Base Address 와 Table Limit 은 GDTR 에 담겨 있다. (우리는 위에서 이미 GDTR이 이러한 기능을 한다는것을 알아 보았다.) GDT의 Base Address 는 프로세서의 성능을 위해서 8 Byte 단위로 정렬 되야 한다.

하나의 디스크립터 크기는 64 비트, 즉 8 Byte 다. GDTR의 Table Limit 비트가 16 비트이므로, 8 단위로 나누면 최대 8192(2의 13승) 만큼의 디스크립터를 GDT 내에 포함할 수 있다. 세그먼트 셀렉터의 인덱스 비트가 13 비트 인 이유도 여기에 있다. GDTR이나 LDTR 의 Table Limit 비트가 16비트이므로 8 Byte 단위의 디스크립터를 모두 가리키려면 2의 13승, 8192 만큼의 비트가 필요하기 때문이다.

GDT 의 디스크립터중 첫번째 디스크립터는 "NULL Desciprotr" 라고 불리며 사용되지 않는다. 데이터 세그먼트 셀렉터(DS, ES, FS, GS)가 널 디스크립터를 가리키는 것은 예외를 발생시키지 않지만, 널 디스크립터를 통해서 메모리에 접근하려는 시도는 #GP 를 발생시킨다. 초기화 과정에서 세그먼트 셀렉터를 널 디스크립터로 지정해 두는것은 사용되지 않은 레지스터를 통해 메모리 접근하려는 시도를 막기 위함이다. 

LDT 는 LDT 타입 시스템 세그먼트에 존재하며, GDT 는 이 LDT 를 가리키는 세그먼트 디스크립터를 포함해야 한다. LDT 가 여러개라면 개수만큼의 LDT 세그먼트 디스크립터가 GDT 내부에 존재해야 하며 LDT 디스크립터는 GDT 어느곳에나 존재할 수 있다.



(위의 문단은 영어실력의 부족으로 인해 해석할 수가 없다.)









논리(가상) 주소가 선형 주소로 바뀌는 과정, SEGMENTATION



우리는 이전 글, Memory Management : Segmentation 1 과 이번 글 통해서 세그먼테이션에서 사용되는 레지스터와 각종 구조체에 대해서 알아 보았다. 세그먼테이션 과정을 전체적으로 정리해 보자.


우리가 흔히 알고 있는 세그먼트 레지스터, 정식 명칭은 세그먼트 셀렉터Segment Selector 로서 어느 세그먼트를 선택할 지를 나타낸다.

Index 는 GDT (or LDT) 의 몇번째 세그먼트 디스크립터를 선택할지를 나타내며, TI 비트를 통해서 우리가 원하는 세그먼트 디스크립터가 GDT에 존재하는지, LDT 에 존재하는지를 결정한다.


GDTR 로 구한 GDT의 베이스 어드레스로부터, 세그먼트 셀렉트의 인덱스 X 8 만큼의 주소를 더해서 원하는 세그먼트 디스크립터에 접근 해서 세그먼트의 정보를 나타내는 디스크립터를 얻는다.

그리고 세그먼트 디스크립터로부터 세그먼트의 베이스 어드레스와 기타 정보들을 얻는다. 여기서 얻은 세그먼트의 베이스 주소를 통해 세그먼트에 접근하고, 여기에 우리가 가지고 있는 주소, 즉 논리 주소를 더해 선형 주소를 얻는다.



이것이 바로 세그먼테이션이다.

윈도우에서는 이렇게 얻어진 선형주소를 페이징을 통해 다시 실제 물리 주소를 변환하며, 만약 해당 운영체제가 페이징 기능을 사용하지 않는다면 이 선형주소는 실제 물리주소가 될 수 있다.

Posted by cyj4369
,