090327

|



残りの菜園も耕しました。汗だく。3畝全部で40kg堆肥を入れて、鶏糞も混ぜま
した。去年は自家製の腐葉土を混ぜただけだった。

手前の半畝の部分にチンゲンサイを蒔きました。

トマトは腐葉土(自家製)を使って育苗箱に。夜は部屋に入れています。

x86続き。
保護モードに移行した後もリアルモードのBIOSはまだ使いたい。

BIOSを呼ぶルーチンはこの形に固定することにした。引数が2つなのは
regparm (3)のうち一つはこの関数へのポインタに使われてしまうから。
保護モードとリアルモードでpush/popのアライメントが異なるので、そこの複
雑さをレジスタ渡しでクリアする目論見も。

typedef int (bios_func_t)(int, int) __attribute__((regparm (2)));
bios_func_t bios_com_init; これはリアルモード用の関数。

保護モードからはこのようにしてコールする。regparm (3)なので
3引数はそれぞれ左からEAX, EDX, ECXに積まれる。

int call16 (bios_func_t *, int, int) __attribute__((regparm (3)));

// int call16 (void (*)(int, int), int, int)__attribute__((regparm (3)))
// call real-mode subroutine from protect-mode.
	.code32
FUNC (call16)
	ENTER_32	これはcaller saved(EBX,ESI,EDI,EBP,ESP)を退避。

まず、リアルモードの設定にしたデスクリプタを設定。保護モード用の設定
だけれど、そのlimitはリアルモードでも引きつがれる。Dビットは16bitに
設定。
BXを使っているのは引数のAXをそのまま下に渡すため。
	// Install Descriptor for real-mode.
	movw	$0x20,	%bx
	movw	%bx,	%ds
	movw	%bx,	%es
	movw	%bx,	%ss
CSはmovで設定できないのでLJMPで設定。
	ljmp	$0x18,	$1f	// Load CS descriptor for real-mode.
Dビットは16bitに設定してあるので、ここから16bitモード。
1:	.code16
	// Change to real-mode.
	movl	%cr0,	%ebx
	andl	$~1,	%ebx
	movl	%ebx,	%cr0
パイプラインをフラッシュして、リアルモードのCSに0x0を設定。
	ljmp	$0,	$2f	// Load real-mode CS with pipeline flush.
2:
その他のセグメントもリアルモード用に設定。
	// Set real-mode DS,ES,SS
	subw	%bx,	%bx
	mov	%bx,	%ds
	mov	%bx,	%es
スタックポインタは今現在、リアルモードでもそのまま使える設定なので
これでいい。
	mov	%bx,	%ss
	// Now Real-mode.

呼び出す関数の引数を設定します。
	// Setup argument.
	mov	%ax,	%bx
	mov	%dx,	%ax
	mov	%cx,	%dx
	// Call requested function.
	call	*%bx

この後は普通にプロテクトモードに移ります。
	// Return to Protect-mode.
	movl	%cr0,	%ebx
	orl	$0x1,	%ebx
	movl	%ebx,	%cr0
	ljmp	$0x8,	$4f	// Load CS(0x08) with pipeline flush.
4:	.code32
	// Load DS(0x10),ES,FS,GS
	movw	$0x10,	%bx
	movw	%bx,	%ds
	movw	%bx,	%es
	movw	%bx,	%fs
	movw	%bx,	%gs
	// Load SS
	movw	%bx,	%ss
	LEAVE_32
	ret

これを使って、保護モードから呼ぶラッパーを作成。
void
bios_com_putc32 (int8_t c)
{

  call16 ((void *)bios_com_putc, c, 0);
}
これでBIOSを使ってシリアルにputc/getcできるようになったので、ここで はじめて本体のOSにつなげてみました。何も問題なくシェルモジュールは 動いた。気をよくして、ささっとスレッドまわりもポートしてみたところ、
qemu  -serial stdio -std-vga -hda boot
boot1: disk=0x0080
jump to boot2
stack_start: 0xfff0
data: 0xbc00-0xc4c4 2244byte
bss: 0xc4e0-0xcee4 2564byte
A20: enabled.
boot drive: 80
__thread_setup: [1] c928-c528
__thread_setup: [2] ced4-cad4
thread_create: [2]:app0 func=86ab esp=cec4 eip=86ab eflags=2 cs=8 stack=1024byte
thread_start: [2]
thread_priority: [1] pri 1->1 state = 0 (UP)
thread_context_switch: c4e0: sp=c8a0
thread_context_switch: switch 1->2: sp=cec4
app0: arg=abcdef90
thread_context_switch: ca8c: sp=ce88
thread_context_switch: switch 2->1: sp=c8a0
thread_priority: [1] pri 1->3 state = 0 (DOWN)
thread_context_switch: c4e0: sp=c880
thread_context_switch: switch 1->1: sp=c880
>help
[0] help
2: 610
1: 498
---Ready Queue---
<0>: 
<1>: 
<2>: 
<3>: 1 
---Thread Status---
id   pri(used/total)
[2] W 1 (418/1028) app0
[1] R 3 (530/1028) root
---Monitor---
avaliable command: help reset S 
>
おお。こんなにうまくいくとは思わなかった。