使用文件系统

注:本文仍然主要来自《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), %dl
GoOnReading:
    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 sector's 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,            %ax

LABEL_EVEN_2:
    and        $0x0fff,    %ax

LABEL_GET_FAT_ENTRY_OK:
    pop        %bx
    pop        %es
    ret

四、测试

没有截图

posted @ 2014-06-26 22:37  windmissing  阅读(302)  评论(0编辑  收藏  举报