;%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