文档库 最新最全的文档下载
当前位置:文档库 › 30天自制操作系统日志第3天

30天自制操作系统日志第3天

30天自制操作系统日志第3天
30天自制操作系统日志第3天

一、实验主要内容

1、制作真正的IPL,即启动程序加载器,用来加载程序。

添加的代码关键部分如下:

MOV AX,0x0820

MOV ES,AX

MOV CH,0 ;柱面0

MOV DH,0 ;磁头0

MOV CL,2

MOV AH,0x02 ;AH=0x02:读盘

MOV AL,1 ;执行1个扇区

MOV BX,0

MOV DL,0x00 ; A驱动器(现在都只有一个驱动器了)

INT 0x13 ;调用磁盘BIOS

JC error

这里有JC指令,是一些特定指令中的一种,后面知识点收录有。JC就是jump if carry,如果进位标志位1的话,就跳转。就是成功调用0x13就会跳转到error处。

INT 0x13又是一个中断,这里AH是0x02的时候是读盘的意思,就是要把磁盘的内容写入到内存中。今天实验用到了4个软中断,都记在知识点里了。

至于CH\DH\CL\AL三个寄存器呢,就分别是柱面号、磁头号、扇区号、执行的扇区数。那么含有IPL的启动区位于:C0-H0-S1 (Cylinder, magnetic Head, Sector)

然后ES\BX和缓冲地址有关。

2、缓冲区地址0x0820

MOV AL,[ES:BX] ; ES*16+BX -> AL

说是原来16位的BX只能表示0~65535,后来就引入了一个段寄存器,用MOV AL,[ES:BX] ;

ES*16+BX -> AL这样的方法就可以表示更大的地址,就够当时用了,可以指定1M内存地址了。那么这里我们就是将0X0820赋值给ES,BX为0,这样ES*16后就访问0X8200的地址,那么就是讲软盘数据转载到0X8200到0X83ff的地方。

3、试错以及读满10个柱面

MOV AX,0x0820

MOV ES,AX

MOV CH,0

MOV DH,0

MOV CL,2

readloop:

MOV SI,0 ; 记录失败的次数,SI达到5就停止

retry:

MOV AH,0x02

MOV AL,1

MOV BX,0

MOV DL,0x00

INT 0x13

JNC next ; 没出错就跳到next

ADD SI,1 ; SI加一

CMP SI,5 ; SI和5比较

JAE error ; SI >= 5 时跳转到error

MOV AH,0x00

MOV DL,0x00

INT 0x13 ; 重置驱动器,看上面AH变为0X00和0X02功能不同

JMP retry

next:

MOV AX,ES

ADD AX,0x0020

MOV ES,AX

ADD CL,1

CMP CL,18

JBE readloop

MOV CL,1

ADD DH,1

CMP DH,2

JB readloop

MOV DH,0

ADD CH,1

CMP CH,CYLS

JB readloop

这里很明显,从CL\DH\CH依次循环计数,就是读取完一个磁头的扇区后换一个磁头,到这个柱面都结束了就换一个柱面,一直读完10个柱面。

4、到正菜了,主程序操作系统

完成了启动区的制作,下一步开始编写操作系统代码。

最简单的操作系统:

Fin:

HLT

Jmp fin

我们需要将操作系统本身的内容写到名为文件中,再把他保存到磁盘映像里,然后我们从启动区执行这个就行了。老作者用一个简单的例子告诉我们当我们向一张空软盘保存文件时,1)文件名会写在0x002600以后的地方;2)文件的内容会写在0x004200以后的地方。由于目前的启动区程序是从启动区后面开始(不包括启动区)加载到内存地址0x8200处的,所以磁盘0x4200的内容就会被加载到内存地址0xc200处,其中0xc200 = 0x8200 + 0x4200 - 512(启动区大小),现在我们就可从0xc200处加载我们自己写的程序用于执行了。需要在头加入org 0xc200,在启动区最后添加代码jmp 0xc200。如此在装载完os后,即会跳到地址0xc200执行操作系统程序。

5、让他显示图形模式

这里是中断调用显卡函数,设置显示模式,320*200*8位彩色模式,有256种颜色可以使用。

