您的位置:首页 > 其它

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

2016-03-03 10:12 363 查看
这块的基础至少,网上太多了,自己看去吧,

废话不多说,直接贴代码

# 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: