プロテクトモードモニタを作る

 一時、「MyOS」ブームだったようです。 最近少なくなった、「直制御」の世界に興味を持つ人が増えたことは、 OSASKの河合さんを始め、多くの人の功績でしょう。
 一方、私は個人的に、生産装置分野で、「プロテクトモード・モニタ」などを作っています。 OSと呼べるものではないと思っているので、「モニタ」と呼んでいます。 その開発成果物のうち、公開しても差し支えないものを、公開していきたいと思います。


始める前に

 なんとも軟弱な話ですが、開発はWindows上で行っています。 言い訳をすれば、生産装置分野で現地調整ともなると、ノーパ持って、日本中(いや世界中・・)移動になります。 そして、Windowsでしか動かないユーティリティもあるので、BSD上に開発環境を持っていてしまうと、 パソを2台か、それこそエミュ上のBSDでなんてことになってしまいます。
〜使っているもの〜
秀丸エディタ
nasm
mingw
qemu
bochs
intel社のマニュアルpdf
あと、書籍が数冊といったところでしょうか。 もちろん、インターネットエクスプローラも使っています。

 基本的にC言語で開発していますので、mingwのgcc、でもアセンブラは表記が気に入らないので、 nasmを使っています。後は、気に入ったエディタとエミュがあれば、OKです。 エミュはBochsとQEMUの両方を用意したいところです。
 昔、モニタ開発当初は、エミュもなく、出来上がったバイナリをFDに書き込んで、 リセットして実際に起動させておりました。

ブートセクタを作る

 もし、マイOSを作りたいと考えている人がいらっしゃったら、 ブートセクタを最初に作ることはお勧めしません。  マイクロソフトの管理された世界から、自由の海を求めて旅たてば、 そこは、INTELの管理社会だったなんてことになってます。  ちょっとプロテクトモードを実験するにも、GDT,IDT、ページング(これは任意かな) TSS(仮想86や特権いじるなら必須)割り込み、フォルト、アセンブラの知識 etc,etcと必要になり、 これに、ハード仕様の調べモノなどが加わって、かなり大変です。
 この分野でネットを巡回していると、「リンク切れ率」が非常に高い気がします。 それは、OSの構築が、布教活動あるいは価値観の押し付け、議論になりやすいといった問題もあるでしょうし、 一人で取り組むには、あまりに範囲の広い総合技術だからという点もあるでしょう。
 GUIなんかの実験をするのであれば、別にWindows上で、DIBに描画して、 (但し、Windows依存コードを局所化しておいて)ある程度デバック終わってから独自ブートにするとか、 ファイルシステムなんかでも、イメージファイルを作って、一晩、ファイル読み書きを続けて、 システム破綻しないか、windows上やUnix上で実験するなど、OS技術の大半は、 アプリケーションとして、他のOS上で検証できるものだと思います。  前にH8上にFAT16載せる仕事していたときも、FAT16のデバックはwindows上で行いました。 一晩、ランダムにファイルを読み書きして、そのイメージファイルをFreeBSD上で、SDカードに書き出し、 それをwindowsで検証するという方法で。(あ、でも、この後、リトルエンディアンの問題で、 H8上でバグるという失敗を犯してますが)

 さて、前置きが長くなりました。ブートセクタを作るのですが、 BSDやLINUXにあるものと同じものを作っても仕方ないと思います。
 ここでは、「プロテクトされていない何でもアリの32ビット環境」を最終形として狙っています。 また、実験を行うのには、コンパクトなほうが良いだろうとか、 16ビットコードは、少ないほうがよいだろうというのも頭の隅にいれています。 で、作ったのがこんな感じです。さすがに最初のブート部分は全部アセンブラです。

;
;	boot1	一番最初のブート
;	>nasm -f bin boot1.bin boot1.asm
;	boot2を0x8000に読み込んで(最大32K)
;	プロテクトモードに(必要最小限度設定で)移行
;	0x00008000 番地にJUMP 割り込みは止まったまま。
;	ページングは動作していない。
;	copyright(c)2000-2007 by faicha
;
	org	0x7c00

	cli
	jmp	entry2
;
;	メッセージの表示
;
msgout:
	mov	ah,0x0e
.loop
	mov	al,[bx]
	cmp	al,0x00
	jnz	.next
	ret
.next
	int	10h		; テレタイプ式書き込み
	inc	bx
	jmp	.loop

;
;	PANIC
;
panic:
	jmp	panic		; 永久ループへ


;
;	エントリー2
;
entry2:
	mov	ax,cs
	mov	ds,ax
	mov	es,ax
	mov	ax,0x6000
	mov	sp,ax
;
;	拡張INT13H の検査
;
chk_e13:
	mov	bx,0x55aa	; 拡張検査用数値
	mov	ah,0x41		; 拡張検査コマンド
	int	0x13		; DISK BIOS
	cmp	bx,0xaa55	; 拡張機能有効
	jz	.next		; 有効であればOK

	mov	bx,err1		; エラーメッセージアドレス
	call	msgout		; エラー表示
	jmp	panic		; 永久ループ
.next


;
;	boot2を読み込む
;
read2:
	mov	bx,drv
	mov	dl,[bx]		; ドライブを指定
	mov	si,dap		; DISK Address Packetを設定
	mov	ah,0x42		; 拡張read
	int	0x13
	jnc	.next
	mov	bx,err2		; エラーメッセージアドレス
	call	msgout		; エラー表示
	jmp	panic		; 永久ループ
.next


;
;	プロテクトモードの準備
;
setup:
	mov	bx,gdtdat
	lgdt	[bx]		; GDTのセット


;
;	プロテクトモードへの移行
;
go32bit:
	cli
	mov	eax,cr0
	or	eax,1		; PEビットをセットしてプロテクトモードへ
	mov	cr0,eax

	jmp	.next		; パイプラインクリアのため
.next:

	;*********
	bits	32
	;*********
	db	0xea		; セレクタ付JUMPの命令
	dw	.next2 		; 
	dw	0x08		; セレクタ 0x08

.next2:
	mov	ax,0x10		; セレクタ0x10をds,esに
	mov	ds,ax
	mov	es,ax
	mov	ax,0x18		; セレクタ0x18をssに
	mov	ss,ax
	mov	eax,0x00007800	; スタックの新しい値
	mov	esp,eax
;
;	32ビット起動コードへJUMP
;
	jmp	0x00008000	; boot2コードの先頭へ

;
;	文字列
;
msg0:
	db	"Faicha IPL version 2.20",0x0d,0x0a,0x00
err1:
	db	"ERR INT13 EXT.",0x00
err2:
	db	"ERR READ BOOT2",0x00

;
;	Disk Address Packet
;
dap:
	db	0x10		; パケットサイズ(=16)
	db	0x00		; 予約
	db	63			; Blocks = 31.5Kbyte
	db	0			; 予約
	dw	0x0000		; 読み込みオフセット位置
	dw	0x0800		; 読み込みセグメント位置
	dd	1			; 読み込み先頭セクタ番号
	dd	0			; 読み込み先頭セクタ番号上位32ビット
drv:
	db	0x80		; ブートドライブ

;
;	GDT用データ
;
gdt:
	db	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00	; セレクタ 0x00 なし
	db	0xff,0xff,0x00,0x00, 0x00,0x9a,0xcf,0x00	; セレクタ 0x08	code/code386/bigseg
	db	0xff,0xff,0x00,0x00, 0x00,0x92,0xcf,0x00	; セレクタ 0x10	data
	db	0x00,0x00,0x00,0x00, 0x00,0x96,0xc0,0x00	; セレクタ 0x18 stack
gdtdat:
	dw	0x0fff		; Limit = 4k (###)
	dw	gdt		; offset 0-15
	dw	0x0000		; offset 16-31

;
;	Boot Sign
;
	times	510-($-$$) DB 0
	dw	0xaa55					; ブートサイン

 パーティションはどうしたとか、色々問題のあるコードですが、 ひとまず、ハードディスクの先頭1セクタに書き込めば、次のセクタから64セクタほどを、 0x8000番地に読み込み、32ビット・プロテクトモードにして先頭を呼び出します。 但し、ページングは動いていませんし、GDTは暫定、IDT、TSSは未設定という、 本当に「ヨタヨタ」でプロテクトモードに入ります。あ、A20もONにしていません。

 ただ、こんなひどい形ででもプロテクトモードに入ってしまったほうが、 (BIOSが使いにくいという一点を除いて)プログラムは書きやすいですし、 単なる実験であれば、32Kバイト内でコードを書けば、出来てしまうということで、 結構、使っています。

 世の中の(特にフリーなUNIXは)古いハードを大切にするようですが、 このコードは、もともと組み込みPC用なので、あまり古いハードサポートを考えていません。 このBOOT1も、拡張int 13hをサポートしてないBIOSだと、 ERR INT13 EXT. というひどいエラーを出して止まります。ほとんど見たことありませんが。


無作為研究所トップページに戻る

copyright(c)2007 by MUSAKUI-LABO