自己动手写操作系统:4.模拟软盘的数据结构,加载指定软盘扇区中的数据
来源:互联网 发布:苹果电脑怎么使用软件 编辑:程序博客网 时间:2024/05/22 01:37
前面两节介绍了如何在系统加载的时候在屏幕上打印出Hello OS!
我们是使用汇编直接对cpu进行操作,我们的数据容量只有启动扇区的512字节,这样的空间显然不够以后的开发使用。
本节我们引入软盘的数据结构,对软盘的数据结构进行模拟,并加载软盘中指定扇区的内容。
本节按照一下结构组织:
1.介绍软盘的物理以及逻辑结构
2.根据软盘逻辑结构,使用C语言创建软盘映像文件,并把数据写入软盘扇区
3.介绍如何使用汇编读取软盘中扇区的数据
4.实际运行测试
一.介绍软盘的物理以及逻辑结构
以一块软盘为例,一块软盘有两个面,正面和反面,每个面被80个圆环分成80个磁道(1-80),每个磁道(或者称为柱面)由18个扇区(0-17)组成,每个扇区的大小为512字节。
所以一块软盘的大小为 2*80*18*512 = 1474560 字节 = 1440KB = 1.44M
物理地址 逻辑扇区地址
0面0磁道 1扇区 0
0面0磁道 2扇区 1
: :
0面0磁道 18扇区 17
1面0磁道 1扇区 18
1面0磁道 2扇区 19
: :
1面0磁道18扇区 35
: :
我们把逻辑扇区地址可以看成大小为1.44M的数组的下标,每个数组元素的大小为512字节。
所以我们希望能根据 面 磁道 扇区 找到和 逻辑扇区的对应的关系,这样把对 面、磁道、扇区转化为对数组元素的操作,
这样就大大简化了我们的实现难度。
相对扇区号 = {盘面(0~1)*每条磁道扇区数(18)} + {2*磁道(0~79)*每条磁道扇区数(18)} + {扇区(1-18)-1};
对于我们制作写盘来说知道上面的公式就可以了,补充一点,知道了逻辑扇面号,怎么推断出 扇面 磁道 和 盘面 号呢?
而当知道相对扇区号,怎么推算出盘面、磁道、扇区呢?
具体步骤:
(1)从上面公式可以看出,相对扇区号对每条磁道扇区数(18)取余数 加1 就得到扇区;
(2)再根据(1)得到的商,如果盘面为1则商为奇数,否则为偶数,于是通过判断商的奇偶性,就可以得出盘;同时也可以算出磁道(减去1可得);
二、.根据软盘逻辑结构,使用C语言创建软盘映像文件,并把数据写入软盘扇区
下面是主程序 ReadWrite.c
#include "stdio.h" #include <stdlib.h> #include "floppy.h" #include <stdlib.h>void TestResult(FILE * fp) { if(feof(fp)) { //printf("Read OK\n"); //读取成功不许要打印消息 } else if(ferror(fp)) { printf("Read REEOR\n"); } } int main() { char Shan[512] = {0}; FILE *fpA = NULL; FILE *fpB = NULL; int ret = 0; int DateNo = 2*80*18*512; char * Floppy = NULL;char *meg = "This is message from floppy!" ; fpA = fopen("A.boot","rb");//1.修改文件名为A.boot 2.b表示打开对象为二进制文件 fpB = fopen("system.img","w+");//目的文件 if(0 != fflush(NULL)) { printf("flushall REEOR\n"); return 0; } if(NULL == fpA || NULL == fpB) { printf("open file error\n!"); return 0; } ret = fread(Shan, 1, DateNo,fpA);//读取A文件数据 if(ret != DateNo) { TestResult(fpA); } Shan[512-1-1] = 0x55;// 写512最后两字字节 Shan[512-1] = 0xaa; Floppy = MakeFloppy();if(False == WriteFloppy(0, 0, 1, Floppy, Shan)){printf("WriteFloppy Error!\n");free(Floppy);return 0;}if(False == WriteFloppy(0, 1, 4, Floppy, meg)){printf("WriteFloppy Error!\n");free(Floppy);return 0;} ret = fwrite(Floppy, 1, DateNo, fpB);//把缓冲文件写入到B文件中 if(ret != DateNo) { TestResult(fpB); } if(0 != fclose(fpB) && 0 != fclose(fpA) )//关闭所有打开的文件 { printf("fcloseall REEOR\n"); } free(Floppy); return 0; }
下面是创建软盘印象文件的具体实现程序floppy.c :
#include <stdio.h> #include <stdlib.h>
#include <string.h>#include "floppy.h" char * MakeFloppy(void){char * pFloppy = NULL;pFloppy = (char *)malloc(2*80*18*512);if(NULL == pFloppy){printf("malloc error!\n");}else{memset(pFloppy, 0, (2*80*18*512));}return pFloppy;}int CheckPara(char bSide, char bCidao, char bShanmian, char * pFloppy, char * pBuffe){if(NULL != pFloppy && NULL != pBuffe){if(0 == bSide || 1 == bSide){if(bCidao <= 79 && bCidao >= 0){if(bShanmian <= 18 && bShanmian >= 1){return True;}}}}return False;}static void WriteFloppyShanZero(char * pFloppy, char * pBuffe){int ShanNum = 512;int i = 0;for(i=0; i<ShanNum; i++){*pFloppy = *pBuffe;pFloppy++;pBuffe++;}}static void WriteFloppyShanNotZero(char * pFloppy, char * pBuffe){int ShanNum = 0;ShanNum = strlen(pBuffe);ShanNum = ShanNum/512;printf("we will write %d ShanQu\n", ShanNum+1);while(* pBuffe){*pFloppy = *pBuffe;pFloppy++;pBuffe++;}}int WriteFloppy(char bSide, char bCidao, char bShanmian, char * pFloppy, char * pBuffe){int LogicShanMian = 0;if(False == CheckPara(bSide, bCidao, bShanmian, pFloppy, pBuffe)){printf("Para error!\n");return False;}LogicShanMian = bSide * 18 + bCidao * 2 * 18 + (bShanmian - 1);pFloppy += LogicShanMian * 512;//把指针移动到第 LogicShanMian 个扇区开头if(0 == LogicShanMian){WriteFloppyShanZero(pFloppy, pBuffe);//0 扇区写满}else{WriteFloppyShanNotZero(pFloppy, pBuffe);}return True;}
三、介绍如何使用汇编读取软盘中扇区的数据
通过调用BIOS的 0x13 号中断,用于读取软盘数据,
在调用之前需要在相应的寄存器中设置该函数入参:
mov CH, 1 ;CH 用来存储磁道号
mov DH, 0 ;DH 用来存储磁头号
mov CL, 4 ;CL 用来存储扇区号
mov AH, 0x02 ; AH = 02 表示要做的是读盘操作
mov AL, 2 ; AL 表示要连续读取几个扇区
mov DL, 0 ;驱动器编号,一般我们只有一个软盘驱动器,所以写死为0
然后调用中断,具体的程序如下所示:
org 0x7c00;entry: mov ax, 0 mov ss, ax mov ds, ax mov es, ax mov si, msgreadFloppy: mov CH, 1 ;CH 用来存储磁道号 mov DH, 0 ;DH 用来存储磁头号 mov CL, 4 ;CL 用来存储扇区号 mov BX, msg ; ES:BX 数据存储缓冲区 mov AH, 0x02 ; AH = 02 表示要做的是读盘操作 mov AL, 2 ; AL 表示要练习读取几个扇区 mov DL, 0 ;驱动器编号,一般我们只有一个软盘驱动器,所以写死 ;为0 INT 0x13 ;调用BIOS中断实现磁盘读取功能 jc errorputloop: mov al, [si] add si, 1 cmp al, 0 je fin mov ah, 0x0e mov bx, 15 int 0x10 jmp putloopfin: HLT jmp finerror: mov si, errmsg jmp putloopmsg: RESB 64errmsg: DB "error"
注:(1)实际上从软盘读取到缓冲区是读的软盘扇区的起始地址,经过测试:在创建的“缓冲区”只有64的时候能也够读到3个扇区的内容。 (2)软盘多扇区的连续读或者写是按照逻辑扇区的顺序进行读写的,因此当创建好软盘之后可以直接往软盘中写入大于一个扇区的内容,超过的部分会自动写入逻辑上连续物理上不连续的扇区中。
4.实际运行测试
我们使用下面的命令来编译执行上面的程序:
A.asm -o A.boot && gcc ReadWrite.c floppy.c -g -o ReadWrite && ./ReadWrite
执行效果如图所示,可以在屏幕上看到我们写入到软盘中的数据:This is message from floppy!
- 自己动手写操作系统:4.模拟软盘的数据结构,加载指定软盘扇区中的数据
- 《自己动手写操作系统》初学笔记------软盘第一扇区写入问题解决方案
- 从boot读取软盘扇区中的汇编
- 软盘结构及软盘数据的读取
- 软盘结构及软盘数据的读取
- 读取软盘逻辑扇区的汇编过程
- 硬盘和软盘的引导扇区结构
- 硬盘和软盘的引导扇区结构
- 用软盘引导扇区加载.bin文件到内存…
- FAT12软盘引导扇区格式
- 软盘结构(磁头号和起始扇区的计算方法)
- 磁头号和起始扇区的计算方法------软盘结构
- 软盘结构(磁头号和起始扇区的计算方法)
- 磁头号和起始扇区的计算方法------软盘结构
- 突破BIOS无法连续读取软盘72扇区的限制
- ORANGE’S:一个操作系统的实现-chap4之:软盘结构(磁头号和起始扇区的计算方法)
- 《自己动手写操作系统》,软盘没有,用U盘引导,大白菜MBR Boot启动512字节反汇编代码!
- 从软盘引导操作系统
- 田忌赛马
- c#图像处理、图片拼接、图片裁剪、图片缩放、图上添加形状、屏幕截图、图片反色、改变图片色彩度全解
- imx6的mipi接口在qnx系统中的调试技巧,vcapture-test功能应用
- 无线中继和无线桥接
- 静态库和动态库的分析
- 自己动手写操作系统:4.模拟软盘的数据结构,加载指定软盘扇区中的数据
- ORACLE RAC集群的体系结构
- HDU 2017 多校联赛5 1011 Rikka with Competition
- WiFi有死角? 巧用旧无线路由器扩展覆盖.WDS设置
- 容器Collection的总结一 Vector ArrayList LinkedList HashSet TreeSet
- Spring MVC原理及配置详解
- 无线信号不好,如何进行扩展?(中继、无线桥接、级联、HyFi、AP/AC)
- QAQ & 火星情报局
- 街机捕鱼大亨游戏隐私政策