手写操作系统--主引导扇区以及内核加载器

news/2025/2/22 5:50:11/

在CPU上电后,会自动将cs:ip置为f000:fff0,下图就是一个计算机刚上电的模拟:

 ffff00这里开始的代码是BIOS自检,检查计算机的硬件完备性,做完这一切后将第一个扇区的内容复制到0x7c00的位置,并从0x7c00位置执行代码:

 0x7c00开始就放着我们的主引导扇区的代码。因为我的第一句代码是mov ax,0x0003,是占用3个字节,因此实际代码将会从0x7c02开始。

因此我们能接触的第一个操作系统代码就是编写这个主引导扇区。主引导扇区的功能主要是要将内核加载器加载到内存中。因此我们此次实验就模拟一个内核加载器,内核加载器的功能我们将慢慢完善。

;boot.asm[org 0x7c00]   ;告诉编译器代码从0x7c00位置开始
xchg bx,bx
mov ax, 3           ;清空屏幕
int 0x10; 初始化段寄存器
mov ax, 0
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00mov si, booting
call printmov edi, 0x1000; 读取的目标内存
mov ecx, 2; 起始扇区
mov bl, 4; 扇区数量call read_diskcmp word [0x1000], 0x55aa
jnz errorjmp 0:0x1002  ; 没问题则跳转到内核加载器; 阻塞
jmp $read_disk:; 设置读写扇区的数量mov dx, 0x1f2mov al, blout dx, alinc dx; 0x1f3mov al, cl; 起始扇区的前八位out dx, alinc dx; 0x1f4shr ecx, 8mov al, cl; 起始扇区的中八位out dx, alinc dx; 0x1f5shr ecx, 8mov al, cl; 起始扇区的高八位out dx, alinc dx; 0x1f6shr ecx, 8and cl, 0b1111; 将高四位置为 0mov al, 0b1110_0000;or al, clout dx, al; 主盘 - LBA 模式inc dx; 0x1f7mov al, 0x20; 读硬盘out dx, alxor ecx, ecx; 将 ecx 清空mov cl, bl; 得到读写扇区的数量.read:push cx; 保存 cxcall .waits; 等待数据准备完毕call .reads; 读取一个扇区pop cx; 恢复 cxloop .readret.waits:mov dx, 0x1f7.check:in al, dxjmp $+2; nop 直接跳转到下一行jmp $+2jmp $+2and al, 0b1000_1000cmp al, 0b0000_1000jnz .checkret.reads:mov dx, 0x1f0mov cx, 256; 一个扇区 256 字.readw:in ax, dxjmp $+2;  ;类似与nop空指令 只不过时钟周期会更长jmp $+2jmp $+2mov [edi], axadd edi, 2loop .readwretprint:mov ah, 0x0e
.next:mov al, [si]cmp al, 0jz .doneint 0x10inc sijmp .next.done:retbooting:db "Loading XJC_OS", 10, 13, 0; \n\rerror:mov si, .msgcall printhlt; 让 CPU 停止jmp $.msg db "Booting Error!!!", 10, 13, 0; 填充 0
times 510 - ($ - $$) db 0; 主引导扇区的最后两个字节必须是 0x55 0xaa
; dw 0xaa55
db 0x55, 0xaa

上述代码是一个完整的主引导扇区,它主要实现如下功能:

1,清空屏幕

2,在屏幕上输出一句加载内核

3,调用硬盘读写功能,将硬盘中的第二个扇区开始的内核加载器写入内存0x1000的位置

4,校检内核加载器的完备性,如果出现错误则跳转到输出错误语句

5,如果成功将控制权交给内核加载器。

这样主引导扇区的使命就完成了。接下来我们模拟实现一个小型的内核加载器

;loader.asm[org 0x1000]   ;程序将从0x1000开始执行dw 0x55aamov si,loading
call print1jmp $print1:mov ah, 0x0e
.next:mov al, [si]cmp al, 0jz .doneint 0x10inc sijmp .next
.done:retloading:db "os loading success!!!", 10, 13, 0; \n\r

这个内核加载器并没有实现很多功能,只是模拟主引导扇区是否成功加载内核加载器。如果成功加载将会在屏幕上输出一句“os loading success!!!”。我们编译这个asm看看二进制文件的样子:

 这是编译完的内核加载器的二进制文本,我们去验证一下是否加载到0x1000的内存位置:

屏幕输出了内核加载器的内容,并且确实加载进来了,因此实验成功。

 


http://www.ppmy.cn/news/741256.html

相关文章

github Copilot使用及代理设置

使用前先保证自己能正常访问github.com,找个科学上网工具 找到系统的hosts文件做个配置,在https://www.ipaddress.com/ 中搜索github.com和api.github.com 140.82.112.4 github.com 140.82.113.6 api.github.com 我的搜索完是上面两个ip,加入…

解决软件注册机被win10杀灭问题

某些激活软件会被win10 的病毒防护功能误认为是病毒杀灭,例如AutoCAD的注册机等等,解决这类问题的方法是设置一个排除项,也就是说设置一个文件夹让win10的病毒防护功能不扫描该文件。步骤如下 1、打开设置中的更新和安全选项,选择…

CAD C#二次开发自动注册代码片段

## **自动注册插件,CAD启动时自启**重新编译生成DLL在CAD中使用NetLoad第一次加载编译好的DLL后,在CAD中执行RegisterCustomApp命令进行插件注册,注册成功,此时可以在注册表中看到已经注册的程序执行UnregisterCustomApp卸载注册的…

【板栗糖GIS】win11—提示无法成功完成操作,因为文件包含病毒或潜在的垃圾软件

【板栗糖GIS】win11—提示无法成功完成操作,因为文件包含病毒或潜在的垃圾软件 win11再一次把cad的注册机给自动删除了,好气,以前的解决办法都是把注册表放入电脑的排除项中,然后重新解压出来。 更新了win11的系统,找排…

【vue】Vue3中使用函数调用组件内函数和创建组件【超详细】

uniappuview vue3typescript版本,使用函数方式调用和创建组件,并使用组件内的方法 项目场景 今天突然觉得在视图上应用组件,然后在script脚本里操作组件这方式特别的麻烦。因为每次使用组件时都要进行应用,不管你用不用你都要引…

注册机解压缩后为空文件解决方案

注册机解压缩后为空文件解决方案 太长不看版现象解决方案 太长不看版 解决方案:Windows安全中心-病毒和威胁防护-保护历史记录-还原被系统隔离的威胁 安利:Autodesk公司软件(包括CAD,Inventor等)可在官网获取学生免费…

同一局域网内IP 192.168.1.10 和 IP 10.10.10.8 可以互相访问吗?

同一局域网内IP 192.168.1.10 和 IP 10.10.10.8 可以互相访问吗? 1、网上邻居的方式: 鼠标点击 我的电脑 属性 计算机名,查看一下 计算机名(这个可以点击更改,自己设定和更改) 查看一下工作组,一…

【前端知识】React 基础巩固(十七)——组件化开发(一)

React 基础巩固(十七)——组件化开发(一) 组件化开发 什么是组件化开发? 分而治之的思想将一个页面拆分成一个个小的功能块将应用抽象成一颗组件树 React的组件相对于Vue更加的灵活和多样 按照不同的方式可以分为很多类组件 根据组件的定义…