와 신난다.

이제, 0SOS는 32비트 코드를 실행 할 수 있다.

그말은즉슨, 32비트 범용레지스터를 쓸 수 있다는 이야기.

eax, esi 등등 같은거 말이다.

아 기뻐라.

이걸 봐라.

32Bit!

보면 잘 돌아간다.

C언어로 하면 되는데요 같은 헛소리 할꺼면 창 닫기를

아무튼 이해하려고 용썻다.

다 이해했다.

젠장맞을, 세그먼트 테이블하고, 메모리 사용 범위, 스택때문에 좀 머리아팠음.

일단 16비트 리얼모드에서 32비트 보호모드로 바꾸려면

GDT 테이블을 구성하고

프로세서에 GDT의 크기와 위치를 알린다.

그 테이블 안에 첫번째 요소로는 NULLDescriptor이라고, 모든 필드가 0으로 초기화 한

세그먼트 디스크립터를 넣고

그다음에는 우리가 정의하는데

나와 책 저자분은

Code, Data 세그먼트 디스크립터를 넣었다.

여기서 이해하려고 용썼는데,

나는 코드와 데이터 디스크립터의 베이스 주소, 제한이 동일하길레 둘이 겹치면 안되는 거

아닌가 라는 생각을 했는데,

내가 잘못 전제를 깔고 들어갔던거다.

젠장 결국

현재 코드에선, 정확힌 지금 정의된 테이블에선

코드영역하고 Data영역하고 세그먼트 디스크립터가 구분해주지 않는다

둘다 다 0~4GB를 가르킬 수 있는 디스크립터.

그리고 스택은 위에서 아래로 자라기때문에, Data영역의 데이터랑 겹칠일은 없다.

(64kb가 제한이기 떄문, 코드에서 esp, ebp를 보기 바람)

그래서 코드에 상대주소값으로 계산하는 코드가 있구만

(LABEL - $$ + 0x10000) 같은거.

아무튼 완전히 이해했으니 넘어가고

그러고 나선, 운영모드를 관리하는 CR0 레지스터를 설정해준다.

설정값은 아레 코드에 표로 만들어져 있뒀으니까 보시고, 각 요소가

뭔지 궁금하면 검색하세요.

변환후 32비트 코드영역으로 점프하면 완성.

와 신나.

아무튼 32비트 전환을 위하면서

시작점이 될 Kernel Entry Point는 다음과 같다.


[ORG 0x00]
[BITS 16]

SECTION .text


START:
	mov ax, 0x1000

	mov ds, ax
	mov es, ax
	
	cli		;Ignore Interrupt

	lgdt[GDTR]

	;	Now Switch Protected Mode.
	;
	;   CR0 Register
	;	Summary: 
	;		Disable Paging, Disable Cache, Internal FPU, Disable Align Check
	;
	;   fields:
	;
	;	|PG|CD|NW|  |  |  |  |  |  |  |  |  |  |AM|  |WP|
	;	31---------------------------------------------16
	;	| 0| 1| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
	;
	;	|  |  |  |  |  |  |  |  |  |  |NE|ET|TS|EM|MP|PE| 
	;	15----------------------------------------------0
	;	| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 1| 1| 1| 0| 1| 1|
	;
	;	0b01000000000000000000000000111011	
	; 	0x4000003B
	;

	mov eax, 0x4000003B
	mov cr0, eax

	jmp dword 0x08 : (PROTECTEDMODE - $$ + 0x10000)


	; Following Code Now Prtoected Mode

[BITS 32]

PROTECTEDMODE:
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax


	mov ss, ax
	mov esp, 0XFFFE
	mov ebp, 0XFFFE
		
	push (SWITCHMESSAGE - $$ + 0x10000)
	push 2
	push 0
	call PRINT
	add  esp, 12

	jmp $

PRINT:
	push ebp
	mov ebp, esp
	push esi
	push edi
	push eax
	push ecx
	push edx

	mov eax, dword [ebp + 12]
	mov esi, 160
	mul esi
	mov edi, eax
		
	mov eax, dword[ebp + 8]
	mov esi, 2
	mul esi
	add edi, eax
		
	mov esi, dword[ebp + 16]
	
.PRINTLOOP:
	mov cl, byte[esi]
	
	cmp cl,0
	je PRINTEND
	
	mov byte[edi + 0xB8000], cl
	
	add esi,1
	add edi,2	
	jmp .PRINTLOOP
 
PRINTEND:
	pop edx
	pop ecx
	pop eax
	pop edi
	pop esi
	pop ebp
	ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;; DATA AREA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

align 8, db 0

dw 0x0000	;For Align

GDTR:
	dw GDTREND - GDT -1
	dd GDT - $$ + 0x10000

GDT:
	NULLDescriptor:
	dw 0x0000
	dw 0x0000
	db 0x00
	db 0x00
	db 0x00
	db 0x00


	CODEDescriptor:
	dw 0xFFFF	; Limit[15:0]
	dw 0x0000	; Base[15:0]
	db 0x00		; Base[23:16]
	db 0x9A		; P = 1, DPL = 0, Code Segment, Execute/Read
	db 0xCF		; G = 1, D = 1, L = 0, Limit [19:16]
	db 0x00		; Base[31:24]
	
	DATADescriptor:
	dw 0xFFFF	; Limit
	dw 0x0000	; Base
	db 0x00		; Base
	db 0x92		; P=1, DPL =0, Data Segment, Read/Write
	db 0xCF		; G= 1, D= 1, L= 0, Limit
	db 0x00		; Base
GDTREND:


SWITCHMESSAGE: db 'Switch Success. Now Running 32bit Protected Mode.',0

times 512 - ( $ - $$) db 0x00

리얼모드와 보호모드는 확실하게 메모리 접근이 다르다

이거이거 IA-32e 에서는 얼마나 복잡할지 기대되는데

게다가 페이징도 Disable인상태라 페이징 넣으면 얼마나 복잡해지려나 ㅋㅋㅋ…

아무튼 , 코드에 있는 표 나름 이쁘게 만들었다.

vim에선 이렇게 보이는데

표!

위에 코드는 어떻게 보일지 모르겠네.

아무튼 32비트 완성 이제 커널코드 작성해야겠네.