首页 > 代码库 > 使用文件系统

使用文件系统

注:本文仍然主要来自《writeos-1.0-2-weekly》

一、加载指定扇区支指定空间

《运行自己的操作系统(linux版) -0.01》提到读入启动扇区,那是由硬盘自动完成的。

若要读入其它扇区到一个特定的内存空间,就要自己写代码完成,使用底层BIOS系统提供的BIOS 13h号中断,如图:

1R_50XT5RVZ73608T

(1)读入一个扇区需要用到的参数,假设扇区号已知,需要用的参数及获取方法如下:

QQ截图20140626195325

al 扇区数 根据需要填写,本文中为1
cx高10位 柱面号 由上图公式计算
cx低6位 扇区号 根据需要填写
dh 磁头号 由上图公式计算
dl 驱动器 根据需要填写,软盘为0
es:bx 数据缓冲区地址 根据需要填写

(2)把各个寄存器的值按如图设置,然后调用13号中断,该扇区的内容就被读到ES:BX空间中

(3)代码实现

/*=====================================================================  Routine: ReadSector  Action: Read %c1 Sectors from %ax sector(floppy) to %es:%bs(memory)  Assume sector number is x, then    x / (BPB_SecPerTrk) = y,    x % (BPB_SecPerTrk) = z.  The remainder z plus 1 is the start sector number;  The quotient y devied by BPB_NumberHeads(RIGHT SHIFT 1 bit) is sylinder number;  AND y by 1 can got magnetic header.*/ReadSector:                            /*图0*/     push    %ebp                       /*图1*/    mov        %esp,    %ebp           /*图2*/     sub        $2,        %esp        /*图3,Reserve space for saving %cl*/    mov        %cl,    -2(%ebp)        /*图4*/     push    %bx                    /*图5,Save bx*/    mov        (BPB_SecPerTrk), %bl/*%bl: the devider*/    div        %bl                    /*y in %al, z in %ah*/    inc        %ah                    /*z++, got start sector*/    mov        %ah,    %cl            /*%cl <- start sector number*/    mov        %al,    %dh            /*%dh <- y*/    shr        $1,        %al            /*y / BPB_NumberHeads*/    mov        %al,    %ch            /*%ch <- Cylinder number(y>>1)*/    and        $1,        %dh            /*%dh <- Magnetic header(Y&1)*/    pop        %bx                    /*图6, Restore %bx*/    /*Now we got cylinder number in %ch, start sector number in %cl, magnetic header in %dh.*/    mov        (BS_DrvNum), %dlGoOnReading:    mov        $2,        %ah    mov        -2(%ebp), %al        /*Read %al sectors,根据图6,%al得到的是图4存入的%cl*/    int        $0x13    jc        GoOnReading            /*If CF set 1, mean read error, reread.*/    add        $2,        %esp        /*图7*/     pop        %ebp                   /*图8*/     ret

(4)为了便于理解该函数,在涉及堆栈操作的地方画了几张图

IMG_3682

二、查找一个指定文件

都在图里了,代码比较长,看原著吧

IMG_3683

三、加载一个指定文件

(1)FAT12表项是12位的,即1.5个字节。若表项号为奇数,则取高12位,若为偶数,则取低12位

IMG_3684

(2)代码

/*=====================================================================  Routine: GetFATEntry  Action: Find %ax sectors index in FAT, save result in %ax*/GetFATEntry:    push    %es    push    %bx    push    %ax    mov        $BaseOfLoader, %ax    sub        $0x0100,    %ax    mov        %ax,        %es    pop        %ax    mov        $3,            %bx    mul        %bx    mov        $2,            %bx    div        %bx    movb    %dl,        (bOdd)LABEL_EVEN:    xor        %dx,        %dx    mov        (BPB_BytsPerSec),%bx    div        %bx    push    %dx    mov        $0,            %bx    add        $SecNoOfFAT1,%ax    mov        $2,            %cl    call    ReadSector    pop        %dx    add        %dx,        %bx    mov        %es:(%bx),    %ax    cmpb    $0,            (bOdd)    jz        LABEL_EVEN_2    shr        $4,            %axLABEL_EVEN_2:    and        $0x0fff,    %axLABEL_GET_FAT_ENTRY_OK:    pop        %bx    pop        %es    ret

四、测试

没有截图