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

发布于 2022-09-29 15:41:17 字数 11297 浏览 15 评论 0

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

  1. .code16
  2. .text
  3. .global        _start
  4.         .set         CODE_SEL,        0x08
  5.         .set         DATA_SEL,        0x10
  6.         .set        GDT_ADDR, 0x80000
  7.         .set        GDT_ENTRIES, 3
  8.         .set        GDT_SIZE, (8*GDT_ENTRIES)
  9. _start:
  10.         jmpl        $0x7c0, $start2
  11. gdt:
  12.         .quad 0x0000000000000000 # null selector
  13.         .quad 0x00cf9a000000ffff # cs base 0x00000000 limit 0xfffff code read/exec
  14.         .quad 0x00cf92000000ffff # ds base 0x00000000 limit 0xfffff data read/write
  15. gdt_48:
  16.         .word        .-gdt
  17.         .long        GDT_ADDR
  18. start2:
  19.         movw        %cs, %ax
  20.         movw        %ax, %ds
  21.         movw        %ax, %es
  22.         movw        %ax, %ss
  23.         movw        $0x7c00, %sp
  24.         cli
  25.         cld
  26.         movb        $0x0f, %ah
  27.         xorb        %al, %al
  28.         int        $0x10
  29.         movb        $0x00, %ah
  30.         int        $0x10
  31. #target address [es:bx][1000:0000]
  32.         movw        $0x1000, %ax
  33.         movw        %ax, %es
  34.         movw        $0x00, %bx
  35.         movb        $0x02, %ah        # ah: read disk
  36.         movb        $0x01, %al        # al: count of sectors
  37.         movb        $0x00, %ch        # ch: track
  38.         movb        $0x02, %cl        # cl: cylinder
  39.                                 # dl: driver num
  40.         int        $0x13                # 13h: disk I/O
  41. #        [ds:si] -> [es:di]
  42. # move kernel to 0x0000:0000
  43.         movw        $0x1000,%ax
  44.         movw        %ax,        %ds
  45.         movw        $0x0000,%ax
  46.         movw        %ax,        %es
  47.         xorw        %si,        %si
  48.         xorw        %di,        %di
  49.         movw        $(512>>2),%cx
  50.         rep
  51.         movsl
  52. # move gdt to GDT_ADDR
  53.         movw        $0x7c0,        %ax
  54.         movw        %ax,        %ds        # reset ds to 0x07c0
  55.         movw        $gdt,        %si
  56.         movw        $GDT_ADDR>>4,%ax
  57.         movw        %ax,        %es
  58.         xorw        %di,        %di
  59.         movw        $GDT_SIZE>>2,%cx
  60.         rep
  61.         movsl
  62. enable_a20:
  63.         inb        $0x64, %al
  64.         testb        $0x2, %al
  65.         jnz        enable_a20
  66.         movb        $0xbf, %al
  67.         outb        %al, $0x64
  68.         lgdt        gdt_48
  69.         # set PE=1
  70.         movl        %cr0, %eax
  71.         orl        $0x1, %eax        # PE = 1
  72.         movl        %eax, %cr0
  73.         ljmp        $CODE_SEL, $0x0
  74.         .org 510
  75.         .word 0xAA55

复制代码

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

  1. .text
  2. .global _start
  3.         .org        0
  4. _start:
  5.         jmp        start2
  6.         .set        CODE_SEL, 0x08 # cs 00001 000
  7.         .set        DATA_SEL, 0x10 # ds 00010 000
  8. start2:
  9.         movl        $DATA_SEL, %eax
  10.         movw        %ax, %ds
  11.         movw        %ax, %es
  12.         movw        %ax, %fs
  13.         movw        %ax, %ss
  14.         movw        %ax, %gs
  15.         movl        $0xa0000, %esp
  16.         cld
  17.         # 0x80000 - 0x80000+GDT_SIZE         : GDT
  18.         # 0x81000 - 0x82000                  : page_dir
  19.         # 0x82000 - 0x83000                  : page_table
  20. # initialize page_dir 0x81000 -> 0x82000
  21.         movl        $0x81000, %eax
  22.         movl        $0x82007, (%eax) # page_dir[0] 只用到这一项,其他都无效
  23.         movl        $1023, %ecx
  24. 1:
  25.         addl        $4, %eax
  26.         movl        $6, (%eax)        # page_dir[1-1023] 无效
  27.         decl        %ecx
  28.         jnz        1b
  29. # initialize page_table 0x82000 -> 0x83000      共表示4M
  30.         movl        $0x82000, %eax
  31.         movl        $0x0, %ebx
  32.         movl        $1024, %ecx
  33. next:
  34.         movl        %ebx, (%eax)
  35.                 addl          $7, (%eax)   # 加上权限就没有错误了。
  36.         addl        $4, %eax
  37.         addl        $0x1000, %ebx
  38.         decl        %ecx
  39.         jnz        next
  40. # enable cr3
  41.         movl        $0x81000, %eax
  42.         movl        %eax, %cr3
  43.         movl        %cr0, %eax
  44.         orl        $0x80000000, %eax
  45.         movl        %eax, %cr0
  46. loop:
  47.         jmp        loop
  48. /*
  49.         .org        0x81000
  50.         .long        0x82007 # 82000 | 7
  51.         .rept         1023
  52.         .long         6        # 00000 | 6
  53.         .endr
  54.         .org        0x82000
  55.         .org        0x83000
  56. */

复制代码

Makefile:

  1. AS=as -Iinclude
  2. LD=ld
  3. .S.o:
  4.         $(AS) $< -o $*.o
  5. all: Image
  6. Image: boot kernel
  7.         cat boot kernel.o > Image
  8. boot: boot.o
  9.         $(LD) --oformat binary -N -e _start -Ttext 0x0000 -o boot $<
  10. kernel: kernel.o
  11.         $(LD) --oformat binary -N -e _start -Ttext 0x0000 -o $@ $<
  12. clean:
  13.         rm -f Image boot boot.o kernel kernel.o

复制代码
[ 本帖最后由 anhongkui 于 2007-6-20 15:12 编辑 ]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文