画面一片漆黑,大概是因为显存没有设置吧,下面的预存地址VRAM就是为显存留的,Video RAM,显卡内存,他的地址对应着屏幕上的像素。修改这个应该可以改颜色,黑色大概是默认老贼(把坑的作者叫老贼)也不说,唉,还要查。

6、进入32位模式及保存画面模式

32位固然好,但是CPU32位模式不能调用BIOS功能。设定完画面模式后就要得到键盘状态。这里就是把画面的像素数、颜色数、键盘信息都保存了起来。和CYLS一样,都保存在了0X0FF0附近。

7、C语言正式出场!小场面,戏份不足

这C关键部分真的是没讲嘛!老贼!下节的内容。

8、文件的转换生成

流程图果然一目了然,但是真的难画,用网上的:

9、一些知识点

A、汇编指令

JC指令

JC,是“jump if carry”的缩写,意思是如果进位标志是1的话,就跳转。

JNC指令

JNC,是“jump if not carry”的缩写,意思是如果进位标志是0的话,就跳转。

JAE指令

JAE,是“jump if above or equal”的缩写,意思是大于或者等于时,跳转。

JBE指令

JBE,是“jump if below or equal”的缩写,意思是小于或者等于时,跳转。

JB,是“jump if below”的缩写,意思是大于或者等于时,跳转。

B、软中断

新学到的4个软中断

(1)INT 13h AH=02h: 读盘,即从磁盘中读取扇区

参数:

AH: 02h

AL: 读入的扇区数

CH: 柱面号

CL: 扇区号

DH: 磁头号

DL: 磁盘号

ES:BX, 缓冲区地址

返回值:

CF: 错误置1,正确置0

AH: 返回值代码

AL: 实际读取的扇区数

(2)INT 13h AH=00h: 复位磁盘驱动

参数:

AH: 00h

DL: 磁盘号

返回值:

CF: 错误置为1

(3)INT 10h AH=00h: 设置显示模式

参数:

AH: 00h

AL: 显示模式

AL = video mode flag / CRT controller mode byte

(4)INT 16H AH=02h: 获取键盘的状态信息

C、文件的转换

工具作用输入输出cc1 gcc以gas汇编语言为基础,输出gas用的源程序 .c .gas gas2nask 把gas变换成nask能翻译的语法 .gas .nas nask 翻译成机器语言,生成目标文件.obj .nas .obj obi2bim 目标文件需与其他文件link才能编程真正可以执行的

机器语言,bim是二进制映像文件,是一种代替的形式 .obj .bim bim2hrm 为了能够实际使用,要做成适合本书操作系统要求的形式.bim .hrb

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

1、

这里有些疑惑,说什么0X8000~0x83ff是留给启动区的,但是启动区明明是在0X7C00到0X7DFF的。8000留给启动区是作什么用途呢还有这中间的地址又是作什么用呢

目前没有解决。

三、程序设计创新点

1、硬盘知识

上面没有细讲到软盘的结构,是我对这个真的感兴趣,就去网上找了一些资料,果然更全面。下面是内容:

概述

盘片(platter)

磁头(head)

磁道(track)

扇区(sector)

柱面(cylinder)

盘片片面和磁头

硬盘中一般会有多个盘片组成,每个盘片包含两个面,每个盘面都对应地有一个读/写磁头。受到硬盘整体体积和生产成本的限制,盘片数量都受到限制,一般都在5片以内。盘片的编号自下向上从0开始,如最下边的盘片有0面和1面,再上一个盘片就编号为2面和3面。

如下图:

图1

扇区和磁道

下图显示的是一个盘面,盘面中一圈圈灰色同心圆为一条条磁道,从圆心向外画直线,可以将

磁道划分为若干个弧段,每个磁道上一个弧段被称之为一个扇区(图践绿色部分)。扇区是磁盘的最小组成单元,通常是512字节。(由于不断提高磁盘的大小,部分厂商设定每个扇区的大小是4096字节)

图2

磁头和柱面

