zoukankan      html  css  js  c++  java
  • 第八课 突破512字节的限制--下

      上一节我们进行了文件的查找实验,文件查找成功了,这一节,我们将文件的内容加载进内存,再一次将整体的流程给出如下:

      读取文件的内容时,我们需要根据FAT表找到存储文件内容的每一个扇区,然后进行内容的读取,在上一节中,我们将整个目录区的内容加载到了内存并根据文件名找到了所在的目录项,为了节省内存,我们将找到的目录项拷贝到另一片内存区域中,因为这个目录项中还有我们需要的内容,比如文件的起始扇区号等。而原来加载目录区的那一部分内存便可以另作他用,比如可以将FAT表加载到该区域。

      目标文件的目录信息如下:

      内存拷贝时,为了防止已经拷贝的内容将原来还没有拷贝的内容覆盖,我们需要考虑一下拷贝的方向,示意图如下:

      当源地址小于等于目标地址时,要从后向前拷贝,如上图中左半部,当源地址大于目标地址时,要从头部向尾部拷贝,如上图右半部。

      用到的汇编指令如下所示:

      

      下面直接给出内存拷贝的汇编代码:

      1 org 0x7c00
      2 
      3 jmp short start
      4 nop
      5 
      6 define:
      7     BaseOfStack      equ 0x7c00
      8     BaseOfLoader     equ 0x9000
      9     RootEntryOffset  equ 19
     10     RootEntryLength  equ 14
     11     EntryItemLength  equ 32
     12     FatEntryOffset   equ 1
     13     FatEntryLength   equ 9
     14 
     15 header:
     16     BS_OEMName     db "D.T.Soft"
     17     BPB_BytsPerSec dw 512
     18     BPB_SecPerClus db 1
     19     BPB_RsvdSecCnt dw 1
     20     BPB_NumFATs    db 2
     21     BPB_RootEntCnt dw 224
     22     BPB_TotSec16   dw 2880
     23     BPB_Media      db 0xF0
     24     BPB_FATSz16    dw 9
     25     BPB_SecPerTrk  dw 18
     26     BPB_NumHeads   dw 2
     27     BPB_HiddSec    dd 0
     28     BPB_TotSec32   dd 0
     29     BS_DrvNum      db 0
     30     BS_Reserved1   db 0
     31     BS_BootSig     db 0x29
     32     BS_VolID       dd 0
     33     BS_VolLab      db "D.T.OS-0.01"
     34     BS_FileSysType db "FAT12   "
     35 
     36 start:
     37     mov ax, cs
     38     mov ss, ax
     39     mov ds, ax
     40     mov es, ax
     41     mov sp, BaseOfStack
     42     
     43     mov ax, RootEntryOffset
     44     mov cx, RootEntryLength
     45     mov bx, Buf
     46     
     47     call ReadSector
     48     
     49     mov si, Target
     50     mov cx, TarLen
     51     mov dx, 0
     52     
     53     call FindEntry
     54     
     55 ;    cmp dx, 0
     56 ;    jz output
     57     
     58     mov si, Target
     59     mov di, MsgStr
     60     mov cx, TarLen
     61     
     62     call MemCpy
     63     
     64 
     65 output:    
     66     mov bp, MsgStr
     67     mov cx, MsgLen
     68     call Print
     69     
     70 last:
     71     hlt
     72     jmp last    
     73 
     74 
     75 ; ds:si --> source
     76 ; es:di --> destination
     77 ; cx    --> length
     78 MemCpy:
     79     push si
     80     push di
     81     push cx
     82     push ax
     83     
     84     cmp si, di
     85     
     86     ja btoe
     87     
     88     add si, cx
     89     add di, cx
     90     dec si
     91     dec di
     92     
     93     jmp etob
     94     
     95 btoe:
     96     cmp cx, 0
     97     jz done
     98     mov al, [si]
     99     mov byte [di], al
    100     inc si
    101     inc di
    102     dec cx
    103     jmp btoe
    104     
    105 etob: 
    106     cmp cx, 0
    107     jz done
    108     mov al, [si]
    109     mov byte [di], al
    110     dec si
    111     dec di
    112     dec cx
    113     jmp etob
    114 
    115 done:   
    116     pop ax
    117     pop cx
    118     pop di
    119     pop si
    120     ret
    121 
    122 ; es:bx --> root entry offset address
    123 ; ds:si --> target string
    124 ; cx    --> target length
    125 ;
    126 ; return:
    127 ;     (dx !=0 ) ? exist : noexist
    128 ;        exist --> bx is the target entry
    129 FindEntry:
    130     push di
    131     push bp
    132     push cx
    133     
    134     mov dx, [BPB_RootEntCnt]
    135     mov bp, sp
    136     
    137 find:
    138     cmp dx, 0
    139     jz noexist
    140     mov di, bx
    141     mov cx, [bp]
    142     call MemCmp
    143     cmp cx, 0
    144     jz exist
    145     add bx, 32
    146     dec dx
    147     jmp find
    148 
    149 exist:
    150 noexist: 
    151     pop cx
    152     pop bp
    153     pop di
    154        
    155     ret
    156 
    157 ; ds:si --> source
    158 ; es:di --> destination
    159 ; cx    --> length
    160 ;
    161 ; return:
    162 ;        (cx == 0) ? equal : noequal
    163 MemCmp:
    164     push si
    165     push di
    166     push ax
    167     
    168 compare:
    169     cmp cx, 0
    170     jz equal
    171     mov al, [si]
    172     cmp al, byte [di]
    173     jz goon
    174     jmp noequal
    175 goon:
    176     inc si
    177     inc di
    178     dec cx
    179     jmp compare
    180     
    181 equal: 
    182 noequal:   
    183     pop ax
    184     pop di
    185     pop si
    186     
    187     ret
    188 
    189 ; es:bp --> string address
    190 ; cx    --> string length
    191 Print:
    192     mov dx, 0
    193     mov ax, 0x1301
    194     mov bx, 0x0007
    195     int 0x10
    196     ret
    197 
    198 ; no parameter
    199 ResetFloppy:
    200     push ax
    201     push dx
    202     
    203     mov ah, 0x00
    204     mov dl, [BS_DrvNum]
    205     int 0x13
    206     
    207     pop dx
    208     pop ax
    209     
    210     ret
    211 
    212 ; ax    --> logic sector number
    213 ; cx    --> number of sector
    214 ; es:bx --> target address
    215 ReadSector:
    216     push bx
    217     push cx
    218     push dx
    219     push ax
    220     
    221     call ResetFloppy
    222     
    223     push bx
    224     push cx
    225     
    226     mov bl, [BPB_SecPerTrk]
    227     div bl
    228     mov cl, ah
    229     add cl, 1
    230     mov ch, al
    231     shr ch, 1
    232     mov dh, al
    233     and dh, 1
    234     mov dl, [BS_DrvNum]
    235     
    236     pop ax
    237     pop bx
    238     
    239     mov ah, 0x02
    240 
    241 read:    
    242     int 0x13
    243     jc read
    244     
    245     pop ax
    246     pop dx
    247     pop cx
    248     pop bx
    249     
    250     ret
    251 
    252 MsgStr db  "No LOADER ..."    
    253 MsgLen equ ($-MsgStr)
    254 Target db  "LOADER     "
    255 TarLen equ ($-Target)
    256 EntryItem times EntryItemLength db 0x00
    257 Buf:
    258     times 510-($-$$) db 0x00
    259     db 0x55, 0xaa

      以上程序将Target处的字符串拷贝到了MsgStr处,然后将MsgStr处的内容打印出来,结果如下:

      下一步,我们进行FAT表项的读取,并根据表项的内容加载文件数据,FAT表项中每个表项占用1.5个字节,即使用3个字节表示两个表项,如下图所示:

      以前读取a.img的实验中,我们是将FAT表项完全读取后做了一次转换,生成了一个向量,向量中的每一项占用2个字节,那是一次性将所有FAT表项转换好的,而在我们的汇编程序中,我们使用动态组装的方法,即每用到一个表项就进行临时组装,组装后的FAT表项的下标和起始字节的关系图如下:

      

      组装时用到的关系式如下所示:

      需要用到的乘法汇编指令如下:

       

      我们先打开之前写的读取a.img的Qt程序,添加一行,如下所示:

     

      我们新添加了224行,将数据所在的扇区号分别打印出来,运行程序,得到如下结果:

      上图中只打印出了4,说明数据只存在第4扇区,也就是222行的循环只循环了一次,第二次循环是vec[j]已经不再小于0xFF7,也就是FAT表项不再是一个有效项,而是一个结束项。

      下面给出汇编程序:

      1 org 0x7c00
      2 
      3 jmp short start
      4 nop
      5 
      6 define:
      7     BaseOfStack      equ 0x7c00
      8     BaseOfLoader     equ 0x9000
      9     RootEntryOffset  equ 19
     10     RootEntryLength  equ 14
     11     EntryItemLength  equ 32
     12     FatEntryOffset   equ 1
     13     FatEntryLength   equ 9
     14 
     15 header:
     16     BS_OEMName     db "D.T.Soft"
     17     BPB_BytsPerSec dw 512
     18     BPB_SecPerClus db 1
     19     BPB_RsvdSecCnt dw 1
     20     BPB_NumFATs    db 2
     21     BPB_RootEntCnt dw 224
     22     BPB_TotSec16   dw 2880
     23     BPB_Media      db 0xF0
     24     BPB_FATSz16    dw 9
     25     BPB_SecPerTrk  dw 18
     26     BPB_NumHeads   dw 2
     27     BPB_HiddSec    dd 0
     28     BPB_TotSec32   dd 0
     29     BS_DrvNum      db 0
     30     BS_Reserved1   db 0
     31     BS_BootSig     db 0x29
     32     BS_VolID       dd 0
     33     BS_VolLab      db "D.T.OS-0.01"
     34     BS_FileSysType db "FAT12   "
     35 
     36 start:
     37     mov ax, cs
     38     mov ss, ax
     39     mov ds, ax
     40     mov es, ax
     41     mov sp, BaseOfStack
     42     
     43     mov ax, RootEntryOffset
     44     mov cx, RootEntryLength
     45     mov bx, Buf
     46     
     47     call ReadSector
     48     
     49     mov si, Target
     50     mov cx, TarLen
     51     mov dx, 0
     52     
     53     call FindEntry
     54     
     55     cmp dx, 0
     56     jz output
     57     
     58     mov si, bx
     59     mov di, EntryItem
     60     mov cx, EntryItemLength
     61     
     62     call MemCpy
     63     
     64     mov ax, FatEntryLength      ; FAT zhan yong 9 ge Sector
     65     mov cx, [BPB_BytsPerSec]    ; mei ge Sector de da xiao
     66     mul cx                      ; xiang cheng hou de dao FAT biao de zong zi jie da xiao,cun                                     ; zai ax zhong
     67     mov bx, BaseOfLoader        ; jia zai FAT biao de qi shi di zhi
     68     sub bx, ax
     69     
     70     mov ax, FatEntryOffset
     71     mov cx, FatEntryLength
     72     
     73     call ReadSector
     74     
     75     mov cx, [EntryItem + 0x1A]  ;huo qu qi shi cu hao
     76     
     77     call FatVec
     78     
     79     jmp last
     80     
     81 output:    
     82     mov bp, MsgStr
     83     mov cx, MsgLen
     84     call Print
     85     
     86 last:
     87     hlt
     88     jmp last    
     89 
     90 
     91 ; cx --> index
     92 ; bx --> fat table address
     93 ;
     94 ; return:
     95 ;     dx --> fat[index]
     96 FatVec:
     97     mov ax, cx
     98     mov cl, 2
     99     div cl
    100     
    101     push ax
    102     
    103     mov ah, 0
    104     mov cx, 3
    105     mul cx
    106     mov cx, ax
    107     
    108     pop ax
    109     
    110     cmp ah, 0
    111     jz even
    112     jmp odd
    113 
    114 even:    ; FatVec[j] = ( (Fat[i+1] & 0x0F) << 8 ) | Fat[i];
    115     mov dx, cx
    116     add dx, 1
    117     add dx, bx
    118     mov bp, dx
    119     mov dl, byte [bp]
    120     and dl, 0x0F
    121     shl dx, 8
    122     add cx, bx
    123     mov bp, cx
    124     or  dl, byte [bp]
    125     jmp return
    126     
    127 odd:     ; FatVec[j+1] = (Fat[i+2] << 4) | ( (Fat[i+1] >> 4) & 0x0F );
    128     mov dx, cx
    129     add dx, 2
    130     add dx, bx
    131     mov bp, dx
    132     mov dl, byte [bp]
    133     mov dh, 0
    134     shl dx, 4
    135     add cx, 1
    136     add cx, bx
    137     mov bp, cx
    138     mov cl, byte [bp]
    139     shr cl, 4
    140     and cl, 0x0F
    141     mov ch, 0
    142     or  dx, cx
    143 
    144 return: 
    145     ret
    146 
    147 ; ds:si --> source
    148 ; es:di --> destination
    149 ; cx    --> length
    150 MemCpy:
    151     push si
    152     push di
    153     push cx
    154     push ax
    155     
    156     cmp si, di
    157     
    158     ja btoe
    159     
    160     add si, cx
    161     add di, cx
    162     dec si
    163     dec di
    164     
    165     jmp etob
    166     
    167 btoe:
    168     cmp cx, 0
    169     jz done
    170     mov al, [si]
    171     mov byte [di], al
    172     inc si
    173     inc di
    174     dec cx
    175     jmp btoe
    176     
    177 etob: 
    178     cmp cx, 0
    179     jz done
    180     mov al, [si]
    181     mov byte [di], al
    182     dec si
    183     dec di
    184     dec cx
    185     jmp etob
    186 
    187 done:   
    188     pop ax
    189     pop cx
    190     pop di
    191     pop si
    192     ret
    193 
    194 ; es:bx --> root entry offset address
    195 ; ds:si --> target string
    196 ; cx    --> target length
    197 ;
    198 ; return:
    199 ;     (dx !=0 ) ? exist : noexist
    200 ;        exist --> bx is the target entry
    201 FindEntry:
    202     push di
    203     push bp
    204     push cx
    205     
    206     mov dx, [BPB_RootEntCnt]
    207     mov bp, sp
    208     
    209 find:
    210     cmp dx, 0
    211     jz noexist
    212     mov di, bx
    213     mov cx, [bp]
    214     call MemCmp
    215     cmp cx, 0
    216     jz exist
    217     add bx, 32
    218     dec dx
    219     jmp find
    220 
    221 exist:
    222 noexist: 
    223     pop cx
    224     pop bp
    225     pop di
    226        
    227     ret
    228 
    229 ; ds:si --> source
    230 ; es:di --> destination
    231 ; cx    --> length
    232 ;
    233 ; return:
    234 ;        (cx == 0) ? equal : noequal
    235 MemCmp:
    236     push si
    237     push di
    238     push ax
    239     
    240 compare:
    241     cmp cx, 0
    242     jz equal
    243     mov al, [si]
    244     cmp al, byte [di]
    245     jz goon
    246     jmp noequal
    247 goon:
    248     inc si
    249     inc di
    250     dec cx
    251     jmp compare
    252     
    253 equal: 
    254 noequal:   
    255     pop ax
    256     pop di
    257     pop si
    258     
    259     ret
    260 
    261 ; es:bp --> string address
    262 ; cx    --> string length
    263 Print:
    264     mov dx, 0
    265     mov ax, 0x1301
    266     mov bx, 0x0007
    267     int 0x10
    268     ret
    269 
    270 ; no parameter
    271 ResetFloppy:
    272     push ax
    273     push dx
    274     
    275     mov ah, 0x00
    276     mov dl, [BS_DrvNum]
    277     int 0x13
    278     
    279     pop dx
    280     pop ax
    281     
    282     ret
    283 
    284 ; ax    --> logic sector number
    285 ; cx    --> number of sector
    286 ; es:bx --> target address
    287 ReadSector:
    288     push bx
    289     push cx
    290     push dx
    291     push ax
    292     
    293     call ResetFloppy
    294     
    295     push bx
    296     push cx
    297     
    298     mov bl, [BPB_SecPerTrk]
    299     div bl
    300     mov cl, ah
    301     add cl, 1
    302     mov ch, al
    303     shr ch, 1
    304     mov dh, al
    305     and dh, 1
    306     mov dl, [BS_DrvNum]
    307     
    308     pop ax
    309     pop bx
    310     
    311     mov ah, 0x02
    312 
    313 read:    
    314     int 0x13
    315     jc read
    316     
    317     pop ax
    318     pop dx
    319     pop cx
    320     pop bx
    321     
    322     ret
    323 
    324 MsgStr db  "No LOADER ..."    
    325 MsgLen equ ($-MsgStr)
    326 Target db  "START      "
    327 TarLen equ ($-Target)
    328 EntryItem times EntryItemLength db 0x00
    329 Buf:
    330     times 510-($-$$) db 0x00
    331     db 0x55, 0xaa

      运行bochs,在程序的第77,79行打断点(具体方法见上节反汇编ndisasm使用方法),然后运行到第一个断点处,打印寄存器内容如下:

      可以看到ecx中的后两个字节(bochs为16字节操作)确实为4,这就是文件数据起始扇区号,edx此时还为0,继续运行到下一个断点处,打印寄存器如下:

      寄存器edx的内容为0xfff,这就是FAT表项中的内容,说明文件结束了,文件的内容只存在了一个扇区中。本节中的FatVec函数并没有完善,本节还没有进行文件内容的读取,只是根据文件数据起始扇区号,读取了下一个FAT表项的内容,下一节继续。。。

     

    参考狄泰软件学院操作系统教程   

  • 相关阅读:
    我对IOC控制反转,依赖注入原理的理解
    .net带事件的对象BinaryFormatter 序列化失败
    (维权成功,链接已经被删除了)如何防止自己的原创文章被垃圾站IT165采集和盗用
    浅谈.net多线程机制
    给现下流行的打车软件的一点小建议
    C#应用MemoryStream提高File读取速度
    微软真的要抛弃Silverlight了吗?
    C# File.Copy 实现磁盘间文件备份
    遮罩層 日曆效果
    GridView導出Excel
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9245070.html
Copyright © 2011-2022 走看看