zoukankan      html  css  js  c++  java
  • 自制操作系统:引导扇区的实现

    本书依靠的教材是于渊的《Orange'S:一个操作系统的实现》

    实验环境及工具

    • ArchLinux(windows也可以)
    • 代码编辑器Emacs(你尽情使用自己喜欢的编辑器)
    • nasm (一个开源的汇编器,可以从sourceforge下载,也可以从Linux发行版的软件仓库安装)

    思路:

    • 写一段汇编代码,输出 Hello, World
    • 将该段代码写入软盘镜像的第一个扇区
    • 安装virtualbox创建一个操作系统,从软盘镜像引导,查看结果

    引导区代码

        ;; BIOS会把512字节的引导扇区加载到 0000:7c00 处,
        ;; 然后跳转到0000:7c00处,将控制权交给引导代码。
        org 07c00h                  ;这一行告诉编译器,我们的代码将被加载到7c00处。
        mov ax, cs                  ;将代码段寄存器的值送入AX
        mov ds, ax                  ;将数据段的地址置为代码段的地址?
        mov es, ax                  ;将附加段的地址置为代码段的地址?
        call  DispStr               ;调用显示字符串例程
        jmp $                       ;无限循环, $表示当前行编译后的地址
        ;; 以上就是整个程序的执行过程了
        ;; 下面是DispStr子程序
    DispStr:
        mov ax, BootMessage         ;将字符串首地址传给寄存器ax
        mov bp, ax                  ;CPU将用ES:BP来寻址字符串
        mov cx, 16                  ;通过CX,CPU知道字符串的长度
        mov ax, 01301h              ;AH=13表示13号中断, AL=01H,表示目标字符串仅仅包含字符,属性在BL中包含,移动光标
        mov bx, 000ch               ;黑底红字, BL=0CH,高亮
        mov dl, 0                   ;dh表示在第几行显示,dl表示第几列显示
        int 10h                     ;BIOS的10H中断的13号中断用于显示字符串
        ret
    BootMessage:    db "Hello, OS world!" ;对NASM来讲,标号和变量的作用一样, db表示define byte
        ;; $当前行被汇编后的地址,$$表示一个section开始处的地址,本程序只有一个section,所以指0x7c00
        times 510-($-$$) db 0           ;填充剩下空间,使生成的二进制恰好为512字节
        dw 0xaa55                       ;结束标志,如果发现扇区以0xAA55结束,则BIOS认为它是一个引导扇区,dw表示define word
    

    关于中断显示字符串的细节,可参见使用BIOS中断显示字符串笔记(int 10h 13号中断)

    编译生成二进制

    需要nasm。如果你使用Linux,可以直接从软件仓库安装。
    nasm即可以从汇编代码生成目标代码,也带了一个反汇编工具ndisasm, 可以从目标代码生成汇编代码。

    编译我们的扇区代码生成二进制:

    nasm boot.asm -o boot.bin
    

    写入软盘的第一个扇区

    我们用软盘镜像来模拟软盘。

    dd if=/dev/zero of=emptydisk.img bs=512 count=2880 #生成空白软盘镜像文件
    dd if=boot.bin of=boot.img bs=512 count=1 #用 bin file 生成对应的镜像文件
    dd if=emptydisk.img of=boot.img skip=1 seek=1 bs=512 count=2879 #在 bin 生成的镜像文件后补上空白,成为合适大小的软盘镜像
    

    这样,我们引导系统用的虚拟软盘就准备好了。

    安装virtualbox,建立系统

    可以直接从Linux软件仓库安装virtualbox。

    把当前用户加入vboxusers组:gpasswd -a <username> vboxusers

    启动virtualbox,可能提示vboxdrv未能成功加载。如果发生这种情况,需要重新编译vboxdrv模块。安装linux-headersdkms,然后sudo dkms autoinstall就会编译生成vboxdrv模块。

    手动执行sudo modprobe vboxdrv加载vboxdrv模块,启动virtualbox应该不会有问题了。

    建立一个虚拟机,有没有硬盘都可以,增加一个软驱,把我们的boot.img加载到软驱中,启动虚拟机,成功的话,可以看到:

    带有欢迎信息的引导界面

    virtualbox可能出现的问题:

    1. Failed to open a session for the virtual machine a. Failed to load VMMR0.r0 (VERR_SUPLIB_OWNER_NOT_ROOT). Unknown error creating VM (VERR_SUPLIB_OWNER_NOT_ROOT). 解决方法:sudo chown -R root:root /usr/lib/virtualbox

    2. Effective UID is not root. 解决方法: sudo chmod 4711 /usr/lib/virtualbox/VirtualBox

    参见: https://www.virtualbox.org/ticket/7889

    参考文章:

    Hacking 《自己动手写操作系统》Chapter 1&2

  • 相关阅读:
    mysql数据库操作
    django
    django-rest framwork
    Maven项目POM文件错误,提示“Plugin execution not covered by lifecycle configuration”的解决方案
    [Flutter] FFI之生成Ansi字符串指针
    多label实现准确率和召回率
    pickle.dump()和pickle.load()
    numpy.take()
    通俗易懂的lambda表达式,不懂来找我!
    collections(python常用内建模块)
  • 原文地址:https://www.cnblogs.com/jiqingwu/p/os_boot_sector.html
Copyright © 2011-2022 走看看