残りの菜園も耕しました。汗だく。3畝全部で40kg堆肥を入れて、鶏糞も混ぜま
した。去年は自家製の腐葉土を混ぜただけだった。
手前の半畝の部分にチンゲンサイを蒔きました。

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

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

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

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 >おお。こんなにうまくいくとは思わなかった。
