注:本文仍然主要来自《writeos-1.0-2-weekly》
一、加载指定扇区支指定空间
《运行自己的操作系统(linux版) -0.01》提到读入启动扇区,那是由硬盘自动完成的。
若要读入其它扇区到一个特定的内存空间,就要自己写代码完成,使用底层BIOS系统提供的BIOS 13h号中断,如图:
(1)读入一个扇区需要用到的参数,假设扇区号已知,需要用的参数及获取方法如下:
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)为了便于理解该函数,在涉及堆栈操作的地方画了几张图
二、查找一个指定文件
都在图里了,代码比较长,看原著吧
三、加载一个指定文件
(1)FAT12表项是12位的,即1.5个字节。若表项号为奇数,则取高12位,若为偶数,则取低12位
(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
四、测试
没有截图