自己动手写操作系统( 三 )


而使用BIOS时,要实现相同功能使用的指令如下:int 0x10
如何传递参数
在调用BIOS中断之前,我们需要先往寄存器中送一些特定的值 。假设要使用BIOS的中断13h,该中断的功能是把数据从软盘传送至内存之中 。在调用该中断之前,要先指定拷贝数据的段地址,指定驱动器号、磁道号、扇区号,以及要传送的扇区数等等 。然后,就要往相应的寄存器送入相应的值 。在进行下面的步骤前,读者有必要对这一点有比较明确地认识 。此外,一个比较重要的事实是同一个中断往往可以实现各种不同的功能 。中断所实现的确切功能取决于所选择的功能号,功能号一般都存在ah寄存器之中 。比如中断13h可以用于读磁盘、写磁盘等功能,如果把3送入ah寄存器中,那么中断选择的功能就是写磁盘;如果把2送入ah寄存器中,选择的功能则是读磁盘等 。
我们要做的事情
这次我们的源代码由两个汇编语言程序和一个C程序组成 。第一个汇编文件是引导扇区的代码 。在引导扇区中,我们写的代码是要把软盘中第二扇区拷贝至内存段的0x500处(地址是0x5000,即偏移地址为0) 。这时我们需要使用BIOS的中断13h 。这时启动扇区的代码就会把控制权转移至0x500处 。在第二个汇编文件中,代码会使用BIOS中断10h在屏幕上显示一个信息 。C程序实现的功能则是把可执行的文件1拷贝至启动扇区,把可执行的文件2拷贝至软盘的第二扇区 。
启动扇区代码
使用中断13h,启动扇区把软盘第二扇区里的内容加载至内存的0x5000处(段地址为0x500) 。下面的代码是用于实现这一目的的代码,将其保存至文件sbect.s中 。LOC1=0x500
entry start
start:
mov ax,#LOC1
mov es,ax
mov bx,#0
mov dl,#0
mov dh,#0
mov ch,#0
mov cl,#2
mov al,#1
mov ah,#2
int 0x13
jmpi 0,#LOC1
上面代码第一行类似于一个宏 。接下去的两行则是把值0x500加载至es寄存器中,这是软盘上第二扇区代码将拷贝到的地方(第一扇区是启动扇区) 。这时,把段内的偏移设为0 。接下来把驱动器号送入dl寄存器中,其中磁头号送入dl寄存器中,磁道号送入ch寄存器中,扇区号送入cl寄存器中,扇区数送入al寄存器之中 。我们想要实现的功能是把扇区2、磁道号为0、驱动器号为0的内容送至段地址0x500处 。所有这些参数都和1.44MB的软盘相对应 。把2送入ah寄存器中,是选择了由中断13h提供的相应功能,即实现从软驱转移数据的功能 。最后调用中断13h,并且转至偏移为0的段地址0x500处 。
第二个扇区的代码
第二个扇区中的代码如下所示(把这些代码保存至文件sbect2.s之中):entry start
start:
mov ah,#0x03
xor bh,bh
int 0x10mov cx,#26
mov bx,#0x0007
mov bp,#mymsg
mov ax,#0x1301
int 0x10loop1: jmp loop1
mymsg:
.byte 13,10
.ascii “Operating System is Loading......”
上面代码将被加载至段地址为0x500处,并且被执行 。在这段代码中,使用了中断10h来获取目前的光标位置,然后显示信息 。从第3行到第5行用于得到目前光标的位置,在此中断10h选用的是功能3 。然后,清除了bh寄存器的内容,并把字符串送至ch寄存器中 。在bx中,我们送入了页码及显示的属性 。此处,我们想要在黑背景上显示白色的字符 。然后,把要显示字符的地址送到bp之中,信息由两个字节组成,其值分别为13的10,它们分别对应回车和LF(换行)的ASCⅡ值 。接下来是一个由29个字符组成的串;在下面实现的功能是输出字符串然后移动光标;最后是调用中断,然后进入循环 。
C程序代码
C程序的源代码如下所示,将其存储为write.c文件 。#include/* unistd.h needs this */
#include /* contains read/write */

推荐阅读