📄 bootf.asm
字号:
; bootf.asm FAT12 floppy bootstrap for protected mode image
; Version 2.0, May 1, 1999
; Sample code
; by John S. Fine johnfine@erols.com
; I do not place any restrictions on your use of this source code
; I do not provide any warranty of the correctness of this source code
;_____________________________________________________________________________
;
; Documentation:
;
; 1) Most of the documentation is in comments at the END of this file.
; 2) Some is in the read.me file that came with this file.
; 3) In the comments within the source code are several uses of {}, each
; of these indicates a section of documentation at the end of this file
; which applies to that part of the source code.
; 4) The major way I reduced code size was to rely on left-over values in
; registers and/or to initialize registers at points where doing so was
; cheap. To make that understandable, there are several lines beginning
; with either ";>" or ";>>". These lines describe the register contents
; at that point in the code. ";>" indicates that the value is required
; by the next section of code. ";>>" indicates that the value passes
; through the next section unmodified and is needed later.
; 5) I made this code by modifying my bootp example. If something doesn't
; make sense here, maybe comparison to the other version will help.
;_____________________________________________________________________________
;
; Limitations:
;
; For simplicity, I made several assumptions about the environment. Some
; of those may need to be expanded in a future version. Except for the first,
; they are all things that could be checked by a "SYS" program that installs
; this bootstrap. In general it makes more sense (where possible) for a SYS
; program to check compatibility issues than for a bootstrap to check them
; itself.
;
; If these limits are violated, this code simply bombs. It does not check
; the limits nor display error messages.
;
; 1) Runs only on a 386+
; 2) The FAT structure must be the first thing on the drive (no partitions).
; It just uses "reserved" sectors before the FAT, not "hidden" etc.
; 3) The sector size must be 512 bytes
; 4) There are less than 256 sectors per fat (safe, since FAT12 has less than
; 4096*1.5 bytes per FAT).
; 5) LBN of root directory less than 65536 (safe in unpartitioned FAT12)
;_____________________________________________________________________________
%include "gdt.inc"
struc BB ;FAT Boot block
resb 0xD ;Things we ignore
BB_clu resb 1 ;Sectors per cluster
BB_res resw 1 ;Reserved sectors
BB_fats resb 1 ;Number of FATs
BB_root resw 1 ;Root directory entries
resb 3 ;Things we ignore
BB_fat resw 1 ;Sectors per fat
BB_sec resw 1 ;Sectors per track
BB_head resw 1 ;Heads
endstruc
SEGMENT START USE16
;> cs = 0
;>> dl = drive we were booted from
boot: jmp short start ;Standard start of boot sector
nop
resb 0x3B ;Skip over parameters (set by format)
start: cli ;{0}
lgdt [cs:gdt] ;Load GDT
mov ecx, CR0 ;Switch to protected mode
inc cx
mov CR0, ecx ;{5}
.5: in al, 0x64 ;Enable A20 {4A}
test al, 2
jnz .5
mov al, 0xD1
out 0x64, al
.6: in al, 0x64
and ax, byte 2
jnz .6
mov al, 0xDF
out 0x60, al
;> ah = 0
;> dl = drive we were booted from
mov al, flat_data ;Selector for 4Gb data seg
mov ds, ax ;{2} Extend limit for ds
mov es, ax ;Extend limit for es
dec cx ;Switch back to real mode
mov CR0, ecx ;{5}
mov [boot], dl ;Save drive number we came from
mov sp, 0x800 ;{1B}
xor eax, eax ;Segment
mov ds, ax ;
mov ss, ax
mov es, sp ;Read directory at 800:0 {1C}
;> eax = 00000000
mov al, [boot+BB_fats] ;Number of FATs
mul byte [boot+BB_fat] ;Times size of FAT
add ax, [boot+BB_res] ;Plus Sectors before first FAT
;eax = LBN of Root directory
movzx edi,word [boot+BB_root] ;Root directory entries
push di ; used again later
dec di ;Convert to number of sectors
shr di, 4 ; 16 directory entries per sector
inc di
call read_sectors
;> eax = LBN of root directory
;> edi = length of root directory in sectors
;> [sp] = length of root directory in entries
;> esi = 00000000
lea ebp, [eax+edi] ;ebp = LBN of cluster 2
pop bx ;Root directory entries
xor di, di ;Point at directory {1C}
.20: mov si, file_name ;Name of file we want
xor ecx, ecx
mov cl, 11
a32 rep cmpsb ;Found the file?
je found ;Yes
add cl, 21 ;Offset to next directory entry
add edi, ecx ;Advance to next entry
dec bx ;Loop through all entries
jnz .20
;Couldn't find file in directory
boot_error:
disk_error:
mov ax, 0xE07 ;{3}
int 10h
jmp short $
;>> ecx = 00000000
;> es = 800
;> es:edi = Directory entry of file
;> ebp = LBN of cluster 2
;> eax = 0000????
found: push word [es:edi+0xF] ;Starting cluster of file
mov di, [boot+BB_fat] ;Size of FAT (in sectors)
mov ax, [boot+BB_res] ;LBN of FAT
call read_sectors
mov bx, 0x4000
mov es, bx ;es = 0x4000
mov edi, 0x100000-0x40000 ;{1D}{4B} One megabyte minus ES base
.10:
;>> ecx = 0000????
;> [sp] = Next cluster of file
;> esi = 0000????
;>> edx = 0000????
;> es:edi = Destination address
;> ebp = LBN of cluster 2
;> ds = 0
xor eax, eax
pop si ;Next cluster of file
mov bx, si
cmp si, 0xFF8 ;Valid cluster?
jae eof ;No: assume end of file
;Yes: (c-bit set)
rcr bx, 1 ;bx = 0x8000 + cluster/2
mov bx, [bx+si] ;Get word containing FAT entry
jnc .11 ;Entry is low 12 bits
shr bx, 4 ;Entry was high 12 bits
.11: and bh, 0xF ;Mask to just 12 bits
push bx ;Save cluster after next
push di ;Save destination address {7}
mov al, [boot+BB_clu] ;Size of each cluster
mov di, ax ; (in sectors)
dec si
dec si
mul esi ;Times cluster number minus 2
add eax, ebp ;Plus LBN of cluster 2
call read_sectors ;Read that cluster
;> ecx = 0000????
;>> edx = 0000????
;> di = Clustersize in sectors
;> esi = 0
;>> ebp = LBN of cluster 2
;> [sp] = Bottom 16-bits of destination address {7}
;>> [sp+2] = Following cluster
;> ds = 0
;> es = 4000
mov cx, di ;Cluster size in sectors
xchg ch, cl ;Cluster size in words
pop di ;Restore destination address {7}
es a32 rep movsw
jmp short .10 ;Loop until end of file
;> eax = 0
;> edx = 0000????
;> bx = 0FF?
eof:
mov dx, 0x9C00
mov es, dx ;es = 9C00
xor di, di ;{1E} Address of page tables WRT es
mov dh, 4096/256 ;edx = 4096
.10: mov cx, 1024
mov al, 7
.20: stosd
add eax, edx
int 8 ;{8}
loop .20
shr eax, 2 ;{4C} (first time only) 4Mb / 4 = 1Mb
neg bl ;Done just one page?
jns .10 ;Yes: do one more
cli ;{6}
mov eax, 0x9C007 ;First page tbl pointer in page dir
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -