写了个操作系统从实模式跳转到保护模式的过程,不知道对不对

发布于 2022-09-29 12:02:32 字数 137 浏览 17 评论 0

1.在一个固定地址处处创建GDT,设置堆栈积存器地址
2.读取硬盘中的load.s到0x0处
3.打开A20地址线,设置积存器PE位,进入保护模式
4.跳转到0x0处执行load.s

注:设load.s为内核程序

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

泅人 2022-10-06 12:02:32

原帖由 shineyear 于 2007-5-24 13:39 发表于 1楼  
1.在一个固定地址处处创建GDT,设置堆栈积存器地址
2.读取硬盘中的load.s到0x0处
3.打开A20地址线,设置积存器PE位,进入保护模式
4.跳转到0x0处执行load.s

注:设load.s为内核程序

进入保护模式之前,要先为保护模式建立必要的环境。GDT 是其中一个,另一个是 IDT

并安 2022-10-06 12:02:32

我怎么感觉IDT并不是必须的呢?

鲸落 2022-10-06 12:02:32

关了中断就可以不用idt,但这样比较无趣。

与酒说心事 2022-10-06 12:02:32

请问我可不可以在启动的时候(跳入保护模式之前)把内核加载到0X0000位置呢?我尝试着这么做了但好象不行,是不是必须关中断才行?

七禾 2022-10-06 12:02:32

在pc中,0x0000处存放中断向量表,不能加载到那里,建议先在google上搜一下bios初始化完成后的内存布局

避讳 2022-10-06 12:02:32

原帖由 shineyear 于 2007-5-25 11:23 发表于 3楼  
我怎么感觉IDT并不是必须的呢?

什么叫保护模式,要理解它的真正意义才行呀。当然,你直接将 CR0.PE 直接置 1 可以让处理器处于 Protected mode,但这样是不能正常工作的。描述符表及描述符的意义在于处理器可以提供别代码的几个该问权限级别。
从物理上来说,在 protected mode 下,执行 int 指令必须经过 IDT 该问中断例程。你的系统从来绝对不执行 INT 么?

原来是傀儡 2022-10-06 12:02:32

我还是把代码贴上来吧

boot.s

.text
.globl    start
.set CODE_SEL, 0x08      
.set DATA_SEL, 0x10      
.set IDT_ADDR, 0x80000   

