操作系统实现-boot.asm实现
博客网址:www.shicoder.top
微信:18223081347
欢迎加群聊天 :452380935
这一次我们进入操作系统实现的真实编码, 这一次主要是完善对boot.asm文件的全部实现,开始吧。。。
首先我们先来理一下boot.asm需要干什么
- 打印出
Booting System...
- 实现磁盘读写
- 将后续的
loader.asm
所在的区域读入到0x1000
处,然后跳转进入loader.asm
程序 - 开始执行
loader.asm
程序(这一节我们下次实现)
实模式下的print
在我们平时编写c语言时候,可以直接使用,但是在boot.asm中,完全就没有可以用库函数,因此为了在开始打印处start boot,我们需要自己实现print
先来看下代码把
mov si, booting
call print
print:
mov ah, 0x0e
.next:
mov al, [si]
cmp al, 0
jz .done
int 0x10
inc si
jmp .next
.done:
ret
booting:
db "Booting System...", 10, 13, 0; \n\r
这段程序主要使用使用BIOS的int 10h
来实现一个print
功能,al
寄存器存储要显示的字符串
磁盘读写
因为boot.asm
在主引导扇区,磁盘内存太小,不能在boot.asm
中实现loader.asm
的功能,因此我们将loader.asm
保存在磁盘的一个地方,在boot.asm
中利用磁盘读的方式,将代码读入到内存的一个区域,然后跳转到那个地方
先来看下磁盘读的功能实现
; 函数参数
; edi 将磁盘内容读到哪里
; ecx 从磁盘哪一个扇区开始
; bl 要读多少个扇区
read_disk:
; 设置读写扇区的数量
; 0x1f2 是硬盘控制端口,表示读写扇区的数量
mov dx, 0x1f2
mov al, bl
; 写端口用OUT指令 将al的值写入到dx端口
out dx, al
inc dx; 0x1f3 起始扇区前8位端口
; 因为ecx为起始扇区
; ecx中的cl就是0-7位
mov al, cl; 起始扇区前8位
out dx, al
inc dx; 0x1f4 起始扇区中8位端口
shr ecx, 8 ;右移8位
mov al, cl; 起始扇区中8位
out dx, al
inc dx; 0x1f5 起始扇区高8位端口
shr ecx, 8 ;右移8位
mov al, cl; 起始扇区高8位
out dx, al
inc dx ;0x1f6
shr ecx, 8
and cl, 0b1111 ;将高4位置为0,对应起始扇区的24-27位
mov al,0b1110_0000 ;第4位为0,表示主盘,第6位为1,表示LBA,5-7位必须为1
; 将al和cl合二为一,放在al中
or al, cl
out dx, al
inc dx ;0x1f7
mov al, 0x20 ;表示读硬盘
out dx, al
xor ecx, ecx ;清空ecx
mov cl, bl ;得到写扇区的数量
; loop指令会检查ecx是否为0 cl在ecx里面
.read:
push cx ;保存下,因为函数里面使用了
call .waits ;等待数据准备完毕
call .reads ;读取一个扇区
pop cx ;恢复
loop .read
ret
.waits:
mov dx, 0x1f7 ;读0x1f7端口
.check:
in al, dx ;将dx端口的值放入al中
jmp $+2 ;直接跳转到下一行 其实什么都没做,就是为了延迟一下
jmp $+2
jmp $+2
and al, 0b1000_1000 ;获得al的第3位和第7位
cmp al, 0b0000_1000 ;测试是否第7位为0,第3位为1 硬盘不繁忙,数据准备完毕
jnz .check ;数据没准备好
ret
.reads:
mov dx, 0x1f0 ;用于读写数据
mov cx, 256 ;一个扇区256字节
; loop指定会检查ecx cx在ecx里面
.readw:
in ax, dx
jmp $+2 ;直接跳转到下一行 其实什么都没做,就是为了延迟一下
jmp $+2
jmp $+2
; edi表示读取的目标内存
mov [edi], ax
; 因为ax是16bit,2个字节,所以edi+2
add edi, 2
loop .readw
ret
下面是磁盘的相关端口
Primary 通道 | Secondary 通道 | in 操作 | out 操作 |
---|---|---|---|
0x1F0 | 0x170 | Data | Data |
0x1F1 | 0x171 | Error | Features |
0x1F2 | 0x172 | Sector count | Sector count |
0x1F3 | 0x173 | LBA low | LBA low |
0x1F4 | 0x174 | LBA mid | LBA mid |
0x1F5 | 0x175 | LBA high | LBA high |
0x1F6 | 0x176 | Device | Device |
0x1F7 | 0x177 | Status | Command |
- 0x1F0:16bit 端口,用于读写数据
- 0x1F1:检测前一个指令的错误
- 0x1F2:读写扇区的数量
- 0x1F3:起始扇区的 0 ~ 7 位
- 0x1F4:起始扇区的 8 ~ 15 位
- 0x1F5:起始扇区的 16 ~ 23 位
- 0x1F6:
- 0 ~ 3:起始扇区的 24 ~ 27 位
- 4: 0 主盘, 1 从片
- 6: 0 CHS, 1 LBA
- 5 ~ 7:固定为1
- 0x1F7: out
- 0xEC: 识别硬盘
- 0x20: 读硬盘
- 0x30: 写硬盘
- 0x1F7: in / 8bit
- 0 ERR
- 3 DRQ 数据准备完毕
- 7 BSY 硬盘繁忙
注意上面的out和in指令
读端口用IN指令,写端口用OUT指令
out a,b 将b的值写入到a端口
in a,b 将b端口的值读到a中
先来看4个起始扇区的寄存器 :0x1F3
、0x1F4
、0x1F5
、0x1F6
,假如此时的起始扇区ecx=123456789
,即32位bit为00000111010110111100110100010101
0-7位:
00010101
=>0x1F3
8-15位:
11001101
=>0x1F4
16-23位:
01011011
=>0x1F5
24-31位:
00000111
- 24-27位:
0111
=>0x1F6
(0-3) mov al,0b1110_0000
0
=>0x1F6
(4) 表示主盘111
=>ox1F6
(5-7) 固定为1
- 24-27位:
再来看0x1F7
,值为0x20
,表示读磁盘
然后通过mov cl,bl
,将扇区数量放在cl
中,后面进行循环,汇编中循环的次数和ecx
有关。因为是要读磁盘,因此需要先等待磁盘数据处理好,然后才进行读取,.wait
便是这个作用,其余的相关解析可以通过代码注释看懂,这里就不赘述了
jmp $+2
可以通过反汇编看到
0000:jmp $+2
0002:xxx所以这行代码就是跳到下一行,起到等待的作用
经过编写这个函数,我们就可以从磁盘中得到我们想要的代码啦,前面说过,我们本身就想将loader.asm
代码放在磁盘的一个地方,然后再读进来,那怎么放呢,这样,我们先简单写一个loader.asm
loader.asm
代码如下
[org 0x1000]
; 打印字符串
mov si, loading
call print
; 阻塞
jmp $
print:
mov ah, 0x0e
.next:
mov al, [si]
cmp al, 0
jz .done
int 0x10
inc si
jmp .next
.done:
ret
loading:
db "Loading System...", 10, 13, 0; \n\r
同样的,我们只是打印出一句话即可,那我们怎么将这些代码复制到磁盘中去呢,下面两行命令
nasm -f bin loader.bin loader.asm
dd if=loader.bin of=master.img bs=512 count=4 seek=2 conv=notrunc
利用dd命令,将bin文件从偏移为2的地方,写入4个到master.img中,这样就可以知道loader.bin
在磁盘哪里,就可以读入了
boot.asm
中代码如下
; 因为loader.bin是从第2个扇区开始写入,写了4个扇区
mov edi, 0x1000;读取的目标内存
mov ecx, 2 ;起始扇区
mov bl, 4 ;扇区数量
call read_disk
经过上面一番折腾,终于从boot
跳转到loader
中了,后续我们将对loader.asm
进行完善,实现loader
所需要的功能,下次见啦。。。
操作系统实现-boot.asm实现的更多相关文章
- Ubuntu Bochs boot.asm 测试
/********************************************************************* * Ubuntu Bochs boot.asm 测试 * ...
- 操作系统Lab1 详解(boot|kern/debug)
总体 : boot kern libs tools boot asm.h bootmain.c bootasm.S asm.h 汇编头文件 SEG_NULLASM 定义一个空段描述符 SEG_ASM ...
- 操作系统篇-hello world(免系统运行程序)
|| 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.前言 今天起开始分享关于操作系统的相关知识,本人也是菜鸟一个,正处于学习阶段,这整个操作系统篇也是我边学习边总结的一些结果,希 ...
- MIT 6.828 JOS学习笔记4. Lab 1 Part 2.1: The Boot Loader
Part 2: The Boot Loader 对于PC来说,软盘,硬盘都可以被划分为一个个大小为512字节的区域,叫做扇区.一个扇区是一次磁盘操作的最小粒度.每一次读取或者写入操作都必须是一个或多个 ...
- 《30天自制操作系统》笔记(02)——导入C语言
<30天自制操作系统>笔记(02)——导入C语言 进度回顾 在上一篇,记录了计算机开机时加载IPL程序(initial program loader,一个nas汇编程序)的情况,包括IPL ...
- 自制操作系统 (三) 从启动区执行操作系统并进入C世界
qq:992591601 欢迎交流 2016.04.03 2016.05.31 2016.06.29 这一章是有些复杂的,我不太懂作者为什么要把这么多内容都放进一天. 1读入了十个柱面 2从启动区执行 ...
- 操作系统开发系列—9.Loader
一个操作系统从开机到开始运行,大致经历“引导—>加载内核入内存—>跳入保护模式—>开始执行内核”这样一个过程.也就是说,在内核开始执行之前不但要加载内核,而且还有准备保护模式等一系列 ...
- [自制简单操作系统] 2、鼠标及键盘中断处理事件[PIC\GDT\IDT\FIFO]
1.大致介绍: >_<" 大致执行顺序是:ipl10.nas->asmhead.nas->bootpack.c PS: 这里bootpack.c要调用graphic. ...
- [自制简单操作系统] 1、从0-1到汇编再到c语言的奥秘
目录: 1.用0-1编写最简单的操作系统 2.用汇编改写上面0-1程序 2.1 只用DB的汇编改写版 2.2 加入RESB汇编的改写版 2.3 进一步使用汇编替换0-1文件 2.4 核心程序也用 ...
随机推荐
- 面试问题之计算机网络:TCP滑动窗口
滑动窗口协议是传输层进行流量控制的一种措施,接收方通过通知发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的,并且滑动窗口分为接收窗口和发送窗口.TC ...
- 区分 BeanFactory 和 ApplicationContext?
BeanFactory ApplicationContext 它使用懒加载 它使用即时加载 它使用语法显式提供资源对象 它自己创建和管理资源对象 不支持国际化 支持国际化 不支持基于依赖的注解 支持基 ...
- 详细描述一下 Elasticsearch 索引文档的过程?
协调节点默认使用文档 ID 参与计算(也支持通过 routing),以便为路由提供合适的分片. shard = hash(document_id) % (num_of_primary_shards) ...
- java对象的克隆以及深拷贝与浅拷贝
一.为什么要使用克隆 在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也 ...
- java-字节流-字符流
I/O叙述 FileOutputStream类字节输出流的介绍: 写入数据的原理 java程序-->JVM(java虚拟机)--->OS(操作系统)---->OS调用写数据的方法-- ...
- GC和GC Tuning
GC和GC Tuning GC的基础知识 什么是垃圾 C语言申请内存:malloc free C++: new delete c/C++ 手动回收内存 Java: new ? 自动内存回收,编程上简单 ...
- Python中module文件夹里__init__.py的功能
怎么引用模块 环境:win7 + python3.5.2文档结构: -project -data -src -filterCorpus.py -translateMonolingual.py 问题 ...
- Top 15 - Material Design框架和类库(译)
_Material design_是Google开发的,目的是为了统一公司的web端和手机端的产品风格.它是基于很多的原则,比如像合适的动画,响应式,以及颜色和阴影的使用.完整的指南详情请看这里(ht ...
- HTML中meta标签详解;property=og标签详解
meta是用来在HTML文档中模拟HTTP协议的响应头报文.META标签是HTML语言HEAD区的一个辅助性标签,它位于HTML文档头部的<HEAD>标记和<TITLE>标记之 ...
- 软件构造实验-百度图像识别api
识别结果: 识别结果: