30自制操作系统第三天

1. 制作真正的IPL

上次制作的IPL只是简单的取了512个字节,并没有真正的加载程序,因此今天我们要制作真正的IPL

在加载程序之前,我们首先应该把程序装载到内存中,我们在上一次上添加的代码如下:

MOV AX,0x0820

MOV ES,AX

MOV CH,0 ;柱面0

MOV DH,0 ; 磁头0

MOV CL,2 ; 扇区2

 

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

MOV AL,1 ; 1个扇区

MOV BX,0

MOV DL,0x00 ; A驱动器

INT 0x13 ; 调用磁盘BIOS

JC error

其中INT 0x13是调用BISO的磁盘中断,具体内容如下:

磁盘读、写

AH =0x02;(读盘 AH = 0x03(写盘)

AL=处理对象的扇区数(只能同时处理连续的扇区)

CH=柱面号 CL =扇区号(0-5位)|(柱面号&0x300>>2

DH = 磁头号, DL= 驱动器号  ES:BX=缓冲区地址;

返回值:

FLAGS.CF ==0没有错误,AH=0

FLAGS.CF==1 有错误,错误号码卸载AH

软盘的样子如下:

 

软盘中有两个磁头,对应着正反两面,有80个柱面,每个柱面有80个扇区,每个扇区有512字节,软盘的容量80*2*18*512=1.4M

C0-H0-S1(柱面0-磁头0-扇区1),启动扇区。

接下来就是缓冲区地址,是一个内存地址,表明我们要把从软盘上读出的数据装载到内存的那个位置。这里通过一个寄存器最大只有64K的内存,所以这里使用ES:BX这种形式来表示地址,MOV AL,[ES:BX] 它代表ES*16+BX的内存地址,这样最大就可以表示1M的字节内容。

这里指定ES=0x0820,BX=0,所以软盘的数据被装载到内存中0x82000x83ff的地方,为何要转载到这个地方呢,书上说,因为启动区装载到0x7c00-0x7dfff用于启动区,0x7e00以后直到0x9fbff为止的区域都没有特别用途,操作系统可以随便使用。其中0x8000~0x81ff512字节是留给启动区的。

注意:需要注意的是之前开发程序时没有考虑段寄存器,但事实上,不管我们制定内存是什么地址,都需要制定段寄存器,一般如果省略的话就把“DS:”作为默认的寄存器。以前我们用“MOV CX,[1234]”,其实是“MOV CX,[DS:1234]”。

接着本节又加入了试错,并且读了又读了10个柱区。

注意:在读18个扇区时,没有直接赋予AL=18,而是一个一个扇区的读取。具体原因:书中解释为:

指定处理的扇区数,范围在0x01-0xff(指定0x02以上的数值时,要特别注意能够连续处理多个扇区的条件。如果是FD的话,似乎不能跨越多个磁道,也不能超过64KB的界限)。

读了10个柱面后,我们已经将10*2*18*512=180KB

2.着手开发系统

我们把文件加入到磁盘映像中,可以同过WinImage来装入,之后我们可以通过二进制软件观察,可以发现在0x002600,可以发现我们向一个空软盘保存文件时:

(1)文件会写在0x002600以后的地方,

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

为什么是如下两个地址,主要是根据FAT12的文件格式来,其中启动扇区占一个扇区,fat1,fat2各占9个扇区,根目录区所在位置时19扇区,19*512=0x002600,同样,在默认设置下,数据区会在0x004200处。

接着,由于文件内容在0x4200处,就应该位于内存0x8000+0x4200=0xc200,因此,我们在ipl.nas中加入jmp 0xc200,haribote.nas 加上ORG 0xC200

3. 确认操作系统的执行情况

现在程序运行出来没有现象,因此我们加入一些屏幕显示来观察一下。在haribote.nas中加入程序如下:

  MOV AL,0x13 ; VGA显卡,320*200*8位彩色

MOV AH,0x00

INT 0x10

设置显卡模式:

AH =0x00AL=模式(省略了一些不重要的画面模式)

0x03:16字符模式;

0x12VGA图形模式640*480*4,独特的4面存储模式

0x13VGA图形模式320*200*8位彩色模式,调色板模式

0x6a:扩展VGA图形模式,800*600*4位彩色模式,独特的4面存储模式(有的显卡不支持这种模式)

返回值:无

这里我们采用0x13模式,因为8中彩色模式可以使用256中颜色,运行之后,我们可以发现画面变为一篇漆黑。

4. 32位模式的前期准备

由于本操作系统主要以C语言开发为主,由于本书使用的编译器只能生产32位的机器语言,如果要生成16位的机器语言也是可以做到的,但是很费事,其次,32位模式下可以使用的内存量远远大于1MB,而且,CPU的自我保护功能,在16位下不可用,但在32位下可用,并且,现在16位的模式几乎使用的很少,因此本书使用了32位的模式了。

可是如果用32位模式就不能调用BIOS功能了,这是因为BIOS是用16位机器语言写的,如果我们有什么事想用BIOS做的,那么就全部放在开头先做,一旦进入32位模式就不能调用BIOS函数了(当然,也可以从32位返回到16位的方法,但是非常费工夫)。

下面,我们就把画面模式,图像缓冲区地址,各个指示灯状态保存在内存中。

CYLS EQU 0x0ff0 ; 设定启动区

LEDS EQU 0x0ff1

VMODE EQU 0x0ff2 ; 关于颜色数目,位数

SCRNX EQU 0x0ff4 ; 分辨率X

SCRNY EQU 0x0ff6 ; 分辨率Y

VRAM EQU 0x0ff8 ; 图像缓冲区开始地址

 

ORG 0xc200 ; 装载到内存的位置

MOV AL,0x13 ; VGA模式

MOV AH,0x00

INT 0x10

MOV BYTE [VMODE],8 ; 记录画面模式

MOV WORD [SCRNX],320

MOV WORD [SCRNY],200

MOV DWORD [VRAM],0x000a0000

 

BIOS获得键盘上各种LED指示灯的状态,

MOV AH,0x02

INT 0x16  ; keyboard BIOS

MOV [LEDS],AL

注意,[VRAM]中保存的是显卡内存,不同的画面模式的像素数不一样,使用的内存也不一样。而本文所用的画面模式对应的内存为“0xa0000~0xaffff;64KB

5. 开始导入C语言

这个是本章中的重点,因为之后我们都要采用C语言进行系统的开发。程序中添加和修改了很多地方,在asmhead.nas中为了调用C语言程序,添加了100行代码。这部分作者也没有详细的去讲,我们暂时跳过。

添加了一个简单的C语言文件,bootpack.c。里面是一个无限循环。

文中又添加了c文件如何变成机器语言的步骤,写的很详细,大家可以看书。

下面主要讲解如何在C文件中调用汇编函数,首先我们编写一个汇编函数,如下:

 

[FORMAT "WCOFF"] ; 制作目标文件模式

[BITS 32] ; 制作32位模式用的机器语言

制作目标文件信息

[FILE "naskfunc.nas"] ; 源文件信息

GLOBAL _io_hlt ; 程序包含的函数名

以下是实际函数;

[SECTION .text] ; 目标文件写入这些后在写入程序

_io_hlt: ; void io_hlt(void);

HLT

RET

用汇编写的函数,之后还要与bootpack.obj连接,所以也需要编译成目标文件,因此将输出格式设定为WCOFF模式,另外,还要设定成32位机器语言模式。

注意要在函数名的前面加上“_”,否则就不能焊好的与C语言函数链接,需要链接的函数名都需要用GLOBAL指令声明。

在来看看C文件时如何调用的。

/*首先声明有一个函数在别的文件里;

void io_hlt(void);

/*;结尾表示函数在别的文件里;

void HariMain(void)

{

fin:

Io_hlt(); /* 执行naskfunc.nas_io_hlt函数 */

goto fin;

}

我们执行以下,正确,黑屏。

在本文的最后,我突然发现makefile的变化很大,有必要讲一讲,这里面现在采用变量的形式简化了里面的代码。里面按照代码的编译过程,增加了一些新的代码。这里有些代码我还有些不懂,就不说了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值