硬盘通常由重叠的一组盘片构成,每个盘面都被划分为数目相等的磁道,并从外缘的“0”开始编号,具有相同编号的磁道形成一个圆柱,称之为磁盘的柱面。磁盘的柱面数与一个盘面上的磁道数是相等的。由于每个盘面都有自己的磁头,因此,盘面数等于总的磁头数。如下图

图3

磁盘容量计算

存储容量=磁头数×磁道(柱面)数×每道扇区数×每扇区字节数

图3中磁盘是一个 3个圆盘6个磁头,7个柱面(每个盘片7个磁道)的磁盘,图3中每条磁道有12个扇区,所以此磁盘的容量为:

存储容量 6 * 7 * 12 * 512 = 258048

每个磁道的扇区数一样是说的老的硬盘,外圈的密度小,内圈的密度大,每圈可存储的数据量是一样的。新的硬盘数据的密度都一致,这样磁道的周长越长,扇区就越多,存储的数据量就越大。

磁盘读取响应时间

寻道时间:磁头从开始移动到数据所在磁道所需要的时间,寻道时间越短,I/O操作越快,目

前磁盘的平均寻道时间一般在3-15ms,一般都在10ms左右。

旋转延迟:盘片旋转将请求数据所在扇区移至读写磁头下方所需要的时间,旋转延迟取决于磁盘转速。普通硬盘一般都是7200rpm,慢的5400rpm。

数据传输时间:完成传输所请求的数据所需要的时间。

小结一下:从上面的指标来看、其实最重要的、或者说、我们最关心的应该只有两个:寻道时间;旋转延迟。

读写一次磁盘信息所需的时间可分解为:寻道时间、延迟时间、传输时间。为提高磁盘传输效率,软件应着重考虑减少寻道时间和延迟时间。

块/簇概述

磁盘块/簇(虚拟出来的)。块是操作系统中最小的逻辑存储单位。操作系统与磁盘打交道的最小单位是磁盘块。

通俗的来讲,在Windows下如NTFS等文件系统中叫做簇;在Linux下如Ext4等文件系统中叫做块(block)。每个簇或者块可以包括2、4、8、16、32、64…2的n次方个扇区。

为什么存在磁盘块

读取方便:由于扇区的数量比较小,数目众多在寻址时比较困难,所以操作系统就将相邻的扇区组合在一起,形成一个块,再对块进行整体的操作。

分离对底层的依赖:操作系统忽略对底层物理存储结构的设计。通过虚拟出来磁盘块的概念,在系统中认为块是最小的单位。

Page:

操作系统经常与内存和硬盘这两种存储设备进行通信,类似于“块”的概念,都需要一种虚拟的基本单位。所以,与内存操作,是虚拟一个页的概念来作为最小单位。与硬盘打交道,就是以块为最小单位。

扇区、块/簇、page的关系

扇区:硬盘的最小读写单元

块/簇:是操作系统针对硬盘读写的最小单元

page:是内存与操作系统之间操作的最小单元。

扇区 <= 块/簇 <= page

以上是网络搜寻的知识概要。

下面是我用虚拟机查看的硬盘基本信息(绕了一些弯路),

根据以上信息可以得出:

1,该硬盘总容量为10 GB 。

2, sectors表示总共有那么多个扇区。

3,其中Units = sectors of 1 * 512 = 512 bytes表示扇区的容量,这里好像没有柱面~ 4,Sector size (logical/physical): 512 bytes / 512 bytes 扇区大小物理和逻辑都是512bytes。

5,I/O size (minimum/optimal): 512 bytes / 512 bytes 表示磁盘最小I/O读写大小512bytes。

6,Disk identifier表示硬盘标识符。

四、实验心得体会

最开始我们讲要编写一个一通电就能运行的程序。启动盘的第一个扇区是启动区,把程序代码保存到这个扇区即可,这样就是一个通电就能运行的程序。这个程序最开始我们只是在屏幕上显示一个字符串信息“Hello,world!”,最终改造为一个IPL,即把其他程序装载进入内存的程序(从磁盘读取操作系统的程序)。先写个最简单的操作系统,即显示一个字符串即可,再慢慢添加新的功能。现在我们的操作系统能显示画面模式了,虽然还是全黑,但是很快就可以修改显存来更改显示颜色了,还是很期待的。

相关文档