4. Protected Mode의 주소 지정 방법

 

 

Real Mode에서는 16비트의 세그먼트 레지스터를 사용한 반면, Protected Mode에서는 각 세그먼트 레지스터가 셀렉터 레지스터와 디스크립터 레지스터로 나누어 집니다.

오른 쪽에 있는 디스크립터 레지스터는 다음과 같은 형태를 취하고 있습니다.

 

상위 13비트는 디스크립터를 찾기 위한 인덱스가 저장되고, 두번째 비트에는 TI 값, 0, 1 비트에는RPL 값이 들어갑니다.

실제로 프로그래머가, 세그먼트 레지스터에서 다룰 수 있는 것은 이 세그먼트 셀렉터입니다.

 

세그먼트 디스크립터 찾기

이 세그먼트 셀렉터를 이용하여 세그먼트 디스크립터를 찾는 방법을 설명하겠습니다.

본격적으로 찾기 전에 앞서 다음의 코드가 실행이 이미 되어 있어, gdtr 레지스터에 gdt가 등록이 되어 있다고 가정 하겠습니다.

lgdt[gdtr]

 

gdtr:

dw gdt_end – gdt – 1

dd gdt+0x10000

 

 

47

 Base address = 0x00010000

16

15

Limit  = 0x1F

0

00

00

00

00

00

01

00

00

00

00

00

1F

Gdtr 레지스터

 

예시로 세그먼트 셀렉터에 지난 포스팅에서 만든 데이터세그먼트 디스크립터를 나타내는 값을 넣어 보겠습니다.

 

SysCodeSelector equ 0x08

dw 0xFFFF              ; limit 0 - 15

dw 0x0000              ; base 0 - 15

dd 0x01                    ; base 16 - 23

db 0x9A                   ; 10011010(2)

db 0xCF                   ; 11001111(2)

db 0x00                  ; base 24 - 63

 

mov bx, SysCodeSelector

mov cs, bx


CS 레지스터에 SysCodeSelector equ 0x08 값을 넣어 봅니다.

15

 

 

 

 

 

 

 

 

 

 

 

3

2

1

0

 

 

 

 

 

 

 

 

 

 

 

0

1

0

0

0

들어간 값은 다음과 같이 해석할 수 있습니다.

3 - 15 (인덱스) : 1

2 (TI) : 0

0 – 1 (RPL) : 0

 

먼저 GDTR레지스터에 등록되어 있는 GDT의 Base Address를 가져와 GDT의 첫번째 디스크립터의 물리 주소 0x10000를 구합니다.

다음 그림은 지난 포스트에서 만든 4개의 디스크립터가 메모리에 저장된 모습입니다. (Little Endian)

각 세그먼트의 경계는 각기 다른 색으로 표시 되어 있습니다.

   

(hex)

00

01

10

11

 

10000

00

00

00

00

gdt:

10004

00

00

00

00

10008

FF

FF

00

00

SysCodeSelector :

1000C

01

9A

CF

00

10010

FF

FF

00

00

SysDataSelector :

10014

01

92

CF

00

10018

FF

FF

00

80

SysVideoSelector :

1001C

0B

92

40

00

10020

 

 

 

 

 


 

세그먼트 셀렉터에 주어진 인덱스를 가져와 디스크립터의 크기(8byte) 만큼 곱하고, 구한 Base Register 만큼 더합니다.

1 * 8 + 0x10000 = 0x10008

물리주소 0x10008을 찾아가 본 결과, 코드 세그먼트 디스크립터를 찾을 수 있었습니다.

디스크립터를 찾았으면 DS 세그먼트 셀렉터의 RPL과 코드 세그먼트 디스크립터의 DPL을 대조해 봅니다.

CS 세그먼트 셀렉터의 RPL은 00이며, 코드 세그먼트 디스크립터의 DPL은 00 임으로 일치합니다.

값이 일치한다면 CS 세그먼트 디스크립터 레지스터에 코드 세그먼트 디스크립터의 내용을 복사합니다.

 

세그먼트와 오프셋을 이용해 주소 지정

 

Lea esi, [ds:msgPMode]

 

위 코드에서 ds:msgPMode의 선형주소를 구해봅시다.

 

Ds의 세그먼트 디스크립터 레지스터입니다.

Limit

0xFFFFFFFF

Base Address

0x10000

속성

msgPMode의 주소를 구하니 0x65라는 것을 알 수 있습니다.(little endian를 고려합니다)

26

27 ;------------------------------------------------------------;

28 ;*********** 여기부터 Protected Mode입니다. *****************;

29 ;------------------------------------------------------------;

30

31 [bits 32]

32

33 PM_Start:

34 00000025 66BB1000     mov bx, SysDataSelector

35 00000029 8EDB     mov ds, bx

36 0000002B 8EC3     mov es, bx

37 0000002D 8EE3     mov fs, bx

38 0000002F 8EEB     mov gs, bx

39 00000031 8EEB     mov gs, bx

40 00000033 8ED3     mov ss, bx

41

42 00000035 31C0     xor eax, eax

43 00000037 66B81800     mov ax, VideoSelector

44 0000003B 8EC0     mov es, ax

45 0000003D BF54060000     mov edi, 80*2*10+2*10

46 00000042 3E8D35[65000000]     lea esi, [ds:msgPMode]

47 00000049 E802000000     call printf

48

49 0000004E EBFE     jmp $

50

51 ;------------------------------------------------------------;

52 ;*************** Sub Routines *******************************;

53 ;------------------------------------------------------------;

54

 

이제 세그먼트와 오프셋을 이용해 물리 주소를 찾아 봅시다. 먼저

(1) 오프셋의 주소를 lmit와 비교하여 작은지 검사합니다.

 

DS 세그먼트의 디스크립터 레지스터의 limit는 0xFFFFFFFF 로 오프셋 주소가 더 작음을 알 수 있습니다.

0xFFFFFFFF > 0x65

 

(2)lmit보다 작다면 세그먼트의 Base Address와 더해줍니다.

 

0x10000 + 0x65 = 0x10065

 

위 과정을 거치면 선형주소 , 즉 물리 주소가 완성됩니다.

 

+ Recent posts