ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

30天自制操作系统:第三天 进入32位模式并导入C语言

2021-09-14 20:33:41  阅读:227  来源: 互联网

标签:操作系统 32 30 程序 扇区 C语言 BIOS 指令 AH


今天的内容稍稍有点多,一起看看吧

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,解释如下:
在这里插入图片描述
笔者认为这块可能是作者写错了(狗头保命,有待求证)

这里为什么要循环呢,笔者初次读到程序也是这么想的,我们已经知道自己的目标是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:
	HLT
	JMP fin

通过作者提供的makefile文件做成了一个img文件,按照指示用二进制编辑器打开 haribote.img:
在这里插入图片描述
↑ 0x002600附近
在这里插入图片描述
↑ 0x004200附近

再打开haribote.sys,可以惊奇地发现:
在这里插入图片描述
与img文件中0x004200附近的内容是一样的,作者是想让我们知道:
一般向一个空软盘保存文件时,

  1. 文件名会写在0x002600以后的地方
  2. 文件的内容会写在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语言中调用这个函数:
在这里插入图片描述

感受

今天的内容相较前两天确实多了很多,虽然写下了这篇博客,但还是有很多地方没有搞懂,需要慢慢理解,不断渗透,截图非常多的原因也很简单,对于很多内容作者已经给出了非常详尽的解析,在这里就不班门弄斧了。
坚持就是胜利,加油!

标签:操作系统,32,30,程序,扇区,C语言,BIOS,指令,AH
来源: https://blog.csdn.net/Genius_bin/article/details/120282455

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有