1. 程式人生 > >第7課 - 突破512字節的限制(中)

第7課 - 突破512字節的限制(中)

name 右移 函數 AC 如何 2個 返回值 HR reads

突破限制的預備工作

技術分享圖片技術分享圖片

整體思路

技術分享圖片技術分享圖片

如何在根目錄區中查找目標文件?

通過根目錄項的前11個字節進行判斷

技術分享圖片技術分享圖片

內存比較

指定源起始地址(DS:SI) 指定目標起始地址(ES:DI) 判斷在期望長度(CX)內每一個字節是否相等 技術分享圖片技術分享圖片

匯編小貼士

匯編中的比較與跳轉 比較: cmp cx, 0 ;比較cx的值是否為0,並把結果記錄到標誌寄存器 跳轉: jz equal ; 如果比較為真(根據標誌寄存器的值)就跳轉到equal 技術分享圖片  技術分享圖片 訪問棧空間中的棧頂數據 不能使用sp直接訪問棧頂數據
通過其它通用寄存器間接訪問棧頂數據   技術分享圖片

查找根目錄區是否存在目標文件

技術分享圖片   技術分享圖片

加載根目錄區

技術分享圖片技術分享圖片

小結

可通過查找根目錄區判斷是否存在目標文件 加載根目錄區至內存中(ReadSector) 遍歷根目錄區中的每一項(FindEntry) 通過每一項的前11個字節進行判斷(MemCmp) 當目標不存在時,打印錯誤信息(print

代碼

  boot.asm

  1 org 0x7c00                            ; 從0x7c00處開始存儲代碼
  2  
  3 jmp short start                        ;
BS_JmpBoot;短跳指令,jmp指令占用1字節,地址占用1字節;下面的nop空指令占用1字節;共3字節 4 nop 5 6 define: 7 BaseOfStack equ 0x7c00 ; 定義棧的起始地址,註意棧是從高到低增長的,先加後入棧,先出後減 8 RootEntryOffset equ 19 ; 文件數據從19邏輯扇區開始 9 RootEntryLenght equ 14 ; 目錄文件項共14扇區 10 11 ; ##############################################################################
12 header: 13 BS_OEMName db "D.T.Soft" ; OEM字符,8個,不足以空格填充 14 BPB_BytsPerSec dw 512 ; 每扇區字節數 15 BPB_SecPerClus db 1 ; 每簇占用扇區數 16 BPB_RsvdSecCnt dw 1 ; Boot占用的扇區數 17 BPB_NumFATs db 2 ; FAT表的記錄數 18 BPB_RootEntCnt dw 224 ; 最大根目錄文件數 19 BPB_TotSec16 dw 2880 ; 邏輯扇區總數 20 BPB_Media db 0xF0 ; 媒體描述符 21 BPB_FATSz16 dw 9 ; 每個FAT占用扇區數 22 BPB_SecPerTrk dw 18 ; 每個磁道扇區數 23 BPB_NumHeads dw 2 ; 磁頭數 24 BPB_HiddSec dd 0 ; 隱藏扇區數 25 BPB_TotSec32 dd 0 ; 如果BPB_TotSec16是0,則在這裏記錄扇區總數 26 BS_DrvNum db 0 ; 中斷13的驅動器號 27 BS_Reserved1 db 0 ; 未使用 28 BS_BootSig db 0x29 ; 擴展引導標誌 29 BS_VolID dd 0 ; 卷序列號 30 BS_VolLab db "D.T.OS-0.01"; 卷標,必須11個字符,不足以空格填充 31 BS_FileSysType db "FAT12 " ; 文件系統類型,必須使8個字符,不足填充空格 32 33 ; ############################################################################## 34 start: ; 匯編起始標號,類似於main()函數 35 mov ax, cs ; 設置相關的段寄存器 36 mov ss, ax 37 mov ds, ax 38 mov es, ax 39 mov sp, BaseOfStack ; 設置函數調用棧 40 41 ;mov ax, 59 ; 文件數據起始於59扇區 42 ;mov cx, 1 ; 讀取1個扇區 43 ;mov bx, Buf ; 數據寫入的地址 44 45 ;call ReadSector ; 調用讀扇區函數(數據保存到ES:BX) 46 47 ;mov si, MsgStr 48 ;mov di, DEST 49 ;mov cx, MsgLen 50 mov ax, RootEntryOffset ; 記錄數據起始扇區 51 mov cx, RootEntryLenght ; 記錄數據占用扇區數 52 mov bx, Buf ; 讀取的數據存放處 53 54 call ReadSector ; 讀取指定扇區數據到Buf緩存 55 mov si, Target ; 要查找的文件名 56 mov cx, TarLen ; 文件名長度 57 mov dx, 0        ; 設置默認返回值 58 59 call FindEntry ; 查找文件 60 61 cmp dx, 0 ; 如果沒有找到文件就輸出提示,否則跳到last死循環 62 jz output 63 jmp last 64 65 ;call MemCmp 66 67 ;cmp cx, 0 68 ;jz output 69 ;jmp last 70 71 ;mov bp, Buf ; 字符串段的偏移地址,相對於ES; mov bp, MsgStr ; 輸出Hello, DTOS! 72 ;mov cx, 29 ; 字符串長度 ; mov cx, MsgLen ; Test file for virtual floppy. 73 output: 74 mov bp, MsgStr 75 mov cx, MsgLen 76 call Print ; 調用字符串打印函數 77 78 last: ; 死循環 79 hlt 80 jmp last 81 82 ; ############################################################################## 83 ; es:bx --> root entry offset address 84 ; ds:si --> target string 85 ; cx --> target length 86 ; 87 ; return: 88 ; (dx != 0) ? exist : noexist 89 ; exist --> bx is the target entry 90 FindEntry: ; 查找根目錄文件 91 push di 92 push bp 93 push cx 94 95 mov dx, [BPB_RootEntCnt] ; 最大根目錄文件數 96 mov bp, sp ; 棧地址,不能直接將sp棧頂指針賦值給通用寄存器 97 98 find: 99 cmp dx, 0 ; 如果沒有文件就跳轉到noexist結束 100 jz noexist 101 mov di, bx ; bx==Buf緩存;ReadSector()已經讀取數據到Buf緩存 102 mov cx, [bp] ; 借助中間寄存器獲取棧頂指針,此時的bp棧頂指針指向最後入棧的cx寄存器 103 call MemCmp ; 內存匹配查找(文件查找) 104 cmp cx, 0 ; 如果還有文件就繼續,否則匹配失敗跳轉到exist結束 105 jz exist 106 add bx, 32 ; Buf緩存地址加32,每個目錄項占用32字節 107 dec dx ; dx-1,文件數減1 108 jmp find 109 110 exist: 111 noexist: 112 pop cx 113 pop bp 114 pop di 115 116 ret 117 118 ; ############################################################################## 119 ; ds:si --> source 120 ; es:di --> destination 121 ; cx --> length 122 ; 123 ; return: 124 ; (cx == 0) ? equal : noequeal 125 MemCmp: ; 內存數據對比 126 push si 127 push di 128 push ax 129 130 compare: 131 cmp cx, 0 ; 到末尾(文件名結束符)就跳轉到equal 132 jz equal 133 mov al, [si] ; si源(要查找的文件名) 134 cmp al, byte [di] ; di目標(根目錄區的文件名) 135 jz goon ; 匹配一個字節就跳轉到goon繼續循環判斷 136 jmp noequal ; 不匹配就跳轉到noequal,函數返回以便查找下一個文件 137 goon: 138 inc si ; 源和目標+1遞增 139 inc di 140 dec cx ; 剩余次數-1遞減 141 jmp compare ; 跳轉到compare繼續循環 142 143 equal: 144 noequal: 145 pop ax 146 pop di 147 pop si 148 149 ret 150 151 ; ############################################################################## 152 ; es:bp --> string address 153 ; cx --> string length 154 Print: ; 字符串打印函數 155 mov ax, 0x1301 ; ah=13,在Teletype電傳打字機模式下輸出;al=01,字符串只含字符,啟用BL屬性,改變光標 156 mov bx, 0x0007 ; bh頁碼,bl前景色;bl=07,80×25字符的2色文本 157 int 0x10 ; 打印中斷 158 ret ; 函數返回 159 160 ; ############################################################################## 161 ; no parameter 162 ResetFloppy: ; 重置軟盤段 163 push ax 164 push dx 165 166 mov ah, 0x00 ; 磁盤系統復位 167 mov dl, [BS_DrvNum] ; 驅動器號(0x00~0x7F軟盤,0x80~0x0FF硬盤) 168 int 0x13 ; 讀取磁盤的中斷 169 170 pop dx 171 pop ax 172 173 ret 174 175 ; ax --> logic sector number 176 ; cx --> number of sector 177 ; es:bx --> target address 178 ReadSector: ; 讀扇區段(函數) 179 push bx ; 保存相關寄存器 180 push cx 181 push dx 182 push ax 183 184 call ResetFloppy ; 重置軟盤 185 186 push bx 187 push cx 188 189 mov bl, [BPB_SecPerTrk] ; 每柱面(磁道)扇區數;本段代碼用於計算柱面、磁頭和扇區號以及設置驅動器號 190 div bl ; 除法,被除數在AX(或者DX高位+AX地位),商在AL,余數在AH 191 mov cl, ah ; 余數,cl記錄起始扇區;FAT的扇區從0開始,軟盤的扇區從1開始,所以下面+1 192 add cl, 1 193 mov ch, al ; 商(邏輯柱面或磁道數),ch記錄起始柱面(磁道) 194 shr ch, 1 ; 右移一位表示除以2(當前軟盤只有2個磁頭),因為扇區編號是由兩面的柱面(磁道)組合的,然後再從外往內增大;shr移位大於1時需要借助cl寄存器; 195 mov dh, al ; 商,dh記錄起始磁頭 196 and dh, 1 ; 如果邏輯柱面(磁道)號是偶數就在0磁頭,否則就是1磁頭(目前只有2個磁頭) 197 mov dl, [BS_DrvNum] ; 設置驅動器號 198 199 pop ax ; 還原要讀取的扇區數,相當於原來的cx,因為cx是最後入棧的,這裏是最先出棧 200 pop bx ; bx已設置為指向Buf 201 202 mov ah, 0x02 ; 0x02讀扇區 203 204 read: 205 int 0x13 ; 讀取磁盤的中斷 206 jc read ; 若進位位(CF)被置位,表示調用失敗,需要重新讀取 207 208 pop ax 209 pop dx 210 pop cx 211 pop bx 212 213 ret 214 215 ; ############################################################################## 216 ;MsgStr db "Hello, DTOS!" ; 定義字符串,上面43行註釋使用 217 MsgStr db "No LOADER " ; 定義字符串,上面43行註釋使用 218 MsgLen equ ($-MsgStr) ; 定義上面字符串長度標號 219 ;DEST db "Hello, DTOS!" ; 測試目標文件 220 Target db "LOADER" ; 要查棧的文件名 221 TarLen equ ($-Target) ; 要查找的文件名長度 222 Buf: ; Buf緩存,數據的讀取和寫入空間;下面兩行代碼是為mbr準備的,其它讀寫無用無害 223 times 510-($-$$) db 0x00 224 db 0x55, 0xaa

輸出

找到了文件(LOADER) 技術分享圖片  技術分享圖片

沒有找到文件(LiOADER) 技術分享圖片  技術分享圖片

第7課 - 突破512字節的限制(中)