Hatena::ブログ(Diary)

kawa1128の日記 このページをアンテナに追加 RSSフィード Twitter

2010-04-04

32bit Protect Mode

ようやく完全に32bitに移行できたので、その記録。

まずは、IPL。

.code16gcc

_start:
	JMP entry

	// for FAT12
	.byte   0x90
	.ascii  "HelloIpl"
	.word   512
	.byte   1
	.word   1
	.byte   2
	.word   224
	.word   2880
	.byte   0xf0
	.word   9
	.word   18
	.word   2
	.int    0
	.int    2880
	.byte   0,0,0x29
	.int    0xffffffff
	.ascii  "HELLO-OS   "
	.ascii  "FAT12   "
	.skip   18,0
	
entry:
	// レジスタの初期化
	movw	$0x0, %ax
	movw	%ax, %ss
	movw	%ax, %dx
	movw	%ax, %ds
	movw	%ax, %es

	// 0x7c00に読み込まれるので、SP0x7c00にしないとアドレスの
	// 設定が煩雑になるため。
	movw  	$0x7c00, %sp

	// フロッピーディスクを読み込む
	// 読み込む先を設定する。
	movw	$0x0820, %ax
	movw	%ax, %es

	// シリンダ0 ヘッド0 セクタ2
	movb	$0x0, %ch
	movb	$0x0, %dh
	movb	$0x02, %cl

	//10シリンダ分読み込む
readloop:
	// エラーカウンター
	movw	$0x00, %si

retry:	
	//Disk読み出しのBIOSコール
	movb	$0x02, %ah
	movb	$0x01, %al
	movw	$0x00, %bx
	movb	$0x00, %dl
	int	$0x13
	jnc	next

	//エラー処理
	addw	$0x01, %si
	// retry5回でエラー終了
	cmp	$0x05, %si
	jae	error
	// ドライブを初期化
	mov	$0x00, %ah
	mov	$0x00, %dl
	jmp	retry

next:
	//格納場所のアドレスを0x0020進める
	movw	%es, %ax
	addw	$0x0020, %ax
	movw	%ax, %es
	
	add	$0x01, %cl
	cmp	$18, %cl
	jbe	readloop
	
	movb	$0x01, %cl
	addb	$0x01, %dh
	cmp	$0x02, %dh
	jb	readloop
	
	movb	$0x01, %dh
	add	$0x01, %ch
	cmpb	$10, %ch
	jb	readloop

	// カーネルイメージが、読み込まれている
	// アドレスにジャンプする
	jmp	0x00c200

fin:
	hlt
	jmp     fin

error:	
	movw	$err_msg, %si
	call	printstr
	jmp	fin
	
printstr:
	nop
putloop:
	// SIで指定された文字列を
	// 1文字ずつ取り出す。
	movb   	(%si), %al
	addw	$0x01, %si
	// NULL文字か比較
	cmpb 	$0x00, %al
	je      putloop_end
	// SystemCallの設定
	movb   	$0x0E, %ah
	movw	$0x0015, %bx
	int	$0x10
	jmp     putloop
putloop_end:
	ret
	
err_msg:
	.byte   0x0a,0x0a
	.ascii  "Disk Error\r\n"
	.byte	0x00

	.org    0x1fe
	.byte   0x55,0xaa

iplである程度、kernelに相当する部分をメモリ上に読み込んでおく。


        .code16
        .global _start

_start:
        // レジスタを初期化する                                                        
        movw    $0x00, %ax
        movw    %ax, %ds
        movw    %ax, %es
        movw    %ax, %ss
        // 32ビットモードを有効にするために                                            
        // PICをマスクする                                                             
        movb    $0xff, %al
        outb    %al, $0x21
        nop
        outb    %al, $0xa1

        // 割り込みフラグをクリア                                                      
        cli

        // A20Gateを有効にする。                                                       
        //割り込みを禁止する                                                           
        call    waitkbout
        movb    $0xd1, %al
        outb    %al, $0x64
        call    waitkbout
        movb    $0xdf, %al
        outb    %al, $0x60
        call    waitkbout

        .arch   i486
to_protect:
	// Protectモードにする                                                         
        lgdtl   (gtr0)
        movl    %cr0, %eax
	and     $0x7ffffff, %eax
        or      $0x0000001, %eax
        movl    %eax, %cr0
        jmp     pipelineflash

pipelineflash:
        movw    $0x8, %ax
        movw    %ax, %ds
        movw    %ax, %es
        movw    %ax, %fs
	movw    %ax, %gs
        movw    %ax, %ss

        // osmain0x00280000にコピー                                                  
	movl    $osmain, %esi
        movl    $0x00280000, %edi
        movl    $512 * 1024 / 4, %ecx
        call    _memcpy

        jmp     $0x10, $0x00000001

_fin:
        hlt
        jmp     _fin
waitkbout:
        inb     $0x64, %al
        andb    $0x02, %al
        jnz     waitkbout
        ret

        // Memory Copy                                                                 
        // Source : esi                                                                
        // Destination: edi                                                            
        // Counter: ecx                                                                
_memcpy:
        movl    (%esi), %eax
        add     $4, %esi
        movl    %eax, (%edi)
        add     $4, %edi
        sub     $1, %ecx
        jnz     _memcpy

        ret

        .align  8
gdt0:
        // GlobalDescriptor Table                                                      
        // Null Selecter                                                               
        .skip   8, 0x00
        // 1st GDT                                                                     
        .word 0xffff, 0x0000, 0x9200, 0x00cf
        // 2nd GDT                                                                     
        .word 0xffff, 0x0000, 0x9a28, 0x0047
        // Last GDT                                                                    
        .word   0x0000
gtr0:
        .word   8 * 3 - 1
        .int    gdt0

osmain:
	nop
	hlt
	jmp	osmain

動作確認には、bochsを利用。

00442040000i[CPU0 ] CPU is in protected mode (halted)
00442040000i[CPU0 ] CS.d_b = 32 bit
00442040000i[CPU0 ] SS.d_b = 32 bit
00442040000i[CPU0 ] EFER   = 0x00000000
00442040000i[CPU0 ] | RAX=0000000000000000  RBX=0000000000000015
00442040000i[CPU0 ] | RCX=0000000000000000  RDX=0000000000000100
00442040000i[CPU0 ] | RSP=0000000000007c00  RBP=0000000000000000
00442040000i[CPU0 ] | RSI=000000000008c2a8  RDI=0000000000300000
00442040000i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00442040000i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00442040000i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00442040000i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00442040000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf ZF af PF cf
00442040000i[CPU0 ] | SEG selector     base    limit G D
00442040000i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00442040000i[CPU0 ] |  CS:0010( 0002| 0|  0) 00280000 0007ffff 0 1
00442040000i[CPU0 ] |  DS:0008( 0001| 0|  0) 00000000 ffffffff 1 1
00442040000i[CPU0 ] |  SS:0008( 0001| 0|  0) 00000000 ffffffff 1 1
00442040000i[CPU0 ] |  ES:0008( 0001| 0|  0) 00000000 ffffffff 1 1
00442040000i[CPU0 ] |  FS:0008( 0001| 0|  0) 00000000 ffffffff 1 1
00442040000i[CPU0 ] |  GS:0008( 0001| 0|  0) 00000000 ffffffff 1 1

で、どこでハマっていたかというと、far jmpするところ。far jmpがうまくいかずにコードセグメントがなかなか32bitになってくれませんでした。

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。

トラックバック - http://d.hatena.ne.jp/kawa1128/20100404/1270361566