30天自制操作系统第三天

操作系统实验日志3

学号 201708010402 姓名 徐冰娜 专业年级班级
实验日期 2019.9.28 实验项目 第3天:进入32位模式并导入C语言 智能1701

一、实验主要内容


1、内容1: 新出现的指令以及名词解释

① INT 0x13:调用bios的0x13号函数

AH=0x00 复位磁盘驱动器 AH=0x0D 复位硬盘控制器
AH=0x01 检查磁盘驱动器状态 AH=0x15 取得驱动器类型
AH=0x02 读扇区 AH=0x16 取得软驱中盘片的状态
AH=0x03 写扇区 AL=处理对象的扇区数 只能同时处理连续的扇区
AH=0x04 校验扇区 CH=柱面号&0xff 柱面有80个(0~79)
AH=0x05 格式化磁道 CL=扇区号(0-5位)|(柱面号&0x300)>>2 每个柱面18个扇区(1~18号)
AH=0x08 取得驱动器参数 DH=磁头号 正面位0反面为1
AH=0x09 初始化硬盘驱动器参数 DL=驱动器号 从0开始,制定从哪个软盘驱动器上的软盘读取数据
AH=0x0C 寻道 ES:BX=缓冲地址
返回值:FLACS.CF=0 没错误,AH=0 FLACS.CF=1 有错,错误号码存入AAH

INT 0x16:

30天自制操作系统第三天

软盘的磁盘结构: 磁盘被分成若干个磁道即柱面,每个柱面又分为若干个扇区,每个扇区存储512个字节。柱面是一组同心圆,一个1.44M的软盘,它有80个柱面,每个磁道有18个扇区,两面都可以存储数据,因此有正反两个磁头。

注释:使用软盘时,需要注意不要划伤盘片,盘片不能变形、不能受高温、不能受潮、不要靠近磁性物质等等。

变量改写Makefile: 变量采用$(变量)的格式。

JC: 如果进位标志是1的话,就跳转。

JNC: jump if not carry 如果进位标志是0就跳转。

JAE: jump if above or equal 大于或等于+时跳转。

JBE: jump if below or equal 小于等于则跳转。

VRAM: 指显卡内存,也就是用来显示画面的内存。可以向内存一样存储数据,且各个地址都对应着画面上的像素,因此能在画面上绘制出五彩缤纷的图案。

⑩ INT 0x10画面模式下“VRAM是0xa0000~0xaffff的64KB”。

汇编指令EQU: 用符号名代表字符串。用一个具有一定含义的符号名定义某一个较长的字符串,在随后的程序中就用该符号名。

2、内容2:用IPL装载程序

启动区位置: C0-H0-S1(柱面0,磁头0,扇区1的缩写);

段址+基址的地址表示方法: 使用段寄存器时用ES:BX这种方式来表示,写成“MOV AL, [ES:BX]”,代表ES*16+BX的内存地址;

操作系统安装步骤: 首先软盘中的启动区会被装载到内存的0x7c00~0x7dff中,然后cpu会执行已经加载的启动区程序的指令,将软盘中的其余数据按需求加载到内存的指定位置中。

3、内容3:软盘读取数据(读取一个扇区->试错->读到18个扇区->读到10个柱面)

根据教材中的代码,由于第一个扇区是留给启动区,所以从第二个扇区开始读,即从C0-H0-S2读到C0-H0-S18,然后再读取另一个磁头,即从C0-H1-S1读到C0-H1-S19,再不断读取下一个柱面、扇区和磁头,即从C1-H0-S1读到C9-H1-S18.

试错:当出现错误,会重新读,5次还不行就放弃,每次出错的时候,就调用bios的13号函数,重置驱动器。

4、内容4:从启动区执行操作系统

过程: 因为已经将操作系统的内容保存到了.sys,文件,接下来只要找到它的位置,然后启动区在执行的时候,跳转到那个位置就可以了。所以要设置段寄存器,所以就在操作系统的文件中加了0rg 0xc200。

注释:sys是Windows的系统文件。如安装文件,日志文件,驱动文件,备份文件,操作如播放等文件,还有些垃圾文件等诸如此类。都是这类sys后缀名的。

我们已经得到的结论是:向一个空软盘保存文件时,

(1)文件名会写到0x002600以后的位置;

(2)文件的内容会写在0x004200以后的地方;