.set IDT_SIZE, (256*  
.set GDT_ADDR, (IDT_ADDR+IDT_SIZE)   

.set GDT_ENTRIES, 5      

.set GDT_SIZE, (8*GDT_ENTRIES)

.set KERNEL_SECT, 2      
.set STACK_BOT, 0xa0000   

.code16
start:
        jmp        code
gdt:   
        .quad    0x0000000000000000
        .quad    0x00cf9a000000ffff
        .quad    0x00cf92000000ffff
        .quad    0x0000000000000000
        .quad    0x0000000000000000
gdt_48:
        .word    .-gdt-1
        .long    GDT_ADDR
code:
        xorw    %ax,    %ax
        movw    %ax,    %ds   
        movw    %ax,    %ss   
        movw    $0x1000,%sp   

        movw    $0x0000,%ax
        movw    %ax,    %es
        xorw    %bx,    %bx   
        movw    $KERNEL_SECT,%cx
        movw    $1,     %si   
rd_kern:
        call    read_sect   
        addw    $512,    %bx
        incw    %si
        loop    rd_kern

        cli                 

        cld                    

        xorw    %ax,    %ax
        movw    %ax,    %ds   

        movw    $GDT_ADDR>>4,%ax   
        movw    %ax,    %es      
        movw    $gdt,   %si
        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            
     
        movl   %cr0,    %eax
        orl    $0x1,    %eax
        movl   %eax,    %cr0      

        ljmp   $CODE_SEL, $0x0

read_sect:
        pushw   %ax
        pushw   %cx
        pushw   %dx
        pushw   %bx

        movw    %si,    %ax        
        xorw    %dx,    %dx
        movw    $18,    %bx   

        divw    %bx
        incw    %dx
        movb    %dl,    %cl   
        xorw    %dx,    %dx
        movw    $2,     %bx   
        divw    %bx

        movb    %dl,    %dh   
        xorb    %dl,    %dl   
        movb    %al,    %ch   

        popw    %bx         
rp_read:
        movb    $0x1,   %al   
        movb    $0x2,   %ah
        int     $0x13
        jc      rp_read
        popw    %dx
        popw    %cx
        popw    %ax
        ret

.org    0x1fe,  0x90
.word   0xaa55

load.s

a.text
.globl        pm_mode
.org 0

pm_mode:
        movl    $0x10,        %eax
        movw    %ax,    %ds
        movw    %ax,    %es
        movw    %ax,    %fs
        movw    %ax,    %gs
        movw    %ax,    %ss
        movl    $0xa0000,        %esp

cld

movb    $0x07, %al
movl    $msg,  %esi
movl    $0xb8000,%edi

1:
        cmp     $0,    (%esi)
        je      1f
        movsb
        stosb
        jmp     1b
1:      jmp     1b
msg:
                .string "Hello World!\x0"

荆棘i 2022-10-06 12:02:32

我在进入保护模式之后只是让他打印了一个HELLO WORLD,没有用INT
但是我现在这段程序就是运行不起来,不知道怎么搞的

七色彩虹 2022-10-06 12:02:32

终于找到原因了,是因为我把0X0000处的BIOS中断表给覆盖了,改了加载地址和GDT地址,下面把测试通过的代码贴上来,请指教

boot.s

  1. .text
  2. .globl    start
  3. .set CODE_SEL, 0x08     #选择子cs
  4. .set DATA_SEL, 0x10       #选择子ds
  5. .set IDT_ADDR, 0x80000    #IDT位置
  6. .set IDT_SIZE, (256*8)  
  7. .set GDT_ADDR, (IDT_ADDR+IDT_SIZE)   #GDT位置(紧挨着IDT)
  8. .set GDT_ENTRIES, 5      #GDT数量
  9. .set GDT_SIZE, (8*GDT_ENTRIES)
  10. .set KERNEL_SECT, 2      #需要读取的扇区数
  11. .set STACK_BOT, 0xa0000   #最终的堆栈位置
  12. .code16
  13. start:
  14.         jmp        code
  15. #声明GDT
  16. gdt:   
  17.         .quad    0x0000000000000000
  18.         .quad    0x00cf9a010000ffff # cs
  19.         .quad    0x00cf92000000ffff # ds
  20.         .quad    0x0000000000000000
  21.         .quad    0x0000000000000000
  22. #48位的GDT描述
  23. gdt_48:
  24.         .word    .-gdt-1 #长度
  25.         .long    GDT_ADDR #位置
  26. code:
  27.         xorw    %ax,    %ax
  28.         movw    %ax,    %ds   
  29.         movw    %ax,    %ss   
  30.         movw    $0x1000,%sp   #设置临时的堆栈位置
  31. #将软盘中除启动扇区外的其他内容读到 es:bx处
  32.         movw    $0x1000,%ax  
  33.         movw    %ax,    %es
  34.         xorw    %bx,    %bx   
  35.         movw    $KERNEL_SECT,%cx  #需要读取多少扇区
  36.         movw    $1,     %si   #跳过启动扇区
  37. rd_kern:
  38.         call    read_sect    #读取扇区的函数(网上找的)
  39.         addw    $512,    %bx
  40.         incw    %si
  41.         loop    rd_kern
  42.         cli                 
  43.         cld                    
  44.         xorw    %ax,    %ax
  45.         movw    %ax,    %ds   
  46. #将GDT移动到指定位置
  47.         movw    $GDT_ADDR>>4,%ax   
  48.         movw    %ax,    %es      
  49.         movw    $gdt,   %si
  50.         xorw    %di,    %di         
  51.         movw    $GDT_SIZE>>2,%cx      
  52.         rep
  53.         movsl
  54. #打开A20地址线
  55. enable_a20:        
  56.         inb    $0x64,   %al   
  57.         testb  $0x2,    %al
  58.         jnz    enable_a20
  59.         movb   $0xbf,   %al
  60.         outb   %al,     $0x64
  61. #加载GDT
  62.         lgdt    gdt_48      
  63. #设置PE位      
  64.      
  65.         movl   %cr0,    %eax
  66.         orl    $0x1,    %eax
  67.         movl   %eax,    %cr0      
  68. #跳到保护模式(跳转到了被加载的扇区位置)
  69.         ljmp   $CODE_SEL, $0x0
  70. read_sect:
  71.         pushw   %ax
  72.         pushw   %cx
  73.         pushw   %dx
  74.         pushw   %bx
  75.         movw    %si,    %ax        
  76.         xorw    %dx,    %dx
  77.         movw    $18,    %bx   
  78.         divw    %bx
  79.         incw    %dx
  80.         movb    %dl,    %cl   
  81.         xorw    %dx,    %dx
  82.         movw    $2,     %bx   
  83.         divw    %bx
  84.         movb    %dl,    %dh   
  85.         xorb    %dl,    %dl   
  86.         movb    %al,    %ch   
  87.         popw    %bx         
  88. rp_read:
  89.         movb    $0x1,   %al   
  90.         movb    $0x2,   %ah
  91.         int     $0x13
  92.         jc      rp_read
  93.         popw    %dx
  94.         popw    %cx
  95.         popw    %ax
  96.         ret
  97. .org    0x1fe,  0x90
  98. .word   0xaa55

复制代码

load.s

  1. .text
  2. .globl        pm_mode
  3. .org 0
  4. pm_mode:
  5.         movl    $0x10,        %eax
  6.         movw    %ax,    %ds
  7.         movw    %ax,    %es
  8.         movw    %ax,    %fs
  9.         movw    %ax,    %gs
  10.         movw    %ax,    %ss
  11.         movl    $0xa0000,        %esp
  12. cld
  13. movb    $0x07, %al
  14. movl    $msg,  %esi
  15. movl    $0xb8000,%edi
  16. 1:
  17.         cmp     $0,    (%esi)
  18.         je      1f
  19.         movsb
  20.         stosb
  21.         jmp     1b
  22. 1:      jmp     1b
  23. msg:
  24.                 .string "Hello World!\x0"

复制代码

as -o boot.o boot.s
ld --oformat binary -N -e start -Ttext 0x7c00 -o boot.img boot.o
as -o load.o load.s
ld --oformat binary -N -e pm_mode -Ttext 0x10000 -o load.img load.o
cat boot.img load.img > final.img

用VMWARE加载 final.img 即可

[ 本帖最后由 shineyear 于 2007-5-30 11:13 编辑 ]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文