当前位置: 首页 > news >正文

自制操作系统(三、文件系统实现)

一、选择文件系统

通常来说,自制操作系统都是fat12,fat16,ext之类的

经过3周的努力,查阅了各方的资料,终于——失败

看着一堆的db,什么ata,我陷入了沉默

为什么不自制文件系统呢?

说干就干

尽管这是纯汇编操作系统,我还是决定用python构建文件系统

其实python只是为了编译方便...

fs.py

import os
import sysdef create_fs_asm(files):"""完全保持原样的暴力文件系统实现,仅添加二进制支持"""asm_content = """; 完全保持原样的暴力文件系统
section .data
global fs_files_count
fs_files_count dd %d; 文件系统API
global fs_init, fs_list_files, fs_read_filesection .textfs_init:retfs_list_files:mov esi, file_namesretfs_read_file:; 直接暴力比较文件名mov edi, esi
""" % len(files)for i, filename in enumerate(files):if not os.path.exists(filename):continuebase = os.path.splitext(filename)[0]clean_base = base.replace('.', '_').replace(' ', '_')asm_content += f"""; 检查文件: {filename}mov esi, file_{clean_base}_namecall str_compareje .found_{i+1}
"""asm_content += """; 文件未找到stcret
"""for i, filename in enumerate(files):if not os.path.exists(filename):continuebase = os.path.splitext(filename)[0]clean_base = base.replace('.', '_').replace(' ', '_')asm_content += f"""
.found_{i+1}:mov esi, file_{clean_base}_content_strclcret
"""asm_content += """
str_compare:push eaxpush esipush edi
.loop:mov al, [esi]cmp al, [edi]jne .not_equaltest al, aljz .equalinc esiinc edijmp .loop
.equal:xor eax, eaxjmp .done
.not_equal:or eax, 1
.done:pop edipop esipop eaxret
"""asm_content += """
section .data
file_names db """name_list = []for filename in files:if not os.path.exists(filename):continuename_list.append(f"'{filename} '")asm_content += ', '.join(name_list) + ',0\n\n'for filename in files:if not os.path.exists(filename):continuebase = os.path.splitext(filename)[0]clean_base = base.replace('.', '_').replace(' ', '_')# 二进制模式读取文件with open(filename, 'rb') as f:content = f.read()# 生成转义后的字符串escaped = []for byte in content:if byte == 0:  # 处理null字节escaped.append('\\0')elif byte == ord('\''):  # 处理单引号escaped.append('\\\'')elif byte == ord('\\'):  # 处理反斜杠escaped.append('\\\\')elif 32 <= byte <= 126:  # 可打印ASCIIescaped.append(chr(byte))else:  # 其他不可打印字符保持原样escaped.append(f'\\x{byte:02x}')asm_content += f"""
; 文件: {filename}
file_{clean_base}_name db '{filename}',0
file_{clean_base}_content_str db '{''.join(escaped)}',0
"""with open("fs.asm", "w") as f:f.write(asm_content)print("Created original brute-force fs.asm")if __name__ == "__main__":if len(sys.argv) < 2:print("Usage: python fs.py file1 [file2 ...]")sys.exit(1)create_fs_asm(sys.argv[1:])

本次的makefile

all:make binmake imgmake runbin:nasm boot.asm -o boot.binnasm loader.asm -o loader.bin#gcc -c -O0 -fno-builtin -m32 -fno-stack-protector -o main.o main.cnasm -f elf -o a.o a.asmi686-elf-ld -e _start -o a.run a.opython fs.py 123.txt qwe.txt a.runnasm -f elf -o kernel.o kernel.asmnasm -f elf -o io.o io.asmnasm -f elf -o shell.o shell.asmnasm -f elf -o file.o file.asmnasm -f elf -o fs.o fs.asmi686-elf-ld -s -Ttext 0x100000 -o kernel.bin kernel.o io.o file.o shell.o fs.oimg : boot.bin loader.bin kernel.bin#dd if=boot.bin of=a.img bs=512 count=1#dd if=loader.bin of=a.img bs=512 seek=1 conv=notrunc#python img.pyedimg   imgin:1.img \wbinimg src:boot.bin len:512 from:0 to:0 \copy from:loader.bin to:@: \copy from:kernel.bin to:@: \imgout:a.imgrun : a.img#qemu-system-i386 -fda a.imgqemu-system-i386 -fda a.img #-hda disk.img -boot a

shell.asm

;shell.asm
[bits 32]extern scroll_screen
[section .data]
; Shell界面
msg db "[root@Plain]-(/)# ", 0
cmd_buffer times 80 db 0; 命令定义
cmd_echo db "echo", 0
cmd_help db "help", 0
cmd_ls   db "ls", 0
cmd_cat  db "cat", 0
cmd_write db "write", 0
cmd_clear db "clear", 0cmd_time db "time", 0
time_str db "HH:MM:SS", 0
; 帮助信息
help_msg1 db "Available commands:", 0
help_msg2 db "  echo <message> - Display message", 0
help_msg3 db "  help          - Show this help", 0
help_msg4 db "  ls            - List files", 0
help_msg5 db "  cat <file>    - Show file content", 0
help_msg6 db "  write <file> > <content> - Write to file", 0
help_msg7 db "  clear         - Clear screen", 0; 错误和信息消息
not_msg db "Error: Command not found: ", 0
error_msg db "ERROR: Disk operation failed", 0
dir_entry db "  [DIR] ", 0
write_success db "Write successful", 0
write_fail db "Write failed", 0
invalid_format_msg db "Invalid write format. Use: write filename > content", 0[section .text]
extern print_str, put_char, get_key, clear_screen, fs_list_files, fs_files_count, fs_read_file extern scroll_screenglobal shell
shell:cmp ebx, 25ja .scrollmov ecx, 0mov esi, msgmov ah, 0x0Fcall print_str; 初始化命令缓冲区mov edi, cmd_buffermov ecx, 18          ; 从第18列开始输入mov byte [edi], 0    ; 清空缓冲区.input_loop:call get_keytest al, aljz .input_loop; 处理回车cmp al, 0x0Aje .execute; 处理退格cmp al, 0x08je .backspace; 存储并显示字符mov [edi], alinc edimov ah, 0x0Fcall put_charinc ecxjmp .input_loop.backspace:; 退格处理cmp edi, cmd_bufferje .input_loop       ; 忽略空退格dec edidec ecxmov al, ' 'mov ah, 0x0Fcall put_charjmp .input_loop.scroll:call scroll_screendec ebxjmp shell
.execute:; 添加字符串结束符mov byte [edi], 0; 检查空命令mov esi, cmd_buffercall is_emptyje .empty_cmd; 跳过前导空格call skip_spacestest al, aljz .empty_cmd; 检查help命令mov edi, cmd_helpcall cmd_cmpje .show_help; 检查echo命令mov edi, cmd_echocall cmd_cmpje .do_echo; 检查echo命令mov edi, cmd_lscall cmd_cmpje do_lsmov edi, cmd_timecall cmd_cmpje do_timemov edi, cmd_catcall cmd_cmpje do_cat;mov edi, cmd_write;call cmd_cmp;je do_write; 检查clear命令mov edi, cmd_clearcall cmd_cmpje .do_clear; 未知命令处理inc ebxmov ecx, 0mov esi, not_msgmov ah, 0x0C        ; 红色错误信息call print_str; 只显示命令部分(第一个空格前的内容)mov esi, cmd_buffercall print_command_partinc ebxjmp shell.empty_cmd:inc ebxmov ecx, 0jmp shell.show_help:; 显示帮助信息inc ebxmov ecx, 0mov esi, help_msg1mov ah, 0x0A        ; 绿色帮助信息call print_strinc ebxmov ecx, 0mov esi, help_msg2call print_strinc ebxmov ecx, 0mov esi, help_msg3call print_strinc ebxmov ecx, 0mov esi, help_msg4call print_strinc ebxmov ecx, 0mov esi, help_msg5call print_strinc ebxmov ecx, 0mov esi, help_msg6call print_strinc ebxmov ecx, 0mov esi, help_msg7call print_strinc ebxjmp shell.do_echo:; 跳过"echo"和后续空格add esi, 4call skip_spacestest al, aljz .no_args1         ; 无参数情况; 显示echo参数inc ebxmov ecx, 0mov ah, 0x0Fcall print_str.no_args1:inc ebx             ; 换行jmp shell; === clear命令实现 ===
.do_clear:call clear_screenmov ebx, 0mov ecx, 0jmp shell; === 辅助函数 ===; 打印命令部分(第一个空格前的内容)
print_command_part:pushamov ecx, 26         ; 错误信息后位置
.loop:lodsbtest al, aljz .donecmp al, ' 'je .donemov ah, 0x0Fcall put_charinc ecxjmp .loop
.done:poparet; 检查字符串是否为空或只有空格
is_empty:push esi
.loop:lodsbcmp al, ' 'je .looptest al, alpop esiret; 跳过字符串中的空格
skip_spaces:lodsbcmp al, ' 'je skip_spacesdec esi             ; 回退到第一个非空格字符ret; 命令比较函数
cmd_cmp:pusha
.compare:mov al, [esi]mov bl, [edi]; 检查命令是否结束(空格或字符串结束)cmp al, ' 'je .check_cmd_endtest al, aljz .check_cmd_end; 转换为小写比较cmp al, 'A'jb .no_change1cmp al, 'Z'ja .no_change1add al, 0x20
.no_change1:cmp bl, 'A'jb .no_change2cmp bl, 'Z'ja .no_change2add bl, 0x20.no_change2:cmp al, bljne .not_equalinc esiinc edijmp .compare.check_cmd_end:; 检查命令字符串是否也结束了cmp byte [edi], 0jne .not_equal.equal:popaxor eax, eax  ; ZF=1ret.not_equal:popaor eax, 1     ; ZF=0ret; 显示固定数量的字符
print_nchars:pushamov ah, 0x0F
.loop:lodsbcall put_charloop .looppoparetprint_hex:pushadmov ecx, 8
.loop:rol eax, 4mov ebx, eaxand ebx, 0x0fmov bl, [hex_chars + ebx]mov ah, 0x0Fcall put_charloop .looppopadretdo_time:call get_timeinc ebx             ; 换行mov ecx, 0mov esi, time_strmov ah, 0x0F        ; 白色文字call print_strjmp shellget_time:pushad; 禁用NMI并读取小时mov al, 0x04        ; 小时寄存器or al, 0x80         ; 禁用NMIout 0x70, alin al, 0x71call bcd_to_asciimov [time_str], dhmov [time_str+1], dl; 读取分钟mov al, 0x02or al, 0x80out 0x70, alin al, 0x71call bcd_to_asciimov [time_str+3], dhmov [time_str+4], dl; 读取秒mov al, 0x00or al, 0x80out 0x70, alin al, 0x71call bcd_to_asciimov [time_str+6], dhmov [time_str+7], dlpopadretbcd_to_ascii:; 将AL中的BCD码转换为两个ASCII字符,存储在DH和DL中mov dh, alshr dh, 4add dh, '0'mov dl, aland dl, 0x0Fadd dl, '0'ret; === ls命令实现 ===
do_ls:call fs_list_files; 显示文件名inc ebxmov ecx, 0mov ah, 0x0Fcall print_str; 换行inc ebxmov ecx, 0jmp shell; === cat命令实现 ===
do_cat:; 跳过"cat"和空格add esi, 3call skip_spacestest al, aljz .no_filename; 直接调用文件系统call fs_read_filejc .file_not_found; 显示内容 (esi已指向内容字符串)inc ebxmov ecx, 0mov ah, 0x0Fcall print_str  ; 直接打印整个内容inc ebxjmp shell.file_not_found:inc ebxmov ecx, 0mov esi, no_file_msgmov ah, 0x0Ccall print_str; 显示尝试的文件名mov esi, cmd_buffer+3mov ah, 0x0Fcall print_strinc ebxjmp shell.no_filename:inc ebxmov ecx, 0mov esi, cat_usage_msgmov ah, 0x0Ccall print_strjmp shellsection .bss
filename_buffer resb 32  ; 存储临时文件名; === 数据区 ===
[section .data]
no_file_msg db "File not found: ", 0
cat_usage_msg db "Usage: cat <filename>", 0
hex_chars db "0123456789ABCDEF"

 

一个make直接编译

 

终于完成了文件系统!

我知道你很高兴,但你先别高兴

我们没有用其他文件系统,这意味着我们无法执行写入操作

只能修改内存里文件位置指针指向的文件内容(就是重启后没有数据)

但我们的目的很简单,只是运行程序

这将在下一节实现

http://www.xdnf.cn/news/503461.html

相关文章:

  • 8天Python从入门到精通【itheima】-14~16
  • 【PhysUnits】4.2 Integer Trait
  • c/c++的opencv的轮廓匹配初识
  • 提升Qt应用性能--全面解析关键技术与策略
  • C++性能测试工具——Vtune的使用
  • BC 范式与 4NF
  • 全局异常处理:如何优雅地统一管理业务异常
  • Android屏幕采集编码打包推送RTMP技术详解:从开发到优化与应用
  • 数据结构第七章(四)-B树和B+树
  • Linux `mkdir` 命令深度解析与高阶应用指南
  • [逆向工程]C++实现DLL卸载(二十六)
  • 【算法】分支限界法和贪心、动态规划、回溯、分治法的区别是
  • 围炉夜话:三体阅读分析PPT+文稿
  • Java--利用(堆)获取前k个最小元素
  • 非易失性存储技术综合对比:EEPROM、NVRAM、NOR Flash、NAND Flash和SD卡
  • ​哈夫曼树(Huffman Tree)
  • C++ 回调函数
  • 计算机视觉与深度学习 | Python实现EEMD-LSTM时间序列预测(完整源码和数据)
  • JavaScript基础-预解析
  • 线程(二)OpenJDK 17 中线程启动的完整流程用C++ 源码详解之主-子线程通信机制
  • 如何彻底清空docker里面不使用的容器?
  • deepin v23.1 搜狗输入法next配置中文输入法下默认用英文标点
  • 符合Python风格的对象(对象表示形式)
  • 【机器学习】第二章模型的评估与选择
  • 【LeetCode】大厂面试算法真题回忆(91)--几何平均值最大子数组
  • vue引用cesium,解决“Not allowed to load local resource”报错
  • 调用DeepSeek系列模型问答时,输出只有</think>标签,而没有<think>标签
  • 无人机视角垃圾检测数据集VOC+YOLO格式771张1类别
  • 使用Maven和Ant上传文件到Linux服务器
  • 交流学习 | 江西同为科技有限公司赴海尔总部考察交流