;2011.10.20 ;FAT32 Boot Sector ;by trojancyborg ;分區(qū)引導(dǎo)扇區(qū)結(jié)構(gòu) ;+0 3 byte jmp ;+3 87 byte 分區(qū)信息 ;+90 420 byte 引導(dǎo)代碼數(shù)據(jù) ;+510 2 byte 結(jié)束標(biāo)記 ;默認(rèn)一個(gè)簇為4K的情況 ;在獲取指定簇內(nèi)容的時(shí)候,存放簇的緩沖區(qū)位置 Buffer_Cluster_Sector_Base equ 0x8100 ;獲取文件起始簇的時(shí)候,存放目錄項(xiàng)的緩沖區(qū) Buffer_Dir_Base equ 0x8100+0x1000 Buffer_Save_DAP_Base equ 0x8100+0x1000+0x1000 Loader_Base equ Sectors_5_Base Sectors_1_Base equ 0x7c00 Sectors_2_Base equ 0x7e00 Sectors_3_Base equ 0x8100 Sectors_4_Base equ 0x8300 Sectors_5_Base equ 0x8500 fact equ 4 ;fat32目錄項(xiàng)長(zhǎng)度 [BITS 16] ;內(nèi)存 0x7c00 扇區(qū)1 org 7c00h jmp BootEntry ;byte BS_jmpBoot[3]; //跳轉(zhuǎn)指令 ;OFFSET +3 BS_OEMName times 8 db 0 ; //廠商名 ;///////// BIOS Parameter Blocks ///////////// BPB_BytePerSec dw 0; //每扇區(qū)字節(jié)數(shù) BPB_SecPerClus db 0; //每簇扇區(qū)數(shù) BPB_RsvdSecCnt dw 0; //Boot記錄占用扇區(qū) BPB_NumFATs db 0; //FAT表個(gè)數(shù) BPB_RootEntCnt dw 0; //根目錄文件數(shù)最大值 BPB_TotSec16 dw 0; //扇區(qū)總數(shù) BPB_Media db 0; //介質(zhì)描述符 BPB_FATSz16 dw 0; //每FAT扇區(qū)數(shù) BPB_SecPerTrk dw 0; //每磁道扇區(qū)數(shù) BPB_NumHeads dw 0; //磁頭數(shù) BPB_HiddSec dd 0; //隱藏扇區(qū)數(shù) BPB_TotSec32 dd 0 ; ;//////////////////////////////////////////////// ;//下面是FAT32的結(jié)構(gòu) BPB_FATSz32 dd 0; //一個(gè)FAT表占扇區(qū)數(shù) BPB_Flags dw 0; BPB_FSVer dw 0; //高位主板本號(hào) 低位此版本號(hào) BPB_RootClu dd 0; //根目錄的起始簇 BPB_FSInfo dw 0; //FSINFO結(jié)構(gòu)占用扇區(qū)數(shù) BPB_BkBootSec dw 0; //保留區(qū)中引導(dǎo)記錄的備份數(shù)據(jù)所占扇區(qū)數(shù) BPB_Reserved1 times 12 db 0; BS_DrvNum db 0; //終端13的驅(qū)動(dòng)號(hào) BS_Reserved1 db 0; BS_BootSig db 0; //擴(kuò)展引導(dǎo)標(biāo)記 BS_VolID dd 0; //卷序列號(hào) BS_VOlLab times 11 db 0; //卷標(biāo) BS_FileSysType times 8 db 0; //文件類型 ;///////////////////////////////////////////////// ///////////// ;OFFSET +90 ;保留扇區(qū) ;安裝引導(dǎo)程序的時(shí)候,需要將分區(qū)表中該分區(qū)表項(xiàng)最后8字節(jié)復(fù)制到此處 ;其內(nèi)容為改分區(qū)起始扇區(qū),和總扇區(qū)數(shù) ;分區(qū)表中的數(shù)據(jù)拷貝 RelativeSector dd 0;該分區(qū)起始扇區(qū) TotalSector dd 0;分區(qū)總扇區(qū)數(shù) ;OFFSET +90 +8 ;///////////////////////////////////////////////// //////////////////// FirstDataSector dd 0;數(shù)據(jù)區(qū)域起始扇區(qū) FAT_Base dd 0; FAT基表地址 FAT_Size dd 0; FAT表長(zhǎng)度(扇區(qū)總數(shù)) DirRoot_base dd 0; BytePreCluster dd 0; 每簇字節(jié)長(zhǎng)度 ;///////////////////////////////////////////////// //////////////////// ;硬盤(pán)參數(shù)緩沖區(qū) DriverParameters : Info_size dw 26 ;緩沖區(qū)大小標(biāo)志 Flags dw 0 ; 信息標(biāo)志 Cylinders dd 0 ; number of cylinders on disk Heads dd 0 ; number of heads on disk Sec_per_track dd 0 ; number of sectors per track Sectors dq 0 ; number of sectors on requested disk Sector_size dw 0 ; number of bytes per sector ;擴(kuò)展 INT 13H 地址數(shù)據(jù)包 DiskAddressPacket: ; 16Byte PacketSize db 10H ;+0 數(shù)據(jù)包尺寸(16字節(jié)) Reserved db 0 ;+1 這個(gè)一定為0 BlockCount dw 8 ;+2 要傳輸?shù)臄?shù)據(jù)塊個(gè)數(shù)(以扇區(qū)為單位),將后續(xù)保留扇區(qū)全部讀入內(nèi)存 BufferOff dw 0 ;+4 傳輸緩沖地址(segment:offset) BufferSeg dw 0 ;+6 BlockNum dq 64 ;+8 磁盤(pán)起始絕對(duì)塊地址 ;///////////////////////////////////////////////// //////////////////// NotSupportEx13hMsg db "Error,Not Support Ex13h!",0 MsgError db "Load Boot Sector Error!",0 MsgReadSecError db "Read Sector Error",0 LoadFileName db "LOADER ","BIN",0 Load_Loader_Error db "can not find :",0 MsgBoot db "Boot...",0 ;引導(dǎo)代碼開(kāi)始 ;0x7cfa BootEntry : xor ax,ax mov ax,cs mov ds,ax mov ss,ax mov esp,0x7c00 mov byte [BS_DrvNum],80h call CheckInt13H ;檢測(cè)是否支持?jǐn)U展int13h 必須支持才能引導(dǎo) ;加載后續(xù)引導(dǎo)扇區(qū) mov ax,ds mov word [BufferSeg],ax ;緩沖區(qū)段地址 mov Word [BufferOff],7E00h ;將后續(xù)引導(dǎo)扇區(qū)放到此處 mov ah,42h ;讀 mov dl,[BS_DrvNum] ;第一塊硬盤(pán) mov si,DiskAddressPacket ;DAP地址 int 13h jnc LoadSucess push MsgError call DispStr jmp $ LoadSucess : ;加載后續(xù)引導(dǎo)扇區(qū)成功 ;計(jì)算分區(qū)文件系統(tǒng)參數(shù) mov eax,dword [RelativeSector] xor ebx,ebx mov bx,word [BPB_RsvdSecCnt] add eax,ebx mov dword [FAT_Base],eax ;FAT表起始扇區(qū) xor edx,edx xor eax,eax mov al,byte [BPB_NumFATs] mov bx,word [BPB_FATSz32] mul bx mov word [FAT_Size],ax ;FAT表長(zhǎng)度 mov word [FAT_Size+2],dx mov eax,dword [FAT_Base] add eax,dword [FAT_Size] mov dword [FirstDataSector],eax ;數(shù)據(jù)區(qū)起始扇區(qū) xor bx,bx mov ax,word [BPB_BytePerSec] mov bl,byte [BPB_SecPerClus] mul bx mov word [BytePreCluster],ax mov word [BytePreCluster+2],dx ;每簇扇區(qū)數(shù) ;jmp 7e00h ;跳到后續(xù)引導(dǎo)扇區(qū) jmp SecondSector CheckInt13H: ; 檢驗(yàn)擴(kuò)展 13H 功能是否存在 mov ah,0x41 ; 功能號(hào)是 41H mov bx,55aah ; 入口參數(shù)之一 mov dl,[BS_DrvNum] ; 要測(cè)試的 驅(qū)動(dòng)器 80H 是第一塊硬盤(pán) int 13H cmp bx,0xAA55 ; 如果存在擴(kuò)展 13H 功能,則bx==AA55H jnz NotSupport ; 檢測(cè)結(jié)果是不支持,跳到下面顯示不支持的信息。 ret ; 支持?jǐn)U展int 13h ,直接返回 NotSupport: push NotSupportEx13hMsg call DispStr jmp $ ret ;DispStr(char *) ;打印字符串 ;注:由于第一扇區(qū)要調(diào)用,不要將此函數(shù)放后面的扇區(qū)中 DispStr : pusha mov ah,0eh ;顯示字符 xor bx,bx mov bl,02 ;前景色 mov si,[esp+12h] Print_Loop : lodsb ;al中為要顯示的字符 test al,al jz Print_over int 10h jmp Print_Loop Print_over : popa ret 2 ;DispInt(short int) ;以十六進(jìn)制輸出整數(shù) DispInt : pusha mov ax,[esp+12h] mov cx,4 PrintIntLoop : rol ax,4 push ax and ax,0x000F cmp al,10 JAE PrintCh ;大于等于0x0A add al,'0' jmp PrintInt2 PrintCh : add al,'A'-10 PrintInt2 : push ax xor bx,bx mov bl,02h mov ah,0eh int 10h pop ax dec cx test cx,cx pop ax jnz PrintIntLoop popa ret 2 %if (510-($-$$)) < 0 %error 超過(guò)分區(qū)引導(dǎo)代碼容納空間 %else times 510-($-$$) db 0 dw 0xaa55 %endif ;///////////////////////////////////////////////// //////////////////////////////// ;后續(xù)引導(dǎo)扇區(qū) ;內(nèi)存 0x7e00 扇區(qū)2 SecondSector : push Loader_Base ;將loader.bin加載到 0x8500 push LoadFileName call LoadFile ;jmp 0xa000 jmp Loader_Base jmp $ ;MemCpy(char *des,char *src,short int len) ;內(nèi)存復(fù)制函數(shù) MemCpy : pusha mov di,word[ esp+12h] mov si,word[ esp+14h] mov cx,word[ esp+16h] cld rep movsb popa ret 6 ;StrEqu(char *s1,char *s2,short int len) ;字符串是否相等 return 1相等 0不等 StrEqu : pusha mov di,word [esp+12h] mov si,word [esp+14h] mov cx,word [esp+16h] cld lable_cmp_loop : cmpsb jz lable_cmp_loop_next popa mov ax,0 ret 6 lable_cmp_loop_next : sub cx,1 test cx,cx jnz lable_cmp_loop popa mov ax,1 ret 6 ; long FileStartCluster(char *name) ;獲取文件起始簇 FileStartCluster : pusha mov di,word [esp + 12h] ;文件名 mov ecx,Buffer_Dir_Base add ecx,dword [BytePreCluster] ;緩沖區(qū)終止地址 push dword [BPB_RootClu] ;根目錄區(qū)起始簇 Label_ReadDir_next : pop eax ;目錄所在的簇 test eax,eax jz Lable_No_FILE_Return cmp eax,0xFFFFFFF7 jae Lable_No_FILE_Return ;目錄區(qū)是否已經(jīng)讀取完 push eax xor ebx,ebx xor edx,edx sub eax,2 mov bl,byte [BPB_SecPerClus] mul ebx add eax,dword [FirstDataSector] mov word [BlockCount],bx mov word [BufferOff],Buffer_Dir_Base mov dl,[BS_DrvNum] mov dword [BlockNum],eax ;起始?jí)K mov ah,42h ;ah=42h 讀 mov si,DiskAddressPacket ;DAP地址 int 13h jnc ReadDirEntrySucess push MsgReadSecError call DispStr jmp $ ReadDirEntrySucess : ;讀取扇區(qū)成功,則在當(dāng)前扇區(qū)尋找目錄項(xiàng) pusha mov si,Buffer_Dir_Base-0x20 Lable_find_file : add si,0x20 cmp si,cx jz Lable_find_no_file push 11 push si push di call StrEqu test ax,ax jz Lable_find_file mov ax,word [si+0x1a] mov [esp+10h-2],ax popa add esp,4 mov [esp+10h-2],ax popa ret 2 Lable_find_no_file : popa call ClusterContext push eax jmp Label_ReadDir_next ;尋找后面的扇區(qū) Lable_No_FILE_Return : popa mov eax,0 ret 2 ;long ClusterContext(long ClusterNum) ;獲取指定簇號(hào)內(nèi)容 ClusterContext : pusha xor eax,eax mov ax,word [esp +12h] mov dx,word [esp +14h] mov bx,word [BPB_BytePerSec] shr bx,fact/2 div bx ;ax 商(在FAT表中的扇區(qū)) dx 余數(shù) 偏移 shl dx,fact/2 add eax,dword [FAT_Base] push dx ;保存偏移量 xor edx,edx mov dword [BlockNum],eax ;起始?jí)K mov word [BlockCount],1 mov word [BufferOff],Buffer_Cluster_Sector_Base mov ah,42h ;ah=42h 讀 mov dl,[BS_DrvNum] ;dl 第一塊硬盤(pán) mov si,DiskAddressPacket ;DAP地址 int 13h jnc ReadSecSucess push MsgReadSecError call DispStr jmp $ ReadSecSucess : xor edx,edx pop dx mov eax,dword [edx+Buffer_Cluster_Sector_Base] mov word [esp+10h-2],ax popa ret 4 ;LoadFile(char *name,word desbuf) ;讀文件到內(nèi)存 LoadFile : pusha mov si,word [esp +12h] ;取文件名 push si call FileStartCluster test eax,eax jnz Lable_find_loadfile push Load_Loader_Error call DispStr push word [esp +12h] call DispStr jmp $ Lable_find_loadfile : push eax ;文件起始簇 mov di,word [esp +14h+4] mov word [BufferOff],di ;緩沖地址 mov ax,word [BPB_BytePerSec] xor bx,bx mov bl,byte [BPB_SecPerClus] mov word [BlockCount],bx ;讀取的塊數(shù) mul bx mov di,ax ;緩沖區(qū)增量 Label_load_file_next : pop eax ;文件起始簇 test eax,eax jz label_load_file_over cmp eax,0xfff7 jae label_load_file_over push eax sub eax,2 xor ebx,ebx mov bl,byte [BPB_SecPerClus] mul ebx add eax,dword [FirstDataSector] mov dword [BlockNum],eax ;起始?jí)K push 64 push DiskAddressPacket push Buffer_Save_DAP_Base call MemCpy call ClusterContext push eax ;下次的簇 push 64 push Buffer_Save_DAP_Base push DiskAddressPacket call MemCpy mov ax,ds mov word [BufferSeg],ax mov dl,[BS_DrvNum] mov ah,42h ;ah=42h 讀 mov si,DiskAddressPacket ;DAP地址 int 13h jc label_load_file_error add word [BufferOff],di jmp Label_load_file_next label_load_file_error : push MsgReadSecError call DispStr jmp $ label_load_file_over : popa ret 4 %if ($-$$) > (512+ 512 * 1) %error 引導(dǎo)代碼超過(guò)保留扇區(qū)空間 %else times 512+512-($-$$) db 0 %endif ;//////////////////////////////////////////////// ;內(nèi)存 0x8100 扇區(qū)3 扇區(qū)4 %if ($-$$) > (512+ 512) %error 緩沖區(qū)邊界未對(duì)齊 %else ;內(nèi)存0x8100 扇區(qū)3 ;times 512*8 db 0 ;times 512*8 db 0 %endif ??;makefile # All Phony Targets IMG_PATH = ./../hd.img BOOT_PATH = ./bin/Boot.bin LOADER_PATH = ./bin/loader.bin MBR_PATH = ./bin/hdmbr.bin .PHONY : build debug build : ./bin/Boot.bin ./bin/loader.bin debug : build Write ./bin/Boot.bin : Boot_fat32.asm nasm -o $(BOOT_PATH) Boot_fat32.asm #寫(xiě)入jmp 指令 dd if=$(BOOT_PATH) of=$(IMG_PATH) bs=1 seek=32256 count=3 conv=notrunc #寫(xiě)入分區(qū)引導(dǎo)扇區(qū)引導(dǎo)代碼 dd if=$(BOOT_PATH) of=$(IMG_PATH) bs=1 skip=62 seek=32318 count=450 conv=notrunc #寫(xiě)入分區(qū)保留扇區(qū)引導(dǎo)代碼 dd if=$(BOOT_PATH) of=$(IMG_PATH) bs=512 skip=1 seek=64 count=1 conv=notrunc #復(fù)制分區(qū)表中的分區(qū)信息到分區(qū)引導(dǎo)扇區(qū) dd if=$(IMG_PATH) of=$(IMG_PATH) bs=1 skip=454 seek=32346 count=8 conv=notrunc #fat16磁盤(pán) dd if=$(IMG_PATH) of=$(IMG_PATH) bs=1 skip=454 seek=32318 count=8 conv=notrunc ./bin/loader.bin : loader.asm nasm -o $(LOADER_PATH) loader.asm sudo losetup -o 32256 /dev/loop0 $(IMG_PATH) sudo mount -t msdos /dev/loop0 /mnt/dvd/ sudo cp $(LOADER_PATH) /mnt/dvd/ -v sudo umount /mnt/dvd/ sudo losetup -d /dev/loop0 #安裝主引導(dǎo)記錄 Write : $(MBR_PATH) $(BOOT_PATH) dd if=$(MBR_PATH) of=$(IMG_PATH) conv=notrunc dd if=$(BOOT_PATH) of=$(IMG_PATH) bs=1 skip=510 seek=510 count=2 conv=notrunc --------轉(zhuǎn)載
|
|