07 突破512字节的限制 中
https://www.cnblogs.com/wanmeishenghuo/tag/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/
https://blog.51cto.com/13475106/category6.html
及狄泰软件相关课程
上一节我们写了字符串打印的函数和软盘读取函数,在软盘读取函数中,我们是直接给定了要读的逻辑扇区号,这一节我们来实现一个查找文件的功能,也就是根据给定的文件名,在根目录区中查找指定的文件是否存在,涉及到文件名的查找,就会涉及到内存的比较,因此,我们需要实现两个函数,分别为内存比较函数和根目录区查找函数。
整体的流程如下:
首先将根目录区加载到内存中的指定位置上,这里面包含了一定数目的根目录项,而根目录项的前11个字节为文件名,因此,查找文件的工作就可以进行了,我们只需要将目标文件名和每一个根目录项的前11个字节进行比较即可,如果文件存在,必定会在某一个目录项中找到,只需将目录项的偏移位置通过寄存器返回即可。
内存比较的示意图如下:
需要用到的两个指令如下:
比较指令:cmp cx, 0 ; 比较cx的值是否为零
跳转:jz equal ; 如果比较的结果为真,则跳转到equal处
用于比较的汇编程序片段如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | org 0x7c00 jmp short start nop define: BaseOfStack equ 0x7c00 RootEntryOffset equ 19 RootEntryLength equ 14 header: BS_OEMName db "D.T.Soft" BPB_BytsPerSec dw 512 BPB_SecPerClus db 1 BPB_RsvdSecCnt dw 1 BPB_NumFATs db 2 BPB_RootEntCnt dw 224 BPB_TotSec16 dw 2880 BPB_Media db 0xF0 BPB_FATSz16 dw 9 BPB_SecPerTrk dw 18 BPB_NumHeads dw 2 BPB_HiddSec dd 0 BPB_TotSec32 dd 0 BS_DrvNum db 0 BS_Reserved1 db 0 BS_BootSig db 0x29 BS_VolID dd 0 BS_VolLab db "D.T.OS-0.01" BS_FileSysType db "FAT12 " start: mov ax, cs mov ss, ax mov ds, ax mov es, ax mov sp, BaseOfStack mov si, MsgStr mov di, DEST mov cx, MsgLen call MemCmp cmp cx, 0 jz label jmp last label: mov bp, MsgStr mov cx, MsgLen call Print output: mov bp, MsgStr mov cx, MsgLen call Print last: hlt jmp last ; ds:si --> source ; es:di --> destination ; cx --> length ; ; return : ; (cx == 0) ? equal : noequal MemCmp: push si push di push ax compare: cmp cx, 0 jz equal mov al, [si] cmp al, byte [di] jz goon jmp noequal goon: inc si inc di dec cx jmp compare equal: noequal: pop ax pop di pop si ret ; es:bp --> string address ; cx --> string length Print: mov ax, 0x1301 mov bx, 0x0007 int 0x10 ret ; no parameter ResetFloppy: push ax push dx mov ah, 0x00 mov dl, [BS_DrvNum] int 0x13 pop dx pop ax ret ; ax --> logic sector number ; cx --> number of sector ; es:bx --> target address ReadSector: push bx push cx push dx push ax call ResetFloppy push bx push cx mov bl, [BPB_SecPerTrk] div bl mov cl, ah add cl, 1 mov ch, al shr ch, 1 mov dh, al and dh, 1 mov dl, [BS_DrvNum] pop ax pop bx mov ah, 0x02 read: int 0x13 jc read pop ax pop dx pop cx pop bx ret MsgStr db "Hello World" MsgLen equ ($-MsgStr) DEST db "Hello World" Buf: times 510-($-$$) db 0x00 db 0x55, 0xaa |
运行结果如下:
上图的程序中,我们直接比较的字符串“Hello World”,如果比较成功,就将字符串打印出来。
下面我们进行文件的查找,具体流程如下图:
首先加载根目录区,将根目录区加载到指定的缓冲区中,程序片段如下:
访问栈顶数据时,不能通过sp直接访问,而要经过其他寄存器间接访问,如下:
有了以上的思路后,我们直接给出查找文件的汇编程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | org 0x7c00 jmp short start nop define: BaseOfStack equ 0x7c00 RootEntryOffset equ 19 RootEntryLength equ 14 header: BS_OEMName db "D.T.Soft" BPB_BytsPerSec dw 512 BPB_SecPerClus db 1 BPB_RsvdSecCnt dw 1 BPB_NumFATs db 2 BPB_RootEntCnt dw 224 BPB_TotSec16 dw 2880 BPB_Media db 0xF0 BPB_FATSz16 dw 9 BPB_SecPerTrk dw 18 BPB_NumHeads dw 2 BPB_HiddSec dd 0 BPB_TotSec32 dd 0 BS_DrvNum db 0 BS_Reserved1 db 0 BS_BootSig db 0x29 BS_VolID dd 0 BS_VolLab db "D.T.OS-0.01" BS_FileSysType db "FAT12 " start: mov ax, cs mov ss, ax mov ds, ax mov es, ax mov sp, BaseOfStack mov ax, RootEntryOffset mov cx, RootEntryLength mov bx, Buf call ReadSector mov si, Target mov cx, TarLen mov dx, 0 call FindEntry cmp dx, 0 jz output jmp last output: mov bp, MsgStr mov cx, MsgLen call Print last: hlt jmp last ; es:bx --> root entry offset address ; ds:si --> target string ; cx --> target length ; ; return : ; (dx != 0) ? exist : noexist ; exist --> bx is the target entry FindEntry: push di push bp push cx mov dx, [BPB_RootEntCnt] mov bp, sp find: cmp dx, 0 jz noexist mov di, bx mov cx, [bp] call MemCmp cmp cx, 0 jz exist add bx, 32 dec dx jmp find exist: noexist: pop cx pop bp pop di ret ; ds:si --> source ; es:di --> destination ; cx --> length ; ; return : ; (cx == 0) ? equal : noequal MemCmp: push si push di push ax compare: cmp cx, 0 jz equal mov al, [si] cmp al, byte [di] jz goon jmp noequal goon: inc si inc di dec cx jmp compare equal: noequal: pop ax pop di pop si ret ; es:bp --> string address ; cx --> string length Print: mov ax, 0x1301 mov bx, 0x0007 int 0x10 ret ; no parameter ResetFloppy: push ax push dx mov ah, 0x00 mov dl, [BS_DrvNum] int 0x13 pop dx pop ax ret ; ax --> logic sector number ; cx --> number of sector ; es:bx --> target address ReadSector: push bx push cx push dx push ax call ResetFloppy push bx push cx mov bl, [BPB_SecPerTrk] div bl mov cl, ah add cl, 1 mov ch, al shr ch, 1 mov dh, al and dh, 1 mov dl, [BS_DrvNum] pop ax pop bx mov ah, 0x02 read: int 0x13 jc read pop ax pop dx pop cx pop bx ret MsgStr db "No LOADER ..." MsgLen equ ($-MsgStr) Target db "LOADER " TarLen equ ($-Target) Buf: times 510-($-$$) db 0x00 db 0x55, 0xaa |
如果找不到文件会打印出“No LOADER...”,如果能找到,则不打印任何字符。不打印字符的话却无法证明我们的程序是正确的,我们下面进行断点调试,看一下寄存器内容,首先使用ndisasm -o 0x7c00 boot.bin > boot.txt进行反编译,找到适合的断点。
我们应该在第51行cmp dx, 0处对应的地方打断点,根据boot.txt文件中的内容,我们来确定断点地址,如下:
可以看到,断点地址应该为0x7c61,接下来,启动bochs,进行调试,结果如下:
根据上图可以看出,dx寄存器的值为219,dx为输出寄存器,也就是文件所在的目录项的位置,如果dx为0,说明文件不存在,dx不为0,则说明文件找到了,到此为止,我们查找文件的实验成功了。
总结:
posted on 2020-11-17 13:36 lh03061238 阅读(136) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)