上一期我讲述了如何在软盘的启动扇区写一些代码然后再从软盘启动的过程制作好一个启动扇区在切换到保护模式之前我们还应该知道如何使用BIOS中断BIOS中断是一些由BIOS提供的为了使操作系统的创建更容易的低级程序在本文中我们将学习处理BIOS的中断 为什么要用BIOS BIOS会把启动扇区拷贝至RAM中并且执行这些代码除此之外BIOS还要做很多其它的事情当一个操作系统刚开始启动时系统中并没有显卡驱动软盘驱动等任何驱动程序因此启动扇区中不可能包含任何一个驱动程序我们要采取其它的途径这个时候BIOS就可以帮助我们了BIOS中包含有各种可以使用的程序包括检测安装的设备控制打印机计算内存大小等用于各种目的的程序这些程序就是所说的BIOS中断 如何调用BIOS中断 在一般的程序设计语言中函数的调用是一件非常容易的事情比如在C语言中如果有一个名为display的程序它带有两个参数其中参数noofchar表示显示的字符数参数attr表示显示字符的属性那么要调用它只需给出程序的名称即可对于中断的调用我们使用的是汇编语言中的int指令 比如在C语言中要显示一些东西时使用的指令如下所示 display(nofcharattr) 而使用BIOS时要实现相同功能使用的指令如下 int x 如何传递参数 在调用BIOS中断之前我们需要先往寄存器中送一些特定的值假设要使用BIOS的中断h该中断的功能是把数据从软盘传送至内存之中在调用该中断之前要先指定拷贝数据的段地址指定驱动器号磁道号扇区号以及要传送的扇区数等等然后就要往相应的寄存器送入相应的值在进行下面的步骤前读者有必要对这一点有比较明确地认识 此外一个比较重要的事实是同一个中断往往可以实现各种不同的功能中断所实现的确切功能取决于所选择的功能号功能号一般都存在ah寄存器之中比如中断h可以用于读磁盘写磁盘等功能如果把送入ah寄存器中那么中断选择的功能就是写磁盘如果把送入ah寄存器中选择的功能则是读磁盘等 我们要做的事情 这次我们的源代码由两个汇编语言程序和一个C程序组成第一个汇编文件是引导扇区的代码在引导扇区中我们写的代码是要把软盘中第二扇区拷贝至内存段的x处(地址是x即偏移地址为)这时我们需要使用BIOS的中断h这时启动扇区的代码就会把控制权转移至x处在第二个汇编文件中代码会使用BIOS中断h在屏幕上显示一个信息C程序实现的功能则是把可执行的文件拷贝至启动扇区把可执行的文件拷贝至软盘的第二扇区 启动扇区代码 使用中断h启动扇区把软盘第二扇区里的内容加载至内存的x处(段地址为x)下面的代码是用于实现这一目的的代码将其保存至文件sbects中 LOC=x entry start start: mov ax#LOC mov esax mov bx# mov dl# mov dh# mov ch# mov cl# mov al# mov ah# int x jmpi #LOC 上面代码第一行类似于一个宏接下去的两行则是把值x加载至es寄存器中这是软盘上第二扇区代码将拷贝到的地方(第一扇区是启动扇区)这时把段内的偏移设为 接下来把驱动器号送入dl寄存器中其中磁头号送入dl寄存器中磁道号送入ch寄存器中扇区号送入cl寄存器中扇区数送入al寄存器之中我们想要实现的功能是把扇区磁道号为驱动器号为的内容送至段地址x处所有这些参数都和MB的软盘相对应 把送入ah寄存器中是选择了由中断h提供的相应功能即实现从软驱转移数据的功能 最后调用中断h并且转至偏移为的段地址x处 第二个扇区的代码 第二个扇区中的代码如下所示(把这些代码保存至文件sbects之中) entry start start: mov ah#x xor bhbh int x mov cx# mov bx#x mov bp#mymsg mov ax#x int x loop: jmp loop mymsg: byte ascii Operating System is Loading 上面代码将被加载至段地址为x处并且被执行在这段代码中使用了中断h来获取目前的光标位置然后显示信息 从第行到第行用于得到目前光标的位置在此中断h选用的是功能然后清除了bh寄存器的内容并把字符串送至ch寄存器中在bx中我们送入了页码及显示的属性此处我们想要在黑背景上显示白色的字符然后把要显示字符的地址送到bp之中信息由两个字节组成其值分别为的它们分别对应回车和LF(换行)的ASCⅡ值接下来是一个由个字符组成的串在下面实现的功能是输出字符串然后移动光标最后是调用中断然后进入循环 C程序代码 C程序的源代码如下所示将其存储为writec文件 #include /* unistdh needs this */#include /* contains read/write */ #include int main() { char boot_buf[]; int floppy_desc file_desc; file_desc = open(/bsect O_RDONLY); read(file_desc boot_buf ); close(file_desc); boot_buf[] = x; boot_buf[] = xaa; floppy_desc = open(/dev/fd O_RDWR); lseek(floppy_desc SEEK_SET); write(floppy_desc boot_buf ); file_desc = open(/sect O_RDONLY); read(file_desc boot_buf ); close(file_desc); lseek(floppy_desc SEEK_SET); write(floppy_desc boot_buf ); close(floppy_desc); } 在上一期中我曾经介绍过如何操作能启动的软盘现在这一个过程稍微有点不同首先把由bsects编译出来的可执行文件bsect拷贝至软盘的启动扇区然后再把由sects产生的可执行文件sect拷贝至软盘的第二个扇区 把上述文件置于同一目录之下然后分别对其进行编译方法如下所示 as bsects o bsecto ld d bsecto o bsect 对sects文件重复以上的操作得出可执行文件sect编译writec插入软盘后执行write文件命令如下所示 cc writec o write /write 下一步我们要做的事情 从软盘启动以后可以看到显示出来的字符串这是使用了BIOS中断来完成的下一期要做的事情是在这个操作系统中实现实模式向保护模式的转换 |