• 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处

      用于比较的汇编程序片段如下:

    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直接访问,而要经过其他寄存器间接访问,如下:

      有了以上的思路后,我们直接给出查找文件的汇编程序:

    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,则说明文件找到了,到此为止,我们查找文件的实验成功了。

    总结:

      

      

  • 相关阅读:
    Winform+SignalR
    LogBack日志异步推送kafka并规范日志输出格式
    springboot集成微信支付APIv3接口 实现小程序和公众号支付
    服务器mysql的CPU占用超过100%
    nginx: [emerg] the "ssl" parameter requires ngx_http_ssl_module
    seata@GlobalTransactional注解失效
    微信小程序CRC16校验,通过测试,好用
    vue2和vue3项目的初始结构对比
    监控平台前端SDK开发实践
    jQuery LigerUI V1.2.0 (包括API和全部源码) 发布
  • 原文地址:https://www.cnblogs.com/lh03061238/p/13993754.html
Copyright © 2020-2023  润新知