• 自己写操作系统---bootsector篇


    其实博主本来想在寒假自己写一个OSkernal的,高高兴兴的影印了本《一个操作系统的实现》。

    然后又去图书馆借来《30天自制操作系统》和《X86/X64体系探索编程》,结果还是被自己的懒惰给打败了。。。

    原本我感觉自制力还不错的,好歹春节前也看了很多东西,但是过了一个春节就懒散了。。

    当然也有一部分原因是因为《30天》写的实在是太乱了。。缺少一个理论的上的指导和概括,看的云里雾里。

    再就是汇编。。。博主原来只学过8086和AT&T汇编啊。。。这下又来个nasm汇编。。这学期还开了个ARM汇编。。Orz。。。

    不过nasm汇编真的是很好用,它还有类似c++默认构造的宏指令,很强大啊!

    当然了,如果我不是一个喜欢深究的人,也可以用《30天》提供的工具也能很快的写出来。但我毕竟还是有点追求的。。

    废话了这么多,开始进入主题吧。。

    首先,bootsector是个什么东西呢?其实就是个引导的作用,引导到bootloader或者是操作系统上。

    注意,bootsector不是双系统的那种引导,而是在它之前的程序。

    那么bootsector程序是如何发挥作用的呢?这得从计算机的开机流程讲起。

    还记得学校上的操作系统教材上面说,计算机开机加电直接就去读取硬盘上的操作系统。(但其实漏掉了好些东西啊!!国产教材误人子弟啊!!!!)

    其实一开机,并不是直接读硬盘,而是从主板的BIOS启动。

    (BIOS不知道可以自己百度,它还把一些自带的中断加载到了内存中)

    上电后,BIOS的ROM中程序通过硬件加载到内存。

    根据BIOS的ROM中的程序,来检测相关硬件是否安装正确。然后才是寻找操作系统。

    完整流程如下:

    bios->bootsector->bootloader->kernel(后面两个以后再说)

    这样就有问题了,BIOS怎么知道操作系统放在哪呢?

    这需要了解通用计算机所遵循的规范了,bios只从硬盘的第一个扇区读取并加载程序。

    扇区又是什么呢?这里我简单的带着你联想一下.

    由于原来32位地址总线只能寻址4G的大小。那么硬盘不断发展,64位总线还没出现,但是硬盘大小超过4g。

    所以多出来的部分就没有用了!但是工程师很聪明,所以就让每个地址存储的内容更多吧!(自己回顾组成原理)

    所以,硬盘就出现了所谓的扇区!一般一个扇区的大小为512b。4G*512b=2t的样子。

    这样来算,现在的发展已经够用了,以后换到64位系统就不用担心地址不够了。

    回到正题。由于BIOS只能自动读一个扇区,512b的大小。

    这么点大小肯定装不下操作系统~所以只好用bootsector来转让计算机使用的权力了。

    于是我们就清楚了bootsector的作用----读入硬盘上的其他程序,并将cpu交给它。

    下面是我写的bootsector。由于没有文件系统也不想用fat12,所以读取loader的位置是我自己随便定的。

    如果fat12那一段不注释的话,U盘就可以被识别了,但是U盘中的内容都是乱的~~~

    linux下可以用dd命令直接写到你的U盘中去。

    dd if=$(OBOOT) of=$(DEVICE) bs=512 count=1 conv=notrunc
    OBOOT表示生成文件,直接用nasm汇编生成.bin文件即可。

    DEVICE就是你U盘在linux下的路径了。

    然后就可以通过U盘启动,来执行你的bootsector了~

    1.  
      %include "boot.inc"
    2.  
      %ifdef DEBUG
    3.  
      org 0100h ;07c00h 0100
    4.  
      %else
    5.  
      org 07c00h
    6.  
      %endif
    7.  
      jmp short LABEL_START
    8.  
      nop
    9.  
       
    10.  
      ;head of FAT12
    11.  
      ; BS_OEMName DB 'meiboyu ' ; OEM String, 必须 8 个字节
    12.  
      ; BPB_BytsPerSec DW 512 ; 每扇区字节数
    13.  
      ; BPB_SecPerClus DB 1 ; 每簇多少扇区
    14.  
      ; BPB_RsvdSecCnt DW 1 ; Boot 记录占用多少扇区
    15.  
      ; BPB_NumFATs DB 2 ; 共有多少 FAT 表
    16.  
      ; BPB_RootEntCnt DW 224 ; 根目录文件数最大值
    17.  
      ; BPB_TotSec16 DW 2880 ; 逻辑扇区总数
    18.  
      ; BPB_Media DB 0xF0 ; 媒体描述符
    19.  
      ; BPB_FATSz16 DW 9 ; 每FAT扇区数
    20.  
      ; BPB_SecPerTrk DW 18 ; 每磁道扇区数
    21.  
      ; BPB_NumHeads DW 2 ; 磁头数(面数)
    22.  
      ; BPB_HiddSec DD 0 ; 隐藏扇区数
    23.  
      ; BPB_TotSec32 DD 0 ; wTotalSectorCount为0时这个值记录扇区数
    24.  
      ; BS_DrvNum DB 0 ; 中断 13 的驱动器号
    25.  
      ; BS_Reserved1 DB 0 ; 未使用
    26.  
      ; BS_BootSig DB 29h ; 扩展引导标记 (29h)
    27.  
      ; BS_VolID DD 0 ; 卷序列号
    28.  
      ; BS_VolLab DB 'MOS by mby '; 卷标, 必须 11 个字节
    29.  
      ; BS_FileSysType DB 'FAT12 ' ; 文件系统类型, 必须 8个字节
    30.  
       
    31.  
      times 18 db 0
    32.  
      LABEL_START:
    33.  
      mov ax, cs
    34.  
      mov ds, ax
    35.  
      mov es, ax ;make all pointer point null place
    36.  
       
    37.  
      mov dx,0
    38.  
      mov ax,BootMessage
    39.  
      mov cx,BMlength
    40.  
      mov dh,0
    41.  
       
    42.  
      call showStr ;show string function
    43.  
       
    44.  
      call Loader ;Loader getting loading
    45.  
      jmp fin ;while(1)
    46.  
       
    47.  
      Loader:
    48.  
      mov ax,4200h
    49.  
      mov dl,0x80
    50.  
      mov cx,0
    51.  
      mov ds,cx
    52.  
      mov si,DAP
    53.  
      int 0x13
    54.  
      jc LoaderError
    55.  
       
    56.  
      mov ax,0 ;clean es register
    57.  
      mov es,ax
    58.  
       
    59.  
      mov dx,0
    60.  
      mov ax,LSuccess
    61.  
      mov cx,LSlength
    62.  
      mov dh,1
    63.  
      call showStr
    64.  
       
    65.  
      jmp BaseOffLoader:SetOffLoader ;jump to Loader !
    66.  
       
    67.  
      LoaderError:
    68.  
      mov ax,0
    69.  
      mov es,ax
    70.  
      mov ax,LError
    71.  
      mov cx,LElength
    72.  
      mov dh,1
    73.  
      call showStr
    74.  
      fin:
    75.  
      hlt
    76.  
      jmp fin
    77.  
       
    78.  
      showStr:
    79.  
      mov bp,ax
    80.  
      mov ax,01301h
    81.  
      mov bx,000Fh
    82.  
      mov dl,0
    83.  
      int 10h
    84.  
      ret
    85.  
       
    86.  
      LSuccess: db "Loader OK!"
    87.  
      LSlength equ $-LSuccess
    88.  
       
    89.  
      LError: db "Booting Loader get wrong!"
    90.  
      LElength equ $-LError
    91.  
       
    92.  
      BootMessage: db "Boot Sector Start!"
    93.  
      BMlength equ $-BootMessage
    94.  
       
    95.  
      DAP:
    96.  
      db 16 ;packet size
    97.  
      db 0 ;must 0
    98.  
      dw 100 ;number of block need to read
    99.  
      dw 0 ;the offset
    100.  
      dw 8000h ;the segment address
    101.  
      dw 1h ;start block
    102.  
      dw 0
    103.  
      dw 0
    104.  
      dw 0
    105.  
       
    106.  
       
    107.  
      times 510-($-$$) db 0
    108.  
      dw 0xaa55

    程序短,所以懒得用宏了。。这样对于新手看着也方便。

    具体汇编的内容很简单,我就不讲了,这里说一下我写这个遇到的个坑。。。

    使用BIOS的int 13h+al=02h的时候,在真机上是无法加载loader的!!软盘跟U盘还是有区别的!

    我看《一个操作系统 的实现》和《30天》的时候,就是这里。。他们都使用的是软盘,但是用U盘就有问题!!

    于是发现要用扩展BIOS中断,详细的可以去google扩展BIOS中断。(我记得我是在wiki上看到的,但是现在找不到了)

    当然看我的代码也可以~

    bootsector就介绍到这里了。过几天我再来写loader的部分~

    恩。。现在正在写,并且写图形化界面的时候又遇到坑了。。

    PS:

    装过win+linux双系统的知道,得先装windows再装linux。

    我估计就是windows直接重写bootsetor,然后直接引导到他的loader了,而linux的引导程序grub会识别原来的系统。

  • 相关阅读:
    toj 1410. Euclid's Game 夜
    hdu 1404 Digital Deletions 夜
    hdu 1536 SNim 夜
    1180. Stone Game 夜
    hdu 1729 Stone Game 夜
    一个有价值的 Sharepoint WebPart 页签部件
    开始 MS Project & P3 E/C 探讨历程!
    cvccomplextype.3.2.2: Attribute 'singleton' is not allowed to appear in element 'bean
    启迪技术
    上传图片:
  • 原文地址:https://www.cnblogs.com/xiongwei/p/9648070.html
Copyright © 2020-2023  润新知