📄 fathelp.asm
字号:
; FATHELP.ASM
; FAT12/16 Boot Sector Helper Code
; Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
;org 8000h
segment .text
bits 16
BootSectorStackTop equ 0x7bf2
DataAreaStartHigh equ 0x2
DataAreaStartLow equ 0x4
BiosCHSDriveSizeHigh equ 0x6
BiosCHSDriveSizeLow equ 0x8
BiosCHSDriveSize equ 0x8
ReadSectorsOffset equ 0xa
ReadClusterOffset equ 0xc
PutCharsOffset equ 0xe
OEMName equ 3
BytesPerSector equ 11
SectsPerCluster equ 13
ReservedSectors equ 14
NumberOfFats equ 16
MaxRootEntries equ 17
TotalSectors equ 19
MediaDescriptor equ 21
SectorsPerFat equ 22
SectorsPerTrack equ 24
NumberOfHeads equ 26
HiddenSectors equ 28
TotalSectorsBig equ 32
BootDrive equ 36
Reserved equ 37
ExtendSig equ 38
SerialNumber equ 39
VolumeLabel equ 43
FileSystem equ 54
BootPartition equ 0x7dfd
; This code will be stored in the first 512 bytes
; of freeldr.sys. The first 3 bytes will be a jmp
; instruction to skip past the FAT helper code
; that is stored in the rest of the 512 bytes.
;
; This code is loaded at 0000:8000 so we have to
; encode a jmp instruction to jump to 0000:8200
global _mainCRTStartup ; For Mingw32 builds where the linker looks for this symbol
_mainCRTStartup:
global start
start:
db 0xe9
db 0xfd
db 0x01
; Now starts the extra boot code that we will store
; in the first 512 bytes of freeldr.sys. This code
; allows the FAT12/16 bootsector to navigate the
; FAT table so that we can still load freeldr.sys
; even if it is fragmented.
FatHelperEntryPoint:
push ax ; First save AX - the start cluster of freeldr.sys
; Display "Loading FreeLoader..." message
mov esi,msgLoading ; Loading message
call [bp-PutCharsOffset] ; Display it
call ReadFatIntoMemory
pop ax ; Restore AX (start cluster)
; AX has start cluster of freeldr.sys
mov bx,800h
mov es,bx
LoadFile:
push ax
call IsFat12
pop ax
jnc LoadFile2
cmp ax,0ff8h ; Check to see if this is the last cluster in the chain
jmp LoadFile3
LoadFile2:
cmp ax,0fff8h
LoadFile3:
jae LoadFile_Done ; If so continue, if not then read then next one
push ax
xor bx,bx ; Load ROSLDR starting at 0000:8000h
push es
call [bp-ReadClusterOffset]
pop es
xor bx,bx
mov bl,BYTE [BYTE bp+SectsPerCluster]
shl bx,5 ; BX = BX * 512 / 16
mov ax,es ; Increment the load address by
add ax,bx ; The size of a cluster
mov es,ax
call IsFat12
pop ax
push es
jnc LoadFile4
call GetFatEntry12 ; Get the next entry
jmp LoadFile5
LoadFile4:
call GetFatEntry16
LoadFile5:
pop es
jmp LoadFile ; Load the next cluster (if any)
LoadFile_Done:
mov dl,BYTE [BYTE bp+BootDrive] ; Load the boot drive into DL
mov dh,[BootPartition] ; Load the boot partition into DH
push WORD 0x0000
push WORD 0x8000 ; We will do a far return to 0000:8000h
retf ; Transfer control to ROSLDR
; Reads the entire FAT into memory at 7000:0000
ReadFatIntoMemory:
mov ax,WORD [BYTE bp+HiddenSectors]
mov dx,WORD [BYTE bp+HiddenSectors+2]
add ax,WORD [BYTE bp+ReservedSectors]
adc dx,byte 0
mov cx,WORD [BYTE bp+SectorsPerFat]
mov bx,7000h
mov es,bx
xor bx,bx
call [bp-ReadSectorsOffset]
ret
; Returns the FAT entry for a given cluster number for 16-bit FAT
; On entry AX has cluster number
; On return AX has FAT entry for that cluster
GetFatEntry16:
mov cx,2 ; AX = AX * 2 (since FAT16 entries are 2 bytes)
mul cx
shl dx,12
mov bx,7000h
add bx,dx
mov es,bx
mov bx,ax ; Restore FAT entry offset
mov ax,WORD [es:bx] ; Get FAT entry
ret
; Returns the FAT entry for a given cluster number for 12-bit FAT
; On entry AX has cluster number
; On return AX has FAT entry for that cluster
GetFatEntry12:
push ax
mov cx,ax
shr ax,1
add ax,cx ; AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
mov bx,7000h
mov es,bx
mov bx,ax ; Put FAT entry offset into BX
mov ax,WORD [es:bx] ; Get FAT entry
pop cx ; Get cluster number from stack
and cx,1
jz UseLow12Bits
and ax,0fff0h
shr ax,4
jmp GetFatEntry12_Done
UseLow12Bits:
and ax,0fffh
GetFatEntry12_Done:
ret
; Returns CF = 1 if this is a FAT12 file system
; Otherwise CF = 0 for FAT16
IsFat12:
mov ebx,DWORD [BYTE bp-DataAreaStartLow]
; EBX now has the number of the starting sector of the data area
; starting from the beginning of the disk, so subtrace hidden sectors
sub ebx,DWORD [BYTE bp+HiddenSectors]
xor eax,eax
mov ax,WORD [BYTE bp+TotalSectors]
cmp ax,byte 0
jnz IsFat12_2
mov eax,DWORD [BYTE bp+TotalSectorsBig]
; EAX now contains the number of sectors on the volume
IsFat12_2:
sub eax,ebx ; Subtract data area start sector
xor edx,edx ; from total sectors of volume
; EDX:EAX now contains the number of data sectors on the volume
movzx ebx,BYTE [BYTE bp+SectsPerCluster]
div ebx
; EAX now has the number of clusters on the volume
stc
cmp eax,4085
jb IsFat12_Done
clc
IsFat12_Done:
ret
msgLoading db 'Loading FreeLoader...',0dh,0ah,0
times 510-($-$$) db 0 ; Pad to 510 bytes
dw 0aa55h ; BootSector signature
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -