30天自制操作系统:第三天 进入32位模式并导入C语言
今天的内容稍稍有点多,一起看看吧
1.制作真正的IPL
到昨天为止,讲到的启动区虽然也称为IPL(Initial Program Loader,启动程序装载器),但它实质上并没有装载任何程序。
小节中作者给出了将之前的 hello-os 改名为 "纸娃娃操作系统" 的深意:用纸糊起来的,笔者将其理解为目前还有太多功能没有实现,只能是一个看起来像操作系统的东西。
从简单的程序开始,磁盘最初的512字节是启动区,所以要装载下一个512字节的内容。看第一段程序 harib00a:
JC指令
jump if carry, 如果进位标志(carry flag) 是1的话,指令就执行(完成跳转)
对于指令 INT 0x13,这里是调用BIOS的0x13号函数,函数作用如下图:
BIOS中断调用–百度百科
↑截自百度百科
图中也说明了当AH = 0x02时为读盘动作,其中0x13号函数的功能如下:
- AH = 0x02(读盘)
- AH = 0x03(写盘)
- AH = 0x04(校验)
- AH = 0x0c(寻道)
- AL = 处理对象的扇区数(只能同时处理连续的扇区)
- CH = 柱面号 & 0xff
- CL = 扇区号(0 ~ 5位) | (柱面号&0x300) * * 2
- DH = 磁头号
- DL = 驱动器号
- ES:BX = 缓冲地址(校验及寻道时不使用)
- 返回值
- FLAGS.CF == 0 没有错误,AH = 0
- FLAGS.CF == 1 有错误,错误号码存入AH内(与重置(reset)功能一样)
FLAGS.CF是什么意思?光看意思也能够理解个大概:进位标志。
因此这里就明晰了JC指令的使用,如果出错,进位标志CF会被设置为1,进而跳转到error程序段。
在多个软盘驱动器的时候,用磁盘驱动器号来指定从哪个驱动器的软盘上读取数据。这里指定0号。
软盘的结构示意图:
一张软盘有80个柱面,2个磁头,18个扇区,一个扇区有512字节,所以一张软盘的容量为:
80 x 2 x 18 x 512 = 1 474 560 Byte = 1 440KB
含有IPL的启动区,位于C0-H0-S1(柱面0,磁头0,扇区1的缩写),下一个扇区是C0-H0-S2,本次要装载的就是这个扇区。
如果没有汇编基础,那么肯定有这样一个疑惑:如果单纯只用寄存器(16位)来表示内存地址,那么最大可以表示的地址为0xFFFFH,一共10000H = 64KB,显然我们对此并不满足,因此有了后来的EBX寄存器(32位),这样能够处理的空间大小变成了2 ^ 32 B= 4 GB,但在此BIOS阶段,用不着这么大的空间,所以只需要使用段寄存器来拓展即可。
段寄存器:通用寄存器 的组合能够访问到最多 FFFF:FFFFH即 (FFFF) * 16 + FFFF H = 1 114 095字节,也就是说可以指定1MB以内的内存了。
这里指定 ES = 0x0820, BX = 0, 软盘的数据会被装载到0x8200 ~ 0x83ff(一共512字节)的地方,使用0x8200的原因是这一块区域没有程序使用,可以将我们的操作系统装载到这片区域,
注:0x7c00 ~ 0x7dff用于启动区,0x7e00以后直到0x9fbff为止的区域都没有特别的用途,操作系统可以随便使用。
双击 !cons_nt.bat 文件 >>> 输入make完成文件编译 >>> 再次输入 make run 运行操作系统
2.试错
由于是机械型存储介质,发生一些硬件错误也是难免的,有时会发生不能读数据的状况,所以应该设计程序重复读几次盘,实在不行那就只能放弃然后打印错误信息来告知程序员这块出错了。
改良后的harib00b程序:
JNC指令的含义与JC相反,jump if not carry,意为没有进位则发生跳转。JAE,jump if above or equal,意思是大于或等于时跳转。
程序中给出了较为详细的注释,看几遍应该可以理清楚。
3.读到18扇区
harib00c程序:
慢慢理解本程序:
首先是JBE指令,jump if below or equal,意思是小于等于则跳转。
程序做的事情很简单,要读下一个扇区,只需要给CL加1,ES加上0x20就行了。CL是扇区号,这里有一点疑惑是在换扇区读盘时只加上了0x20H = 32Byte,前面有提到过,一个扇区的大小为512字节,按理来说每次读完一个扇区偏移地址需要偏移0x200,这里作者给出的是0x20,解释如下:
笔者认为这块可能是作者写错了(狗头保命,有待求证)
偏移问题 后续 9.15 更
这里是对段寄存器的操作,因此ADD AX, 0x20 体现在ES段寄存器上会扩大16倍(8086CPU中表现为ES * 16 + OFFSET, OFFSET表示偏移地址,因此只需要给段寄存器加上 512 / 16即可,在地址偏移的时候会扩大16倍,笔者汇编语言不够扎实,连这个都忘了。。。
这里为什么要循环呢,笔者初次读到程序也是这么想的,我们已经知道自己的目标是18扇区,那么直接将AL的值设置为17(连续读前2 ~ 18 共 17个扇区)不就好了吗。
确实,这么想是没问题的,但是作者查阅了BIOS读盘函数说明的“补充说明”部分:
这一部分暂且到这,只需要明白使用AL = 17 一次完成效果也是一样的,但为了章节推进,这里不做详细讲解。
到此,我们已经把磁盘上C0-H0-S2到C0-H0-S18的512 x 17 = 8704字节的内容,装载到了内存的0x8200 ~ 0xa3ff处。
4.读入10个柱面
C0-H0-S18扇区的下一扇区,是磁盘反面的C0-H1-S1,这次也从0xa400读入,按顺序读到C0-H1-S18后,接着读下一个柱面C1-H0-S1,一直读到C9-H1-S18。
harib00d程序:
JB指令:jump below,意思是如果小于,就跳转。
程序起始位置的EQU指令:相当于C语言的 #define,进行宏定义。
“CYLS EQU 10”意思是:“CYLS = 10”,EQU是equal的缩写(CYLS为cylinders的简写:柱面)。
5.着手开发操作系统
编写了一个非常小的程序:
fin:HLTJMP fin
通过作者提供的makefile文件做成了一个img文件,按照指示用二进制编辑器打开 haribote.img:
↑ 0x002600附近
↑ 0x004200附近
再打开haribote.sys,可以惊奇地发现:
与img文件中0x004200附近的内容是一样的,作者是想让我们知道:
一般向一个空软盘保存文件时,
- 文件名会写在0x002600以后的地方
- 文件的内容会写在0x004200以后的地方
接下来就是将操作系统本身的内容写到 haribote.sys 中,再把它保存到磁盘中,最后从启动区执行这个文件就可以了。
6.从启动区执行操作系统
7.确认操作系统的执行情况
这里详细介绍了画面模式,先看一下本次的 haribote.nas文件:
设置了AH = 0,然后调用了0x10中断:
INT 10h
显示服务 - 由BIOS或操作系统设定以供软件调用。AH=00h 设定显示模式;AH=01h 设定游标形态;AH=02h 设置游标位置;AH=03h 获取光标位置与形态;AH=04h 获取光标位置;AH=05h 设置显示页;AH=06h 清除或滚动栏画面(上);AH=07h 清除或滚动栏画面(下);AH=08h 读取游标处字符与属性;AH=09h 更改游标处字符与属性;AH=0Ah 更改游标处字符;AH=0Bh 设定边界颜色;AH=0Eh 在TTY模式下写字符;AH=0Fh 获取当前显示模式;AH=13h 写字符串。
可以发现这里调用了显卡BIOS的函数,这样就可以切换到显示模式了。
8.32位模式前期准备
↑为什么要切换到32位模式
一旦使用了32位模式就不可以再调用BIOS:
从BIOS得到键盘状态:
设置好了画面模式之后还把与画面相关的信息保存在了内存中(保存起来以后备用)
关于VRAM
9.开始导入C语言
这一部分均为作者的创意部分,笔者学识浅薄,暂时不能够对此做出深刻的解读,就先放上图书截图。
运行效果:一片漆黑
10.实现HLT
在前面的C语言程序,因为没有办法使用HLT指令(这是汇编指令),所以程序做了大量的循环。这里作者还是用汇编写了一个带HLT指令的程序:
函数名前面必须加上"_",否则不能与C语言函数链接(C语言中的函数在编译之后会在头部加上该符号)
在C语言中调用这个函数:
感受
今天的内容相较前两天确实多了很多,虽然写下了这篇博客,但还是有很多地方没有搞懂,需要慢慢理解,不断渗透,截图非常多的原因也很简单,对于很多内容作者已经给出了非常详尽的解析,在这里就不班门弄斧了。
坚持就是胜利,加油!
30天自制操作系统:第三天 进入32位模式并导入C语言相关推荐
- 进入32位模式并导入c语言教程,《30天自制操作系统》读书笔记(3) 引入C语言
这一次的学习相当曲折, 主要是因为粗心, Makefile里面的错误导致了文件生成出现各种奇奇怪怪的问题, 弄得心力交瘁, 因此制作过程还是尽量按着作者的路子来吧. 作者提供的源码的注释在中文系统下是 ...
- 30天自制操作系统第三天
操作系统实验日志3 学号 201708010402 姓名 徐冰娜 专业年级班级 实验日期 2019.9.28 实验项目 第3天:进入32位模式并导入C语言 智能1701 30天自制操作系统第三天 操作 ...
- 【操作系统】30天自制操作系统--(9)叠加处理
这一章主要是处理之前遇到的图层叠加的问题.[操作系统]30天自制操作系统--(7)鼠标移动与32位切换 一 内存管理优化 上一章的内存管理虽然写好,但是还是有不完善的地方.因为如果不对申请内存的大小有 ...
- 索骥馆-DIY操作系统之《30天自制操作系统》扫描版[PDF]
内容简介: <30天自制操作系统>是一本兼具趣味性.实用性与学习性的操作系统图书.作者从计算机的构造.汇编语言.C语言开始解说,让读者在实践中掌握算法.在这本书的指导下,从零编写所有代码, ...
- 《30天自制操作系统》-day3(MAC)
第3天 进入32位模式并导入C语言 基本配置 汇编语言内容 文件 hanbote.nas ipl.nas Makefile 原因 用法 基本配置 设备:Macbookpro(13-inch,2018) ...
- 《30天自制操作系统》前言、目录、样章欢迎阅读!
编著推荐: 只需30天从零开始编写一个五脏俱全的图形操作系统 如果肯坚持,没有什么不可以!祝所有读到这篇文章的人都能写出好的操作系统! 内容简介: 自己编写一个操作系统,是许多程序员的梦想.也许有人曾 ...
- 30天自制操作系统读书笔记(三)
来吧.第三天. 制作真正的IPL: 作者又是那样,一上来就甩一堆代码,用他的话猜测,下面这段代码应该是用来装载下一个512字节的内容的. MOV AX,0x0820MOV ES,AXMOV CH,0 ...
- 30天自制操作系统Day8
一.鼠标解读 鼠标收到激活指令后,发送的第一个按键编码是0xfa,之后,每次从鼠标发送过来的数据都是3个字节一组的. 移动鼠标时,第一个字节的高四位会在0-3的范围内变化,也就是说第七位和第八位始 ...
- 30天自制操作系统 pdf_30天自制操作系统:第三天:系统引导完成
对第二天代码进行了修改,只打印hello ,uos没一点意思. 读取磁盘上10个柱面的1-18个扇区,(目前ssd已经没有柱面这个概念了).读出来的数据放入内存0x8200起始的地方. 启动区放在0x ...
最新文章
- word表格自动编号
- 只用一分钟,给你的宽带加速
- python程序员年薪百万_想要成为年薪百万的Python程序员,这套面试题别错过
- linux 有空格的文件夹,Linux之删除带有空格的文件
- ML之Hash_EditDistance:基于输入图片哈希化(均值哈希+差值哈希)即8*8个元素的单向vector利用编辑距离算法进行判别
- 【Python】怎么用matplotlib画出漂亮的分析图表
- Boost:易变的bimap双图的测试程序
- 误差error,偏置bias,方差variance的见解
- OpenCV2和OpenCV3兼容安装
- 《HTML5 开发实例大全》——1.9 使用 summary 标记元素实现交互
- Jquery Validate 动态添加校验
- windows编程 识别拖动_Quicker 解锁新姿势!Windows 还能这么用?
- 新型计算机作文1000,科技作文1000字(精选3篇)
- python秒表代码_斌哥教你自制千分秒表(键盘控制)
- 软件工程之系统建模篇【设计接口类模型】
- 网络攻击与防范—术语和工具介绍
- TCPC-可用于笔记本,平板等HOST端的解决方案
- drcom linux最新版,Drcom-client.org 上线暨新版 PUM v1.0 发布
- 【Activiti】PersistenceException,MySQLSyntaxErrorException,order by RES.ID_ asc LIMIT 1 OFFSET 0
- FinalRecon:一款多功能网络侦查OSINT工具