anhongkui 发表于 2007-06-20 13:44

进入保护模式, 使用分页机制出错

boot.S,设置GDT表, copy kernel 到0x0000, 进入保护模式


.code16
.text

.global        _start
        .set         CODE_SEL,        0x08
        .set         DATA_SEL,        0x10

        .set        GDT_ADDR, 0x80000
        .set        GDT_ENTRIES, 3
        .set        GDT_SIZE, (8*GDT_ENTRIES)
_start:
        jmpl        $0x7c0, $start2

gdt:
        .quad 0x0000000000000000 # null selector
        .quad 0x00cf9a000000ffff # cs base 0x00000000 limit 0xfffff code read/exec
        .quad 0x00cf92000000ffff # ds base 0x00000000 limit 0xfffff data read/write
gdt_48:
        .word        .-gdt
        .long        GDT_ADDR
start2:
        movw        %cs, %ax
        movw        %ax, %ds
        movw        %ax, %es
        movw        %ax, %ss
        movw        $0x7c00, %sp
        cli
        cld

        movb        $0x0f, %ah
        xorb        %al, %al
        int        $0x10

        movb        $0x00, %ah
        int        $0x10

#target address
        movw        $0x1000, %ax
        movw        %ax, %es
        movw        $0x00, %bx

        movb        $0x02, %ah        # ah: read disk
        movb        $0x01, %al        # al: count of sectors
        movb        $0x00, %ch        # ch: track
        movb        $0x02, %cl        # cl: cylinder
                                # dl: driver num

        int        $0x13                # 13h: disk I/O

#        ->
# move kernel to 0x0000:0000
        movw        $0x1000,%ax
        movw        %ax,        %ds
        movw        $0x0000,%ax
        movw        %ax,        %es
        xorw        %si,        %si
        xorw        %di,        %di
        movw        $(512>>2),%cx
        rep
        movsl

# move gdt to GDT_ADDR
        movw        $0x7c0,        %ax
        movw        %ax,        %ds        # reset ds to 0x07c0
        movw        $gdt,        %si

        movw        $GDT_ADDR>>4,%ax
        movw        %ax,        %es
        xorw        %di,        %di
        movw        $GDT_SIZE>>2,%cx
        rep
        movsl

enable_a20:
        inb        $0x64, %al
        testb        $0x2, %al
        jnz        enable_a20
        movb        $0xbf, %al
        outb        %al, $0x64

        lgdt        gdt_48

        # set PE=1
        movl        %cr0, %eax
        orl        $0x1, %eax        # PE = 1
        movl        %eax, %cr0

        ljmp        $CODE_SEL, $0x0

        .org 510
        .word 0xAA55



kernel.S, 设置分页页目录,页表,设置CR3,CR0,
然后怎么才能叫分配出一个页来使用?
就是说需要手动设置页表吗?



.text

.global _start

        .org        0
_start:
        jmp        start2

        .set        CODE_SEL, 0x08 # cs 00001 000
        .set        DATA_SEL, 0x10 # ds 00010 000

start2:
        movl        $DATA_SEL, %eax
        movw        %ax, %ds
        movw        %ax, %es
        movw        %ax, %fs
        movw        %ax, %ss
        movw        %ax, %gs
        movl        $0xa0000, %esp
        cld

        # 0x80000 - 0x80000+GDT_SIZE         : GDT
        # 0x81000 - 0x82000                : page_dir
        # 0x82000 - 0x83000                : page_table

# initialize page_dir 0x81000 -> 0x82000
        movl        $0x81000, %eax
        movl        $0x82007, (%eax) # page_dir 只用到这一项,其他都无效
        movl        $1023, %ecx
1:
        addl        $4, %eax
        movl        $6, (%eax)        # page_dir 无效
        decl        %ecx
        jnz        1b


# initialize page_table 0x82000 -> 0x83000      共表示4M
        movl        $0x82000, %eax
        movl        $0x0, %ebx
        movl        $1024, %ecx
next:
        movl        %ebx, (%eax)
                addl          $7, (%eax)   # 加上权限就没有错误了。
        addl        $4, %eax
        addl        $0x1000, %ebx
        decl        %ecx
        jnz        next
# enable cr3
        movl        $0x81000, %eax
        movl        %eax, %cr3
        movl        %cr0, %eax
        orl        $0x80000000, %eax
        movl        %eax, %cr0

loop:
        jmp        loop

/*
        .org        0x81000

        .long        0x82007 # 82000 | 7
        .rept         1023
        .long         6        # 00000 | 6
        .endr

        .org        0x82000
        .org        0x83000

*/




Makefile:

AS=as -Iinclude
LD=ld

.S.o:
        $(AS) $< -o $*.o

all: Image

Image: boot kernel
        cat boot kernel.o > Image

boot: boot.o
        $(LD) --oformat binary -N -e _start -Ttext 0x0000 -o boot $<
kernel: kernel.o
        $(LD) --oformat binary -N -e _start -Ttext 0x0000 -o $@ $<
clean:
        rm -f Image boot boot.o kernel kernel.o


[ 本帖最后由 anhongkui 于 2007-6-20 15:12 编辑 ]
页: [1]
查看完整版本: 进入保护模式, 使用分页机制出错