第2课 - Hello,DTOS!

主引导程序

    主引导程序是一段存储于主引导区( MBR)中的有效代码
    主引导程序是可以修改的,所以不是固件,它 是操作系统的一部分
    主引导程序是 启动操作系统的桥梁由汇编语言编写
    主引导程序 运行于实模式(地址都是实际的物理地址)
    主引导程序代码量 不能超过512字节(一般意义上的一个扇区的大小, 且包含结束标记0x55aa
    引导程序(英语:boot loader)位于电脑或其他计算机应用上,是指引导操作系统的程序。引导程序引导方式及程序视应用机型种类而不同。例如在普通的个人电脑上,引导程序通常分为两部分:第一阶段引导程序位于主引导记录(MBR),用以引导位于某个分区上的第二阶段引导程序,如NTLDR、BOOTMGR和GNU GRUB等。 摘自维基百科

主引导程序的开发

    

编程实现主引导程序

    要求使用汇编语言编写
    可独立运行于x86架构上(无操作系统)
    运行后在屏幕上打印“Hello,DTOS!”
    思路:
        将关键寄存器的值设为0(mov ax, 0)
        定义需要打印的数据(db "Hello,D.T.OS!")
        打印预定义好的字符数据(int 0x10)

汇编提示

    mov ax, 0              ; 将0赋值给ax寄存器
    mov byte [0xb800:0x01], 0x07  ; 将0x07处的一个字节赋值给内存0xb800<<4+0x01处(=0xb8001,注:0xb8000-0xbFFFF是留给显卡的32KB的地址)
    int 0x10            ; 触发0x10中断,对屏幕进行操作
    hlt                          ; 使CPU进入暂停状态
    $                            ; 当前指令行地址
    $$                          ; 当前汇编段起始地址,可以使用$$-$方式获得当前代码已经占用的字节数
    ;                               ; 汇编的单行注释符号为‘;’
    not_use macro
        多行注释           ; 我没有验证过
    endm

中断调用和函数调用的相识之处

    

MBR

    将汇编代码编译成二进制机器码(nasm boot.asm -o boot.bin)
    创建虚拟盘(bximage a.img -q -fd -size=1.44)
    将二进制代码写入虚拟盘起始位置(dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc)
    在虚拟机中将虚拟盘作为启动盘执行(vmware)

代码

 1 org 0x7c00                                        ; 从0x7c00处存储下面的代码
 2  
 3 start:                                            ; 汇编程序入口,相当于main();这里是用CS寄存器的值初始化SS、DS、ES寄存器以及设置存储msg标记的SI寄存器
 4     mov ax, cs                                    ; CS代码段寄存器(通常和IP寄存器配合使用),AX通用寄存器
 5     mov ss, ax                                    ; SS数据段寄存器
 6     mov ds, ax                                    ; DS堆栈段寄存器
 7     mov es, ax                                    ; ES附加段寄存器
 8    
 9     mov si, msg                                   ; SI源变址寄存器,此处用于记录msg标记的数据,此标记记录了MBR的地址(一般配合DS使用)
10 print:
11     mov al, [si]                                  ; 把SI寄存器中的值作为内存地址去寻找对应的数据放入al寄存器([si]相当于C语言的*si),要打印的字符存储于AL寄存器,字符颜色存储于BL寄存器
12     add si, 1                                     ; 指向下一个字符位置,相当于C语言打印字符时的递增
13     cmp al, 0x00                                  ; 比较指令,不保存结果,但是会影响标志位,这里的意义是判断字符串结束符
14     je last                                       ; 如果ZF标志位为0就跳转到last,意思是如果到了字符串结束符就停止打印(进入CPU暂停死循环)
15     mov ah, 0x0e                                  ; 配置0x10中断所需数据,对ah寄存器写入0x0e(显示字符并右移光标,到最后时自动换行)
16     mov bx, 0x0f                                  ; BX=BH+BL,BH设置页码,BL设置前景色;这里没发现存在的意义,注释掉未发现影响
17     int 0x10                                      ; 触发显示中断,打印字符
18     jmp print                                     ; 循环打印直至结束
19    
20 last:
21     hlt                                           ; 暂停指令,时钟信号会停止,CPU收到复位或中断信号后又会恢复
22     jmp last
23    
24 msg:
25     db 0x0a, 0x0a                               ; 设置两个换行
26     db "Hello, DTOS!"                         ; 设置打印字符串
27     db 0x0a, 0x0a
28     db 0x07, 0x07                                ; 设置两个响铃
29     times 510-($-$$) db 0x00                     ; 用0填充多余的空间
30     db 0x55, 0xaa                                ; 主引导区结束必须是0x55aa
将代码保存成boot.asm文本文件
以下操作在linux系统上,你或许需要安装相关软件(例如:nasm、bximage,其中dd是系统自带的命令)
使用 nasm boot.asm -o boo.bin命令编译代码
使用 bximage a.img -q -fd -size=1.44生成1.44MB的软盘
使用 dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc将数据写入软盘(bs=大小、count=次数、conv=连续写入不能有空)
设置虚拟机为软盘启动,并将a.img作为启动镜像 (下图是采用bochs虚拟机在linux上运行,下一篇介绍bochs相关的内容;你也可以使用vmware,不懂请自行度娘)
最后5行就是我们输出的内容 (注意Hello,DTOS!前后都有两个换行)
这个MBR没有关机功能,你需要硬件级别的关机
 

猜你喜欢

转载自www.cnblogs.com/Dua677/p/9046077.html