一步一步实现一个简单的OS(进入保护模式)

这块的基础至少,网上太多了,自己看去吧,

废话不多说,直接贴代码

     # bootasm.S
     # 加载Setup模块
 
    .set SETUP_SEG,      0x0000      # SETUP模块加载段地址
    .set SETUP_OFF,      0x7D00      # SETUP模块加载偏移地址

    .globl start
start:   # 入口地址
    .code16  # 声明是16位代码(为什么启动时要用16位代码。。。。自己百度去,,,)

    cld     # 字符串运算方向,(具体的,百度吧,基础)

    # 初始化各个段寄存器
    xorw    %ax, %ax
    movw    %ax, %ds
    movw    %ax, %es
    movw    %ax, %ss

    movw    $start, %sp

    # 保存引导驱动器号
    movb    %dl, (bootdrv)

    # 清屏
    movw    $0x02, %ax
    int     $0x10

    # 显示信息
    movw    $str, %si
    call    puts

    # 读第二个扇区,到内存的0x07D00(0x0000:0x7D00)处, 两个扇区
    movl    $1, %eax    # 扇区号
    movw    $2, %cx     # 扇区数
    movw    $SETUP_SEG, %bx    # buffer 地址
    movw    %bx, %es
    movw    $SETUP_OFF, %bx

    call    readdisk

    # 跳转到刚刚加载到内存中的SETUP模块
    ljmp     $SETUP_SEG, $SETUP_OFF

#
# 字符串显示函数
# 输入:
#       ds:si = 字符串地址
#
puts:
    movw     $0x07, %bx
    movb     $0x0E, %ah
1:
    lodsb
    orb      %al, %al
    jz       1f
    int      $0x10
    jmp      1b
1:
    ret

#
# 读磁盘扇区
#
# 输入:       eax     = 要读LBA扇区号
#             cx      = 扇区数(一次读入的字节数不能大于64KB)
#             es:bx   = 数据缓存区
#
readdisk:
    pushal
    movb       (bootdrv), %dl

    pushl       $0
    pushl       %eax

    pushw       %es
    pushw       %bx

    pushw       %cx
    pushw       $0x0010
    movb        $0x42, %ah
    movw        %sp, %si
    int         $0x13

    addw        $0x10, %sp
    popal
    ret

bootdrv:
    .byte   0

str:
    .string "in the boot code\n\r"

    # setupasm.S
    # 开启保护模式

    #include "asm.h"

    .set SETUP_SEG,      0x0000      # SETUP模块加载段地址
    .set SETUP_OFF,      0x7D00      # SETUP模块加载偏移地址

    .set PROT_MODE_CSEG, 0x8         # 代码段选择符
    .set PROT_MODE_DSEG, 0x10        # 数据段选择符
    .set CR0_PE_ON,      0x1         # 保护模式开启标志位

    .globl start
start:   # 入口地址
    .code16  # 声明是16位代码(为什么启动时要用16位代码。。。。自己百度去,,,)

    cld     # 字符串运算方向,(具体的,百度吧,基础)

    # 初始化各个段寄存器
    movw    %cs, %ax
    movw    %ax, %ds
    movw    %ax, %es
    movw    %ax, %ss

    movw    $start, %sp

    # 显示信息
    movw    $info, %si
    call    puts

# --------------------------------------------------------------------------#
#   下面是进入保护模式的代码,和网上的多少有些不一样。。。                  #
# --------------------------------------------------------------------------#
    # 关中断
    cli     

    # 加载GDTR
    lgdt    gdtdesc

    # 保护模式标志位置位
    movl    %cr0, %eax
    orl     $CR0_PE_ON, %eax
    movl    %eax, %cr0

    # 长跳转,进入32位代码段, 开启保护模式在这条以后就彻底搞定了
    ljmp    $PROT_MODE_CSEG, $start32

#
# 字符串显示函数
# 输入:
#       ds:si = 字符串地址
#
puts:
    movw     $0x07, %bx
    movb     $0x0E, %ah
1:
    lodsb
    orb      %al, %al
    jz       1f
    int      $0x10
    jmp      1b
1:
    ret

# --------------------------------------------------------------------------#
#   这个就是32位保护模式的代码了。。。                                      #
# --------------------------------------------------------------------------#
    .code32     # 下面的代码编译为32位的
start32:
    # 初始化保护模式下的各个段的段寄存器
    movw    $PROT_MODE_DSEG, %ax
    movw    %ax, %ds
    movw    %ax, %es
    movw    %ax, %fs
    movw    %ax, %gs
    movw    %ax, %ss

    movl    $start32, %esp      # 之前的代码没用了,让堆栈覆盖了吧

    # 得显示个东西,这样就知道CPU是不是真的跑到这里了
    # 那本书上这一块显示的是一个红色的P,
    # 那咱们这里,为了证明是原创,就显示一个绿色的P吧,嘿嘿
    movw    $0x0A00 | 'P', (0xB8100)

    # 好了,到这里死循环吧,下节,弄C语言的,这样看起来就简单多了
    # 其实,我觉得,还是这个简单
1:
    hlt
    jmp     1b

info:
    .string "in the setup code!!!\n\r"

    # GDT,需要4字节对齐
    .p2align 2
gdt:
  SEG_NULLASM                             # 空的,保留了
  SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)   # 代码段
  SEG_ASM(STA_W, 0x0, 0xffffffff)         # 数据段

gdtdesc:
  .word   0x17                            # gdt长度减1
  .long   gdt            # gdt物理地址

具体代码到群里面找。。。。。。。

545250960

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值