2010年02月28日

;%define _BOOT_DEBUG_
%ifdef _BOOT_DEBUG
 org 0100h
%else
   org 07c00h
%endif
;==================================================================
%ifdef _BOOT_DEBUG_
BaseOfStack equ 0100h ;調試狀態下堆棧基地址(棧底,從這個位置向低地址生長0
%else 
BaseOfStack equ 07c00h ;堆棧基地址
%endif

BaseOfLoader  equ 09000h ;Loader.bin被加載到的段地址
OffsetOfLoader  equ 0100h ;Loader.bin被加載到的偏移地址
RootDirSectors  equ 14 ;根目錄佔用空間
SectorNoOfRootDirectory equ 19 ;RootDirectory的第一個扇區號
SectorNoOfFAT1  equ 1 ;FAT的第一個扇區號 = BPB_RsvSecCnt
DeltaSectorNo  equ 17
 jmp short LABEL_START
 nop ;nop不能少,估計要初始化下面的BPB磁頭
;下面是FAT12磁頭
 BS_OEMName DB 'LZYSTART' ; OEM String, 必須 8 個字節
 BPB_BytsPerSec DW 512  ; 每扇區字節數
 BPB_SecPerClus DB 1  ; 每簇多少扇區
 BPB_RsvdSecCnt DW 1  ; Boot 記錄佔用多少扇區
 BPB_NumFATs DB 2  ; 共有多少 FAT 表
 BPB_RootEntCnt DW 224  ; 根目錄文件數最大值
 BPB_TotSec16 DW 2880  ; 邏輯扇區總數
 BPB_Media DB 0xF0  ; 媒體描述符
 BPB_FATSz16 DW 9  ; 每FAT扇區數
 BPB_SecPerTrk DW 18  ; 每磁道扇區數
 BPB_NumHeads DW 2  ; 磁頭數(面數)
 BPB_HiddSec DD 0  ; 隱藏扇區數
 BPB_TotSec32 DD 0  ; 如果 wTotalSectorCount 是 0 由這個值記錄扇區數
 BS_DrvNum DB 0  ; 中斷 13 的驅動器號
 BS_Reserved1 DB 0  ; 未使用
 BS_BootSig DB 29h  ; 擴展引導標記 (29h)
 BS_VolID DD 0  ; 卷序列號
 BS_VolLab DB 'OrangeS0.02'; 卷標, 必須 11 個字節
 BS_FileSysType DB 'FAT12   ' ; 文件系統類型, 必須 8個字節 

LABEL_START:  mov ax,cx
   mov ds,ax
   mov es,ax
   mov ss,ax
   mov sp,BaseOfStack
   ;清屏
   mov ax,0600h
   mov bx,0700h
   mov cx,0
   mov dx,0184fh
   int 10h

   mov dh,0
   call DispStr

   xor ah,ah ;軟驅
   xor dl,dl ;復
   int 13h  ;位
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;下面在A盤的根目錄尋找LOADER.BIN
   
 mov word [wSectorNo],SectorNoOfRootDirectory
LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
 cmp word [wRootDirSizeForLoop],0 ;判斷根目錄區是不是已經讀完
 jz LABEL_NO_LOADERBIN
 dec word [wRootDirSizeForLoop]
 mov ax,BaseOfLoader
 mov es,ax    ;es <- BaseOfLoader
 mov bx,OffsetOfLoader  ;bx <- OffsetOfLoader
 mov ax,[wSectorNo]   ;ax <-Root Directory 中的某Sector號
 mov cl,1
 call ReadSector

 mov si,LoaderFileName  ;ds:si ->"LOADER  BIN"
 mov di,OffsetOfLoader  ;es:do ->BaseOfLoader : 0100
 cld
 mov dx,10h    ;每扇區有16個條目,每條目有32個字節
LABEL_SEARCH_FOR_LOADERBIN:
 cmp dx,0
 jz LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR
 dec dx
 mov cx,11
LABEL_CMP_FILENAME:
 cmp cx,0
 jz LABEL_FILENAME_FOUND
 dec cx
 lodsb
 cmp al,byte [es:di]
 jz LABEL_GO_ON
 jmp LABEL_DIFFERENT
LABEL_GO_ON:
 inc di
 jmp LABEL_CMP_FILENAME
LABEL_DIFFERENT:
 and di,0FFE0H ;讓di指向條目開頭,即32的倍數
 add di,20h  ;指向下一個條目
 mov si,LoaderFileName
 jmp LABEL_SEARCH_FOR_LOADERBIN

LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
 add word [wSectorNo],1
 jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN

LABEL_NO_LOADERBIN:
 mov dh,2  ;"No Loader."
 call DispStr  ;顯示字符串
%ifdef _BOOT_DEBUG_
 mov ax,4c00h
 int 21h
%else 
 jmp $
%endif
LABEL_FILENAME_FOUND:
 mov ax,RootDirSectors
 and di,0ffe0h
 add di,01Ah ;di->首Sector,即每條目的第26位後的一個字節寫的是fat號
 mov cx,word [es:di]
 push cx
 add cx,ax
 add cx,DeltaSectorNo
 mov ax,BaseOfLoader
 mov es,ax
 mov bx,OffsetOfLoader
 mov ax,cx
LABEL_GOON_LOADING_FILE:
 push ax
 push bx
 mov ah,0Eh
 mov al,'.'
 mov bl,0Fh
 int 10h
 pop bx
 pop ax

 mov cl,1
 call ReadSector
 pop ax
 call GetFATEntry
 cmp ax,0fffh
 jz LABEL_FILE_LOADED
 push ax
 mov dx,RootDirSectors
 add ax,dx
 add ax,DeltaSectorNo
 add bx,[BPB_BytsPerSec]
 jmp LABEL_GOON_LOADING_FILE
LABEL_FILE_LOADED:
 mov dh,1
 call DispStr
 jmp BaseOfLoader:OffsetOfLoader

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..
;變量
wRootDirSizeForLoop dw RootDirSectors ;Root Directory佔用的扇區數
      ;在循環中會遞減至0
wSectorNo  dw 0  ;要讀取的扇區號
bOdd   db 0  ;奇數還是偶數

;字符串
LoaderFileName  db "LOADER  BIN",0 ;Loader.bin文件名
MessageLength  equ 9
BootMessage:  db "Booting  "
Message1  db "Ready.   "
Message2  db "NO LOADER"
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;顯示字符串,函數開始時dh中應該是字符串序號(0-based)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  DispStr:
       mov ax,MessageLength
      mul dh
      add ax,BootMessage
       mov bp,ax
       mov ax,ds
      mov es,ax
       mov cx,MessageLength
      mov ax,01301h
       mov bx,0007h
       mov dl,0
       int 10h
       ret
 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.
;函數名:ReadSector ,從第ax個Sector開始,將cl個Sector讀入 es:bx中
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ReadSector:
 push bp
 mov bp,sp
 sub esp,2
 mov byte [bp-2],cl
 push bx
 mov bl,[BPB_SecPerTrk]
 div bl
 inc ah ;z++ 爲起始扇區號
 mov cl,ah ;cl <-起始扇區號
 mov dh,al ;dh<-y
 shr al,1 ;y>>1
 mov ch,al ;ch<-柱面號
 and dh,1 ;磁頭號
 pop bx
 ;所需信息全部得到
 mov dl,[BS_DrvNum] ;驅動器號
.GoOnReading:
 mov ah,2 ;讀
 mov al,byte [bp-2] ;讀al個扇區數
 int 13h
 jc .GoOnReading ;如果讀取錯誤CF被置爲1

 add esp,2
 pop bp

 ret
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;函數名: GetFATEntry
; 功能:找到序號爲ax的Sector在FAT中的條目並保存到ax中
; 由於讀FAT的扇區要用到es,bx,所以保存了es,bx
GetFATEntry:
 push es
 push bx
 push ax
 mov ax,BaseOfLoader
 sub ax,0100h ;在BaseOfLoader後面留出4k空間用於存放FAT
 mov es,ax
 pop ax
 mov byte [bOdd],0
 mov bx,3
 mul bx
 mov bx,2
 div bx
 cmp dx,0
 jz LABEL_EVEN
 mov byte [bOdd],1
LABEL_EVEN: ;偶數
 xor dx,dx
 mov bx,[BPB_BytsPerSec]
 div bx
 push dx
 mov bx,0
 add ax,SectorNoOfFAT1
 mov cl,2
 call ReadSector
 pop dx
 add bx,dx
 mov ax,[es:bx]
 cmp byte [bOdd],1
 jnz LABEL_EVEN_2
 shr ax,4
LABEL_EVEN_2:
 and ax,0fffh
LABEL_GET_FAT_ENRY_OK:
 pop bx
 pop es
 ret
   times 510 - ($-$$) db 0
   dw 0xaa55

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章