OS(5) プロテクトモードへ移行

次の内容で作成してみる。

  • フラットモデルとする
  • IPLの動作は呼び出すプログラムを2セクタ分とする以外同じ
  • 最初のセクタは(setup)、IPLから直接呼ばれ、GDTの設定とプロテクトモードへの移行を行うプログラムを入れる
  • 次のセクタ(kernel)はプロテクトモードで動作し、VRAMにメッセージを書き込む。

無事動作完了。
次は割り込みだ。

実行結果(VirtualPC2004)

Makefile(GNU make用)

os.img: os.bin
	ruby makeFDimage.rb $< $@

os.bin: ipl.bin setup.bin kernel.bin
	copy /b ipl.bin+setup.bin+kernel.bin $@

ipl.bin: ipl.asm
	nasm -o $@ $<

setup.bin: setup.asm defs.inc
	nasm -o $@ $<

kernel.bin: kernel.asm defs.inc
	nasm -o $@ $<

defs.inc

CSEG		equ	0x10
DSEG		equ	0x18
VRAMOFS		equ	0xb8000

setup.asm

IDTの初期化とかも入れていく予定

;
; setup.asm プロテクトモードカーネルの起動準備
;
%include	"defs.inc"

; まずは 1000:0 で開始 ss:sp はIPL設定のまま
start:		mov	ax, cs
		mov	ds, ax

		cli			; 割り込み禁止
		lgdt	[GDTR]		; GDTの設定

		mov	eax, cr0	; プロテクモードへ移行
		or	eax, 1
		mov	cr0, eax
		jmp	.@flush		; パイプラインをフラッシュしてjump
.@flush:	
		jmp	dword CSEG:PROTECT_start + 0x10000
;;		db	0x66, 0xea
;;		dd	PROTECT_start + 0x10000	; アドレス補正
;;		dw	CSEG	

GDTR:		dw	initial_GDT_end - initial_GDT - 1
		dd	initial_GDT + 0x10000	; アドレス補正

initial_GDT:
		dw	0, 0, 0, 0	; NULLセグメント
		dw	0, 0, 0, 0	; ダミー

		dw	0xffff		; limit(0-15)
		dw	0		; base(0-15)
		db	0, 0x9a		; base(16-23), code
		db	0xcf, 0		; G,32bit,limit(16-19)

		dw	0xffff
		dw	0
		db	0, 0x92		; data 
		db	0xcf, 0
initial_GDT_end:

		times  512 -( $ - $$) db 0
PROTECT_start:

kernel.asm

;
; kernel.asm
;
[bits 32]
[org 0x10200]

%include	"defs.inc"

PROETCT_start:	
		mov	ax, DSEG
		mov	ds, ax
		mov	es, ax
		mov	ss, ax
		mov	esp, 0xa0000	; メモリホール直前からスタック

		xor	ax, ax
		mov	fs, ax
		mov	gs, ax

		mov	esi, msg
		mov	edi, VRAMOFS

		mov	ah, 0x4f
		cld

.@loop:		lodsb
		stosw
		or	al, al
		jnz	.@loop

		jmp	$

msg:		db	 'This is PROTECTED mode kernel', 0