开发操作系统前的第一个程序

虚拟机选好了,开发工具选好了,平台选好了,可以开始开发操作系统了吗?其实,还不行,要先准备一个工具程序 - 安装引导程序的程序

为什么要先开发安装引导程序的程序?

原因很简单,如果你马上开始写系统,比如引导程序,就算你写好了操作系统的第一个要运行的引导程序,你也会发现一个问题,你要怎么写到硬盘里?在windows里面复制到硬盘就行?当然不行了,因为你根本无法直接操作扇区。所以,不管怎么样,都要把直接读写硬盘的工具程序先开发出来,其实这就是安装操作系统的最后一步要用的程序:安装引导程序的程序

一般来说,在复制完操作系统所需的文件后,才会安装引导程序,毕竟来说,如果原来的磁盘有系统,如果一开始就把引导给改了,如果新系统又没装成,那连原来的系统也引导不了了。如果在复制完所有的文件后,在安装引导程序,那安装的风险就会下降很多很多。

安装引导程序的程序的运行方式

这个程序有几种运行方式:1、在windows或linux下运行;2、在DOS下运行;3、在自己的系统里运行

在windows或linux下运行

在我看来,这仅仅是在开发完成后,正式安装程序用的可选方式之一。

为什么?

这就要考虑在物理机器上的运行方式了,难道你在物理机器上测试的时候,还把电脑拆开挂个硬盘上去后,在windows里运行完安装程序后,再把安装好的系统硬盘拆下来装到别的地方上去?或者说在用U盘启动windows后,在windows里安装?虽然能做到,但每次启动windows的时间,就够你烦的。当然,如果你想借机休息,那倒是应该在windows下运行。

在DOS下运行

这是我选择的方式,很简单,做成DOS启动盘以后来安装和测试很简单,即使在物理机上用U盘启动DOS也很简单。更重要的是,我可以把安装程序放进虚拟软盘里,测试安装过程。在软盘上测OK了,在转到U盘上测试,不用一上来就搞物理机。

在自己的系统中运行

这是终极方法,所有的操作系统都必须这么做,但是现在还做不到,只能放弃

工具程序的功能

这个工具程序的主要功能其实很简单,就是把MBR启动程序和活动分区的启动程序写到对应的地方,核心功能是直接读写硬盘。在这个功能之上,可以发展出其他辅助的功能。

DOS下直接读写硬盘 – INT 13H

详细的内容放到书里的附录写,这里只放DAP的结构、扩展读、扩展写两个调用规范

/*  extend INT 13H use this */
typedef struct _disk_address_packet_t
{
    unsigned char   dap_PacketSize,
                    dap_Rsvd;
    unsigned short  dap_BlockCount;
    unsigned long   dap_BufAddress;         /*  segment:offset */
    unsigned long   dap_BlockNum;           /*  Low 32-bit */
    unsigned long   dap_BlockNumH;          /*  high 32-bit */
}dap_t;

扩展读
入口:
AH = 42h
DL = 驱动器号
DS:SI = 磁盘地址数据包(Disk Address Packet)
返回:
CF = 0,AH = 0 成功
CF = 1,AH = 错误码
这个调用将磁盘上的数据读入内存。如果出现错误,DAP 的 BlockCount项中则记录了出错前实际读取的数据块个数。

扩展写
入口:
AH = 43h
AL
0 位 = 0 关闭写校验
1 打开写校验
1 - 7 位保留,置 0
DL = 驱动器号
DS:SI = 磁盘地址数据包(DAP)
返回:
CF = 0,AH = 0 成功
CF = 1,AH = 错误码
这个调用将内存中的数据写入磁盘。如果打开了写校验选项,但 BIOS不支持,则会返回错误码 AH = 01h,CF = 1。功能 48h 可以检测BIOS是否支持写校验。
如果出现错误,DAP 的 BlockCount 项中则记录了出错前实际写入的数据块个数。

这里有一点要注意:网络上很多资料把DS:SI写成了DS:DI

DOS下直接读写硬盘的C函数

把INT 13H的读写的功能封装成C函数,就完事了,没那么神秘。函数贴出来,

/* 2019-10-12. order source. robin.
purpose : Read/Write hard disk directly.
argument:
    char nDisk:   hard disk id, base 0 
    int bRW:   1 read disk, 0 write disk
    unsigned long nSectAddr:   32-bit sector address 
    void * pBuf:      sector buffer
    unsigned int nBufSize: buffer size
    
output  : success return 0, failed return other 
*/    
int DiskRW( char nDisk, int bRW, unsigned long nSectAddr, void * pBuf,
    unsigned int nBufSize )  
{
    unsigned char   nCmd, retval;
    dap_t           dap;

    nCmd = bRW ? 0x42 : 0x43;

    /*  limit the read/write size */
    if( nBufSize > (unsigned int)(32 * 1024) )
        return 1;
    if( 0 == (nBufSize /= 512) )
        return 0;
    dap.dap_PacketSize  = sizeof(dap_t);
    dap.dap_Rsvd        = 0;
    dap.dap_BlockCount  = (unsigned short)nBufSize;
    dap.dap_BufAddress  = (unsigned long)((void far *)(pBuf));
    dap.dap_BlockNum    = nSectAddr;
    dap.dap_BlockNumH   = 0;
    nDisk |= 0x80;
    asm{
        lea     si, dap;
        mov     dl, nDisk;
        mov     ah, nCmd
        int     013h
        mov     retval, ah
    }
    return retval;
}

DOS下安装引导程序的程序

就是一个直接读写硬盘的程序,
》》读:功能就是把读出的扇区数据保存到文件中。
》》写:把文件中的数据写到扇区中
读写的单位都是一个扇区,如果提供的数据文件不足一个扇区,也会写一个扇区的数据进去。

这个程序为了写书临时写了一个简化的版本,很简单的,就100行左右的程序,这里贴一个运行的截图
直接读写磁盘程序

完整的程序就不贴出来了,可以把这个程序当作安装引导程序的程序,写个批处理逐个扇区写进去就行了,就是要自己把每个扇区单独做成一个文件。

真正用的程序,比较复杂,毕竟要考虑很多不同的运行环境。

如果是初学者,可以用DiskRW这个代码自己扩展,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值