免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 14748 | 回复: 18
打印 上一主题 下一主题

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

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-05-24 13:39 |只看该作者 |倒序浏览
1.在一个固定地址处处创建GDT,设置堆栈积存器地址
2.读取硬盘中的load.s到0x0处
3.打开A20地址线,设置积存器PE位,进入保护模式
4.跳转到0x0处执行load.s

注:设load.s为内核程序

论坛徽章:
0
2 [报告]
发表于 2007-05-24 19:07 |只看该作者
原帖由 shineyear 于 2007-5-24 13:39 发表于 1楼  
1.在一个固定地址处处创建GDT,设置堆栈积存器地址
2.读取硬盘中的load.s到0x0处
3.打开A20地址线,设置积存器PE位,进入保护模式
4.跳转到0x0处执行load.s

注:设load.s为内核程序


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

论坛徽章:
0
3 [报告]
发表于 2007-05-25 11:23 |只看该作者
我怎么感觉IDT并不是必须的呢?

论坛徽章:
0
4 [报告]
发表于 2007-05-28 18:05 |只看该作者
关了中断就可以不用idt,但这样比较无趣。

论坛徽章:
0
5 [报告]
发表于 2007-05-29 01:29 |只看该作者
请问我可不可以在启动的时候(跳入保护模式之前)把内核加载到0X0000位置呢?我尝试着这么做了但好象不行,是不是必须关中断才行?

论坛徽章:
0
6 [报告]
发表于 2007-05-29 08:54 |只看该作者
在pc中,0x0000处存放中断向量表,不能加载到那里,建议先在google上搜一下bios初始化完成后的内存布局

论坛徽章:
0
7 [报告]
发表于 2007-05-29 18:30 |只看该作者
原帖由 shineyear 于 2007-5-25 11:23 发表于 3楼  
我怎么感觉IDT并不是必须的呢?


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

论坛徽章:
0
8 [报告]
发表于 2007-05-29 23:05 |只看该作者
我还是把代码贴上来吧


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"

论坛徽章:
0
9 [报告]
发表于 2007-05-29 23:07 |只看该作者
我在进入保护模式之后只是让他打印了一个HELLO WORLD,没有用INT
但是我现在这段程序就是运行不起来,不知道怎么搞的

论坛徽章:
0
10 [报告]
发表于 2007-05-30 00:24 |只看该作者
终于找到原因了,是因为我把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 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP