D_D系统构建-MBR(8)filesystem.inc代码整改适配32位(附提供当前整个开发目录文件)

8 篇文章 0 订阅
4 篇文章 0 订阅

上几篇我们已经可以通过mbr加载loader文件,并能成功执行loader指令(PS<本章最下面将当前整个开发目录提供了出来,方便大家整个拷贝到本地进行验证)。

下面计划是要扩展我们的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
    ret

;-------------------------------------------------------------
;函数名: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空间。

近期项目又紧张,更新会慢,但不会中断。。。加油。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值