D_D系统构建-MBR(8)filesystem.inc代码整改适配32位(附提供当前整个开发目录文件)
2017-07-28 22:50
429 查看
上几篇我们已经可以通过mbr加载loader文件,并能成功执行loader指令(PS<本章最下面将当前整个开发目录提供了出来,方便大家整个拷贝到本地进行验证)。
下面计划是要扩展我们的loader文件,来进入保护模式的,在保护模式中加载kernel文件,自然想复用我们已经有的filesystem.inc文件。
但检查过这个文件后,发现里面的函数寄存器基本使用的是16位的。且存在修改ds/es的操作。这在实模式下没有关系。但 在进入保护模式就会有问题了。
保护模式下,我们访问32位地址空间,基本要使用32位寄存器;同时在保护模式中ds/es等段寄存器的内容已经发生了变化(后面会说到),不再是实模式下的段物理地址了,而是变成了选择子的内容,如果 代码里面还有对ds/es赋值的,肯定会有问题。
因此需要以代码整改,包括两方面:1. 修改寄存器为32位 2.取消ds/es的修改。
代码如下:
filesystem.inc
最明显的变化是bp变成的ebp, 比如getDiskDataFromSectors,左侧是修改前,右侧是修改后的;还要注意的是用了32位后,实际的入栈参数偏移已经发生了变化 。
![](https://img-blog.csdn.net/20170728225647023?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
这里我们还多做了个文件,在写入boot后,先额外的写个其它文件(比如我们直接把boot.asm文件写入磁盘中),让它占用Inode0,然后再写入Loader.bin,通过这种方式来检查我们的查找loader.bin是否正确。如果 正确,它要显示 出Loader运行的提示。
我们把前面 的操作再重复一下, 操作按照如下步骤进行:
1. 先格式化我们的磁盘,并安装文件系统 。
使用我们之前编写的文件系统 初始化工具mkddfs,(D_D系统构建-文件写入方法: http://blog.csdn.net/b06030927/article/details/73050529)
![](https://img-blog.csdn.net/20170728230848802?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
2.编译并安装boot,这两个动作已经集成到makefile中。
![](https://img-blog.csdn.net/20170728231107993?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
3.在编译loader.bin之前,先安装个其它文件,我们选择了boot.asm,检查下inode分配是否正确,及后面写入loader.bin会不会有问题
![](https://img-blog.csdn.net/20170728231127662?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
4. 调用readddfs工具(同mkddfs), 查看当前文件系统 的应用情况,可以看到写入boot.asm后,可以看到它占用了一个Inode.同时能持到这个boot.asm文件大小,及占用的扇区情况。
![](https://img-blog.csdn.net/20170728231143952?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20170728231202294?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20170728231215531?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
5.此时 再编译并写入loader.bin,
![](https://img-blog.csdn.net/20170728231229216?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
6.检查下此时 的文件系统应用情况,占用两个inode,文件大小与实际 的大小一致。
![](https://img-blog.csdn.net/20170728231239512?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20170728231249648?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
7.最关键的一步到了,现在是检验我们的系统 能否正常加载 loader.bin了。运行bochs
![](https://img-blog.csdn.net/20170728231952575?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQjA2MDMwOTI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
很明显,它正确的找到了我们的Loader.bin,修改后的文件能正常生效,
这样,在下面的保护系统章节里面,我们还 能继续借用这个filessytem.inc函数,节省点开发时间。
PS: 另外,之前 一直没有找到能把整个开发文件目录打包并放到csdn上的方法,这里面把它压缩并放到百度网盘里面,下面是链接,不需要密码,大家随意取用。
http://pan.baidu.com/s/1o8iGp5K
这里面包含我使用的整个开发文件,大家下载后,到linux上解压开来,应该就可以使用。
下面开始我会改造当前的loader,让其工作在保护 模式下,跳出1M空间的限制,自由切换4G空间。
近期项目又紧张,更新会慢,但不会中断。。。加油。
下面计划是要扩展我们的loader文件,来进入保护模式的,在保护模式中加载kernel文件,自然想复用我们已经有的filesystem.inc文件。
但检查过这个文件后,发现里面的函数寄存器基本使用的是16位的。且存在修改ds/es的操作。这在实模式下没有关系。但 在进入保护模式就会有问题了。
保护模式下,我们访问32位地址空间,基本要使用32位寄存器;同时在保护模式中ds/es等段寄存器的内容已经发生了变化(后面会说到),不再是实模式下的段物理地址了,而是变成了选择子的内容,如果 代码里面还有对ds/es赋值的,肯定会有问题。
因此需要以代码整改,包括两方面:1. 修改寄存器为32位 2.取消ds/es的修改。
代码如下:
filesystem.inc
;文件系统相关的宏定义 MACRO_DDFS_SYSTEMBLOCK_START_SECTOR_NO EQU 1 MACRO_DDFS_SYSTEMBLOCK_SECTOR_NUM EQU 1 MACRO_DDFS_SECTORBITMAP_START_SECTOR_NO EQU 2 MACRO_DDFS_SECTORBITMAP_SECTOR_NUM EQU 1 MACRO_DDFS_INODEBITMAP_START_SECTOR_NO EQU 3 MACRO_DDFS_INODEBITMAP_SECTOR_NUM EQU 1 MACRO_DDFS_INODEINFO_START_SECTOR_NO EQU 4 MACRO_DDFS_INODEINFO_SECTOR_NUM EQU 512 MACRO_DDFS_FILESECTORLIST_START_SECTOR_NO EQU 516 MACRO_DDFS_FILESECTORLIST_SECTOR_NUM EQU 32 MACRO_DDFS_FILEDATA_START_SECTOR_NO EQU 548 MACRO_DDFS_FILEDATA_SECTOR_NUM EQU 3548 MACRO_DDFS_FILESYSTEM_SIZE_SYSTEMBLOCK EQU 16 MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_TOTALSECTORNUM EQU 0 MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_USEDSECTORNUM EQU 4 MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_TOTALINODENUM EQU 8 MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_USEDINODENUM EQU 12 MACRO_DDFS_FILESYSTEM_SIZE_INODEINFO EQU 64 MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILENAME EQU 0 MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESIZE EQU 32 MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESECTORNUM EQU 36 MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESTARTSECTOR EQU 40 MACRO_DDFS_FILESYSTEM_SIZE_FILESECTORLIST EQU 8 MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_ISNEXTVALID EQU 0 MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_NEXTSECTOR EQU 4 MACRO_DDFS_FILESYSTEM_INODE_NUM EQU 4096 globalSectorSpace: times 512 db 0 ;------------------------------------------------------------- ;函数名:getDiskDataFromSectors(起始扇区号, 扇区数目, 起始内存地址) ;函数说明:从指定起始扇区处连续加载指定扇区数目的数据到指定的内存起始位置处 ;函数参数: ; 参数说明 参数位置 参数大小 ; 起始扇区号, bp+4 2字节 ; 扇区数目, bp+6 2字节 ; 起始内存地址: bp+8 4字节 ;返回值: ; 无 ;------------------------------------------------------------- getDiskDataFromSectors: push ebp mov ebp, esp pushad ;加载的内存起始地址 mov edi, [ebp+10] ;要读取的扇区数目 mov ax, [ebp+8] ;起始扇区号 mov si, [ebp+6] mov dx,0x1f2 out dx,al ;读取的扇区数 inc dx ;0x1f3 mov ax,si out dx,al ;LBA地址7~0 inc dx ;0x1f4 mov al,ah out dx,al ;LBA地址15~8 xor ax, ax inc dx ;0x1f5 out dx,al ;LBA地址23~16 inc dx ;0x1f6 mov al,0xe0 ;LBA28模式,主盘 out dx,al inc dx ;0x1f7 mov al,0x20 ;读命令 out dx,al .waits: in al,dx and al,0x88 cmp al,0x08 jnz .waits ;不忙,且硬盘已准备好数据传输 ;计算要循环读取的字节数目,由于一次读取是2个字节,因此总字节除以2 mov ax, [ebp+8] mov bx, 512 mul bx mov bx, 2 div bx mov cx, ax mov dx,0x1f0 .readw: in ax,dx mov [edi],ax add edi, 2 loop .readw popad pop ebp ret ;------------------------------------------------------------- ;函数名:getSystemBlockData(buf) ;函数说明:获取文件系统块,保存buf中 ;函数参数: ; 参数说明 参数位置 参数大小 ; buf bp+4 4字节 ;返回值: ; 无 ;补充说明: ;------------------------------------------------------------- getSystemBlockData: push ebp mov ebp, esp pushad mov eax, [ebp+6] push eax mov ax, MACRO_DDFS_SYSTEMBLOCK_SECTOR_NUM push ax mov ax, MACRO_DDFS_SYSTEMBLOCK_START_SECTOR_NO push ax call getDiskDataFromSectors pop ax pop ax pop eax popad pop ebp ret ;------------------------------------------------------------- ;函数名:getInodeBitMapData(buf) ;函数说明:获取inodebitmap,保存到buf中 ;函数参数: ; 参数说明 参数位置 参数大小 ; buf bp+4 4字节 ;返回值: ; 无 ;补充说明: ;------------------------------------------------------------- getInodeBitMapData: push ebp mov ebp, esp pushad mov eax, [ebp+6] push eax mov ax, MACRO_DDFS_INODEBITMAP_SECTOR_NUM push ax mov ax, MACRO_DDFS_INODEBITMAP_START_SECTOR_NO push ax call getDiskDataFromSectors pop ax pop ax pop eax popad pop ebp ret ;------------------------------------------------------------- ;函数名:getInodeInfoByInodeIndex(inodeindex, buf) ;函数说明:通过inode索引获取对应的inodeinfo ;函数参数: ; 参数说明 参数位置 参数大小 ; inodeindex bp+4 2 ; buf bp+6 4字节 ;返回值: ; eax: 0:未使用 1:已经使用 ;补充说明: ;------------------------------------------------------------- getInodeInfoByInodeIndex: push ebp mov ebp, esp pushad mov ax, [ebp+6] xor edx, edx mov bx, MACRO_DDFS_FILESYSTEM_SIZE_INODEINFO mul bx ;除以512后,ax保存扇区偏移,dx保存扇区内偏移 mov bx, 512 div bx add ax, MACRO_DDFS_INODEINFO_START_SECTOR_NO mov ebx, globalSectorSpace push ebx mov bx, 1 push bx mov bx, ax push bx call getDiskDataFromSectors pop bx pop bx pop ebx ;将64字节内容拷贝到用户区 xor esi, esi mov esi, globalSectorSpace add esi, edx xor edi, edi mov edi, [ebp+8] mov cx, MACRO_DDFS_FILESYSTEM_SIZE_INODEINFO cld rep movsb popad pop ebp ret ;------------------------------------------------------------- ;函数名:getFileSectorListBySector(sector, buf) ;函数说明:通过Secto索引获取对应的filesectorlist信息 ;函数参数: ; 参数说明 参数位置 参数大小 ; sector bp+4 2 ; buf bp+6 4字节 ;返回值: ; eax: 0:未使用 1:已经使用 ;补充说明: ;------------------------------------------------------------- getFileSectorListBySector: push ebp mov ebp, esp pushad mov ax, [ebp+6] xor edx,edx mov bx, MACRO_DDFS_FILESYSTEM_SIZE_FILESECTORLIST mul bx mov bx,512 div bx mov ebx, globalSectorSpace push ebx mov bx, 1 push bx mov bx, MACRO_DDFS_FILESECTORLIST_START_SECTOR_NO add bx, ax push bx call getDiskDataFromSectors pop bx pop bx pop ebx ;将8字节内容拷贝到用户区 mov esi, globalSectorSpace add esi, edx mov edi, [ebp+8] mov cx, MACRO_DDFS_FILESYSTEM_SIZE_FILESECTORLIST cld rep movsb popad pop ebp re 4000 t ;------------------------------------------------------------- ;函数名:checkFileNameIsSame(dstFileName, srcFileName, FileLen, outBuf) ;函数说明:比较指定长度的源目的文件名是否相同 ;函数参数: ; 参数说明 参数位置 参数大小 ; dstFileName bp+4 4字节 ; srcFileName bp+8 4字节 ; dstFileName bp+12 2字节 ; outBuf bp+14 4字节 ;返回值: ; outBuf: 0:不相同 1:相同 ;补充说明: ;------------------------------------------------------------- checkFileNameIsSame: push ebp mov ebp, esp pushad mov esi, [ebp+6] mov edi, [ebp+10] mov cx, [ebp+14] cld repz cmpsb cmp cx, 0 jz file_name_same mov esi, [ebp+16] mov word [esi], 0 popad pop ebp ret file_name_same: mov esi, [ebp+16] mov word [esi], 1 popad pop ebp ret ;------------------------------------------------------------- ;函数名:checkFileNameIsSame(bitIndex, bitBuffer, outBuf) ;函数说明:比较指定长度的源目的文件名是否相同 ;函数参数: ; 参数说明 参数位置 参数大小 ; bitIndex bp+4 2字节 ; bitBuffer bp+6 4字节 ; outBuf bp+10 4字节 ;返回值: ; outBuf: 0:不相同 1:相同 ;补充说明: ;------------------------------------------------------------- checkBitIsSet: push ebp mov ebp, esp pushad xor eax, eax mov ax, [ebp+6] mov ebx, [ebp+8] mov ecx, [ebp+12] push ebx xor dx, dx mov bx, 8 div bx pop ebx add ebx, eax mov esi, ebx bt [esi], dx jc bit_is_set mov esi, ecx mov word [esi], 0 popad pop ebp ret bit_is_set: mov esi, ecx mov word [esi], 1 popad pop ebp ret
最明显的变化是bp变成的ebp, 比如getDiskDataFromSectors,左侧是修改前,右侧是修改后的;还要注意的是用了32位后,实际的入栈参数偏移已经发生了变化 。
这里我们还多做了个文件,在写入boot后,先额外的写个其它文件(比如我们直接把boot.asm文件写入磁盘中),让它占用Inode0,然后再写入Loader.bin,通过这种方式来检查我们的查找loader.bin是否正确。如果 正确,它要显示 出Loader运行的提示。
我们把前面 的操作再重复一下, 操作按照如下步骤进行:
1. 先格式化我们的磁盘,并安装文件系统 。
使用我们之前编写的文件系统 初始化工具mkddfs,(D_D系统构建-文件写入方法: http://blog.csdn.net/b06030927/article/details/73050529)
2.编译并安装boot,这两个动作已经集成到makefile中。
3.在编译loader.bin之前,先安装个其它文件,我们选择了boot.asm,检查下inode分配是否正确,及后面写入loader.bin会不会有问题
4. 调用readddfs工具(同mkddfs), 查看当前文件系统 的应用情况,可以看到写入boot.asm后,可以看到它占用了一个Inode.同时能持到这个boot.asm文件大小,及占用的扇区情况。
5.此时 再编译并写入loader.bin,
6.检查下此时 的文件系统应用情况,占用两个inode,文件大小与实际 的大小一致。
7.最关键的一步到了,现在是检验我们的系统 能否正常加载 loader.bin了。运行bochs
很明显,它正确的找到了我们的Loader.bin,修改后的文件能正常生效,
这样,在下面的保护系统章节里面,我们还 能继续借用这个filessytem.inc函数,节省点开发时间。
PS: 另外,之前 一直没有找到能把整个开发文件目录打包并放到csdn上的方法,这里面把它压缩并放到百度网盘里面,下面是链接,不需要密码,大家随意取用。
http://pan.baidu.com/s/1o8iGp5K
这里面包含我使用的整个开发文件,大家下载后,到linux上解压开来,应该就可以使用。
下面开始我会改造当前的loader,让其工作在保护 模式下,跳出1M空间的限制,自由切换4G空间。
近期项目又紧张,更新会慢,但不会中断。。。加油。
相关文章推荐
- D_D系统构建-MBR(7)加载loader文件代码filesystem.inc解析
- 构建根文件系统(1)Linux root filesystem目录结构
- D_D系统构建-开发文件目录结构
- D_D系统构建-MBR(6)加载loader文件代码MBR解析
- 构建根文件系统的/dev目录
- Linux系统基础开发技术1:构建Linux 库文件
- 有关在TreeView上递归显示整个系统盘符文件目录及文件 !
- 构建arm linux 的根文件系统 root filesystem
- 构建根文件系统(4)构建etc目录
- The Linux Bootdisk HOWTO 之 4. Building a root filesystem 构建根文件系统
- 贴一段eclipse插件开发中获取当前package explorer中选中的目录代码
- Windows命令行获取当前bat文件所在目录,添加永久系统环境变量的方法
- 进行DOS系统调用,删除一个当前目录下的文件
- 构建根文件系统(5)构建dev目录
- Linux系统基础开发技术1:构建Linux 库文件
- 在WM系统上构建你的销售系统--代码开源提供
- 整个ROOT文件系统目录的制作
- 使用MFC搜索当前目录下所存在的某种文件,将文件名(路径等)添加到下拉框中,返回文件个数,部分关键代码。。
- Linux系统基础开发技术1:构建Linux 库文件
- SQL SERVER 2008复制--代理消息代码 21100。 分发代理无法在“C:\Program Files\Microsoft SQL Server\100\COM”目录中创建临时文件。系统返回的错误代码为 5。