zoukankan      html  css  js  c++  java
  • 06 突破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

    及狄泰软件相关课程

    前几节我们介绍了FAT12文件系统,制作了虚拟软盘文件a.img,并在Qt Creater中进行了文件内容的读取实验。那些读取都是使用外部的程序实现的,实际应用中,我们需要用主引导程序来实现文件的读写,主引导程序存在于主引导扇区MBR中,也就是说程序和文件是存在一张盘上的,而且这些主引导程序需要使用汇编语言实现。接下来,我们就来实现具有读取功能的主引导程序。

      为了验证文件读取的正确性,我们需要在主引导程序中先实现一个字符串打印函数。BIOS已经将中断向量写到了内存的指定位置处,这其中就有能实现字符串打印的函数,我们需要做的就是配置一些参数,需要配置的参数和配置步骤如下:

      1、指定打印参数(AX=0x1301 , BX = 0x0007)

      2、指定字符串的内存地址(ES:BP  = 字符串地址)

      3、指定字符串的长度(CX = 字符串长度)

      4、中断调用(int 0x10)

    示例如下:

      需要用到的汇编语言的知识点如下:

                                    

      下面直接给出打印字符串的汇编程序:

    org 0x7c00
    
    jmp short start
    nop
    
    define:
        BaseOfStack equ 0x7c00
    
    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, MsgStr
           mov bp, ax
    
           mov ax, ds
           mov es, ax
    
           mov cx, 6
        call Print
    
    last:
        hlt
        jmp last
    
    ; es:bp --> string address
    ; cx    --> string length
    Print:
        mov ax, 0x1301
        mov bx, 0x0007
        int 0x10
        ret
    
    MsgStr db  "Hello, DTOS!"
    MsgLen equ ($-MsgStr)
    Buf:
        times 510-($-$$) db 0x00
        db 0x55, 0xaa
    

    我们的虚拟软盘文件a.img已经格式化好了,现在要修改的只是第一个扇区即主引导扇区,所以我们要按照FAT12的格式来填充第一个扇区,因此,上面的程序中,第10到28行是FAT12的引导扇区的信息,它前面还有三个字节,其中前两个字节是跳转指令jmp short start,第三个字节为空指令nop。从start开始是我们的可执行程序,BaseOfStack是定义的栈底地址。

      汇编程序我们需要编译成二进制可执行程序,然后写入a.img虚拟软盘的第一个扇区中,每次都执行这个过程很麻烦,我们将这个过程写成makefile,如下所示:

    .PHONY : all clean rebuild
    
    SRC := boot.asm
    OUT := boot.bin
    IMG := a.img
    
    RM := rm -fr
    
    all : $(OUT) $(IMG)
        dd if=$(OUT) of=$(IMG) bs=512 count=1 conv=notrunc
        @echo "Success!"
    
    $(IMG) :
        bximage $@ -q -fd -size=1.44
    
    $(OUT) : $(SRC)
        nasm $^ -o $@
    
    clean :
        $(RM) $(IMG) $(OUT)
    
    rebuild :
        @$(MAKE) clean
        @$(MAKE) all
    

    bochs的启动文件修改成如下内容:

    ###############################################################
    # Configuration file for Bochs
    ###############################################################
    
    # how much memory the emulated machine will have
    megs: 32
    
    # filename of ROM images
    romimage: file=/usr/share/bochs/BIOS-bochs-latest
    vgaromimage: file=/usr/share/vgabios/vgabios.bin
    
    # what disk images will be used
    floppya: 1_44=a.img, status=inserted
    # choose the boot disk.
    boot: a
    
    # where do we send log messages?
    # log: bochsout.txt
    
    # disable the mouse
    mouse: enabled=0
    
    # enable key mapping, using US layout as default.
    keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map
    

    启动bochs,即可得到运行结果,如下所示:

      可见,hello已经成功打印出来了。

       接下来,我们开始读取文件,假如我们知道了数据所在的扇区,那么怎么将它读出来呢?先来看一下软盘的构造,如下所示:

      3.5寸软盘的特性如下:

      根据逻辑扇区号计算磁头号、柱面号、物理扇区号的方法如下:

      软盘复位和软驱数据读取的参数如下:

      整体的读取流程如下:

      需要用到的汇编知识点如下:

      

     下面直接给出汇编程序:

    org 0x7c00
    
    jmp short start
    nop
    
    define:
        BaseOfStack equ 0x7c00
    
    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, 34
        mov cx, 1
        mov bx, Buf
        
        call ReadSector
        
        mov bp, Buf
        mov cx, 29
        
        call Print
        
    last:
        hlt
        jmp last    
    
    ; 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, DTOS!"    
    MsgLen equ ($-MsgStr)
    Buf:
        times 510-($-$$) db 0x00
        db 0x55, 0xaa
    

      

    我们将虚拟软盘文件a.img用VS2013打开,查看其中的内容,截取片段如下:

      可以看到,a.txt文件的起始地址为0x4400,也就是第34个扇区开始,而内容的大小为24字节,这两个参数分别体现在汇编程序中的第37和44行。下面,启动bochs,运行结果如下:

    打印出了this is a floppy file.,我们成功读取了指定扇区的数据。

          若有问题,可以使用bochs环境进行汇编代码调试,具体通过反汇编,结合运行地址和断点调试来进行,可以观察指令执行情况

    及相关寄存器的值,可参考本节相关教程。

    小结
    1.当汇编代码中定义了函数,那么需要定义栈空间
    2.读取数据前,逻辑扇区号需要转化为磁盘的物理位置
    3.物理软盘上的数据位置由磁头号,柱面号,扇区唯一确定
    4.软盘数据以扇区512为单位进行读取

      

      

      

      

  • 相关阅读:
    函数
    vue中v-for循环如何将变量带入class的属性名中
    代码规范 前端导航
    2019.8.5 mysql 删除 更新
    2019.8.1
    2019.7.31 Xshell简单学习
    日常使用知识点
    FormData实现文件多次添加累加上传和选择删除
    上传图片
    验证码
  • 原文地址:https://www.cnblogs.com/lh03061238/p/13967949.html
Copyright © 2011-2022 走看看