【操作系统】半小时写一个微型操作系统-写一个启动扇区并且导入到软盘镜像中

一.什么是启动扇区

        我们使用软盘来启动操作系统时,系统首先就是从软盘的第一个扇区中开始读取数据,也就是第0面,0磁道的第0个扇区,软盘的每个扇区为512个字节的大小,如果最后两个字节为0xaa55(当BIOS看到这两个字节时,就认为是引导扇区的结束标志),则代表该两个字节前的机器指令都是启动扇区的指令,以0x00开头一直到0xaa55这512个字节的扇区就称之为启动扇区

二.引导扇区的程序编写

        代码(程序名称为boot.S)以及注释如下:

.code16
.text
        mov     %cs,%ax
        mov     %ax,%ds  
        mov     %ax,%es  #将寄存器ds和es同时指向与cs相同的段,使得后续在进行数据操作时能定位到正确的位置
        call    DispStr  #调用DispStr函数
        jmp     .  #进入死循环
DispStr:  
        mov     $BootMessage,%ax
        mov     %ax,%bp
        mov     $16,%cx
        mov     $0x1301,%ax
        mov     $0x00c,%bx
        mov     $0,%dl
        int     $0x10
        ret
BootMessage:.ascii  "Hello, OS world!"
.org    510
.word   0xaa55

        DispStr函数的注释如下:

DispStr:  
        mov     $BootMessage,%ax #将字符串变量“BootMessage”的首地址传给寄存器ax
        mov     %ax,%bp #使用寄存器ES:BP保存字符串的地址
        mov     $16,%cx  #保存字符串的长度
        mov     $0x1301,%ax #寄存器ax高位为 0x13h,低位为0x01h
        mov     $0x00c,%bx #设置页号为0(高位0X0h),字符串颜色为红色高亮(低位0x0ch)
        mov     $0,%dl
        int     $0x10 #10h号中断
        ret

         剩下的代码注释如下:

BootMessage:.ascii  "Hello, OS world!"  #字符串函数
.org    510  #用0x00填满剩下的字节,一直到第510个字节
.word   0xaa55  #剩下的两个字节填0xaa55

三.连接脚本的编写

        要想将一个程序编译成可执行文件,我们需要经过类似中间代码生成、连接等步骤(可以参考之前写过的一篇文章:【c语言】从高级语言到可以执行的EXE程序的编译过程),所以,在编译之前,我们还需要编写一个连接脚本(名称为solrex_X86.ld),代码如下:

SECTIONS
{
. = 0x7c00;
.text :
{
  _ftext = .;
} = 0
}

        当BIOS发现了引导分区(以0xaa55结尾的前512个字节的扇区)之后,就会把这512个字节的内容转载到内存的0000:7c00处(可以参考之前写过的一篇文章:【操作系统】操作系统的启动都干了些什么),然后跳转到0000:7c00处将控制权彻底交给这段引导代码中,所以该连接脚本的功能就是在进行连接时,将程序入口设置到内存0000:7c00的位置,而如果我们希望将代码放置到其他地址空间时,就可以直接修改连接脚本的地址即可。

四.Makefile脚本编写

        下一步我们编写Makefile脚本,用于将高级语言(.S)编译成中间文件(.o),再将连接脚本(.ld)和中间文件(.o)连接编译成可执行文件(.elf),最后将可执行文件写入到软盘镜像中(.img),代码如下:

CC=gcc
LD=ld
LDFILE=solrex_X86.ld  #连接脚本
OBJCOPY=objcopy

all: boot.img

boot.o: boot.S  #生成中间文件
        $(CC) -c boot.S

boot.elf: boot.o  #连接脚本+中间文件=可执行文件
        $(LD) boot.o -o boot.elf -e c -T$(LDFILE)

boot.bin: boot.elf  #移除可执行文件中没有用到的块
        @$(OBJCOPY) -R .pdr -R .comment -R.note -S -O binary boot.elf boot.bin

boot.img: boot.bin   #生成软盘镜像
        @dd if=boot.bin of=boot.img bs=512 count=1
        @dd if=/dev/zero of=boot.img skip=1 seek=1 bs=512 count=2879

clean:
        @rm -rf boot.o boot.elf boot.bin boot.img

        使用指令:

make

        进行编译,输出如下:

         最后即生成一个软盘镜像(boot.img)和一些中间文件:

 五.虚拟机VXBox开启镜像

        我们在虚拟机上新建一个虚拟电脑,然后按照推荐一直点下一步:

       创建完成后,我们选择虚拟电脑的“设置”项,添加一个虚拟软盘:

         点击”添加虚拟软驱“,然后点击”注册“,将你先前编译的boot.img进行注册操作:

         注册完成后选择对应的软盘镜像,即可保存退出:

        为了让系统优先导入我们的软盘镜像,我们可以将控制器:IDE整个删除,使得我们的镜像处于最高优先级:

        最后我们直接点击“启动”,即可看见先前编写的字符串黑底红字!!

        恭喜!你已经踏入了编写操作系统的第一步!

猜你喜欢

转载自blog.csdn.net/qq_41884002/article/details/130005878