所以最终系统的内容就被储存到0x8000+0x4200=0xc200地址的位置。(为什么从8000开始加后面的问题解答会写到)

  1. 32位模式前期准备

(1)为什么要进行前期准备:16位机器语言模式不能在32位机器语言模式下运行,而bios是用16位机器语言写的,32位模式就不能调用BIOS功能了,所以我们要在开头做好bios要做的事情。

(2)BIOS都要做什么事:画面模式的设定、得到键盘状态

  1. 开始导入C语言

将C语言变成汇编语言:

工具 作用 输入 输出
cc1 gcc以gas汇编语言为基础,输出gas用的源程序 .c .gas
gas2nask 把gas变换成nask能翻译的语法 .gas .nas
nask 翻译成机器语言,生成目标文件.obj .nas .obj
obj2bim.exe 目标文件需与其他文件link才能编程真正可以执行的机器语言,bim是二进制映像文件,是一种代替的形式 .obj .bim
bim2hrb.exe 为了能够实际使用,要做成适合本书操作系统要求的形式 .bim .hrb

实现HLT:

①naskfunc.nas是用汇编写的函数,还要与bootpack.obj链接,它也需要编译成目标文件。

②在nask目标文件的模式下,必须设定文件名信息,然后再写明下面程序的函数名。“_”需加载函数名前面,否则就不能很好地与C语言函数链接。需要链接的函数名,都要用GLOBAL指令声明。

文件结构流程图:

30天自制操作系统第三天

二、遇到的问题及解决方法


1.描述问题1:今天和同学讨论了一下本实验代码中的ORG,有如下几个疑惑,ORG命令后的地址是什么地址?代码中为什么总是使用ORG
0x7c00?为什么有时候去掉ORG指定地址或者使用7c00后的地址后还可以正常执行吗?如果说ORG指令后的地址是启动区的装载地址,那么ORG以及之前的指令被加载内存的什么地方?

解决方法:和同学讨论后,又查阅了一些资料后得知:

①ORG后的地址是程序被载入内存时的起始地址;在我们的实验代码中,org指令本身并不能决定程序将要加载到内存的什么位置,它只是告诉编译器,我的程序在编译好后需要加载到哪个地址;

②引导程序加载到内存的7c00h处是一项标准,并不是在编程时决定的,在实际装系统的过程中(并非是虚拟机),将org后的数字改成其他值,bois程序一样将它加载到7c00处;

③不一定。在数据访问时,都是采用段地址+基址的方式,如果不用org指定地址那么段地址就会清0,最后读取数据的地址就不是我们预期的那个地址了;当程序中没有对内存的寻址操作时,不加org
0x7c00就不会出错。

④org指令只会在编译期影响到内存寻址指令的编译(编译器会把所有程序用到的段内偏移地址自动加上org后跟的数值),而其自身并不会被编译成机器码。

2.描述问题2:

30天自制操作系统第三天

不明白为什么0x8000到0x81ff区域也要留给启动区,而且为什么不是从0x7e00开始?

解决方法:经过查阅了一些资料得知,BIOS读完启动扇区以后,会跳转到0x7C00启动,占用0x7C00-0x7DFF这一段(512字节),而一般bootloader还需要一个栈空间或者读磁盘的交换空间,一般是放到0x7E00-0x7FFF这512字节里,所以有些操作系统的镜像起点是0x8000。然后启动区确实会拷贝一份映射到0x8000位置上。但是BIOS里读取启动扇区都是加载到0x7C00上的。

三、程序设计创新点


1、描述创新点1: 改写c语言,改变不同地址的值,显示出条纹图案

30天自制操作系统第三天

运行结果:
30天自制操作系统第三天

四、实验心得体会


通过本次实验,我真正了解了操作系统的执行过程,以及启动区的位置以及作用。知道从开机到装载内存到指令执行都是怎么回事。在和同学讨论的过程中,真的很惊讶王文斌的研究能力,能在很小的细节上看出问题,然后深入的研究。比如说哪个org命令,我自己就没有看出那么多问题,经过他一点播,我才有了后续那些思考。我也还有一些问题没有搞清楚,是关于后缀名的,我不太清楚为什么都是二进制文件,有的就要命名bin有的就要obj,猜测是window是根据后缀名来分配权限。相比来说linux这一点就完全不同,它不根据后缀名来区分文件,而是根据文件的权限来区分。