📄 fat12-f.asm
字号:
; jump to second stage that is ORGed to address "SS_ORG"
%ifdef DOS
mov ax,ds
add ax,((SS_ADR - SS_ORG) >> 4)
%else
mov ax,((SS_ADR - SS_ORG) >> 4)
%endif
mov ds,ax
mov es,ax
mov ss,ax
push ax
push word SS_ORG
retf
; disk read error; display blinking 'R'
err:
mov ax,9F52h
err2:
mov bx,0B800h ; assumes color emulation
mov es,bx
xor bx,bx
mov [es:bx],ax
; *** BEEEP ***
mov ax,0E07h
int 10h
; await key pressed
mov ah,0
int 16h
; re-start the boot process
int 19h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: find_file
; action: searches for file in root dir
; in: 11-char all-caps filename at SI, [root_start] set
; out (disk error): CY=1
; out (file not found): CY=0, ZF=0
; out (found it): CY=0, ZF=1, BX=starting cluster of file,
; ES:DI is left pointing to the directory entry
; modifies: AX, BX, CX, DX, DI, ES
; minimum CPU: 8088
; notes:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
find_file:
xor dx,dx
mov ax,[root_start] ; 1st sector in root dir
%ifdef DOS
mov bx,ds ; where to load it
add bx,(ADR_DIRBUF >> 4)
%else
mov bx,(ADR_DIRBUF >> 4)
%endif
mov es,bx
find_file_1:
mov cx,1
call read_sectors ; one sector at a time
jc find_file_5 ; disk read error
xor di,di
find_file_2:
test [es:di],byte 0FFh ; 0 byte = end of root dir
je find_file_3
mov cl,11 ; 'read_sectors' zeroed CH
push si
push di ; compare filename to dirent
rep cmpsb
pop di
pop si
je find_file_4
; if filename comparision failed, advance 32 bytes to next dir entry
add di,byte 32
cmp di,[bp - (over -bytes_per_sector)]
jb find_file_2
inc ax
cmp ax,[bp - (over - data_start)]
jb find_file_1 ; go to next sector of root
find_file_3:
; did not find the file: return with CY=0, ZF=0
or al,1
find_file_4:
; found the file
mov bx,[es:di + 26] ; get first cluster of file
find_file_5:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: walk_fat
; action: converts cluster value to sector,
; and gets next cluster of file from FAT
; in: BX=cluster
; out (disk error): CY=1
; out (success): CY=0, DX:AX=first sector of cluster, BX=next cluster
; modifies: AX, BX, DX, SI
; minimum CPU: 8088
; notes:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
walk_fat:
push es
push cx
mov ax,bx
; cluster 2 is the first data cluster
dec ax
dec ax
; convert from clusters to sectors
mov dh,0
mov dl,[bp - (over - sectors_per_cluster)]
mul dx
add ax,[bp - (over - data_start)]
adc dx,byte 0
; 0:AX is return value; save it
push ax
%ifdef DOS
mov ax,ds
add ax,(ADR_FATBUF >> 4)
%else
mov ax,(ADR_FATBUF >> 4)
%endif
mov es,ax
; FAT12 entries are 12 bits, bytes are 8 bits. Ratio is 3 / 2,
; so multiply cluster by 3, and divide by 2 later.
mov ax,bx
shl ax,1 ; entry * 2
add ax,bx ; + entry = entry * 3
mov bx,ax
; BX:0 =use high or low 12 bits of 16-bit value read from FAT
; BX:9...BX:1 =byte offset into FAT sector (9 assumes 512-byte sectors)
; BX:?...BX:10 =which sector of FAT to load
; figure out which FAT sectors to load
shr ax,1 ; entry / 2
xor dx,dx
div word [bp - (over - bytes_per_sector)]
; remainder is byte offset into FAT; put it in SI
mov si,dx
; quotient in AX is FAT sector: add FAT starting sector
add ax,[bp - (over - fat_start)]
; check the FAT buffer to see if this sector is already loaded
cmp ax,[bp - (over - curr_sector)]
je walk_fat_1
mov [curr_sector],ax
; read the target FAT sector plus the sector after it
; (in case the 12-bit FAT entry straddles the two sectors)
xor dx,dx
mov cx,2
call read_sectors
jc walk_fat_4
; get 16 bits from FAT
walk_fat_1:
mov ax,[es:si]
; look at BX:0 to see if we want the high 12 bits or the low 12 bits
shr bx,1
jc walk_fat_2
and ax,0FFFh ; CY=1: use low 12 bits
jmp short walk_fat_3
walk_fat_2:
mov cl,4
shr ax,cl ; CY=0: use high 12 bits
walk_fat_3:
mov bx,ax
; clear CY bit to signal success
xor dx,dx
walk_fat_4:
pop ax
pop cx
pop es
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; name: read_sectors
; action: reads one or more disk sectors into memory
; in: ES:0=address of memory where sectors should be read
; DX:AX=first sector to read
; CX=number of sectors to read
; out (disk error): CY=1
; out (success): CY=0
; modifies: DX, CX, AX
; minimum CPU: 8088
; notes:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
read_sectors:
push es
push bx
xor bx,bx
; add partition start
add ax,[bp - (over - hidden_sectors) + 0]
adc dx,[bp - (over - hidden_sectors) + 2]
read_sectors_1:
push dx
push cx
push ax
; DX:AX=LBA sector number
push ax
mov ax,dx
xor dx,dx
; divide LBA by sectors_per_track (spt).
; Use a two-step 32-bit/16-bit divide to avoid overflow.
; See "9.3.5 Extended Precision Division" in Randall Hyde's "Art of Assembly"
div word [bp- (over - sectors_per_track)]
; DX=high LBA % spt, AX=high LBA / spt
mov cx,ax
pop ax
; DX=high LBA % spt, CX=high LBA / spt, AX=low LBA
; New 32-bit dividend is DX:AX
div word [bp- (over - sectors_per_track)]
; CX:AX=LBA / spt, DX=LBA % spt
xchg cx,dx
inc cx ; CL=sector
; DX:AX=LBA / spt, do normal one-step divide by heads value
div word [bp - (over - heads)]
mov dh,dl ; DH=head
mov ch,al ; CH=cylinder 7:0
mov dl,[bp - (over - boot_drive)]
shl cl,1
shl cl,1 ; trying to use only...
shr ah,1 ; ...8088 asm here
rcr cl,1
shr ah,1
rcr cl,1 ; CL7:6=cyl 9:8, CL5:0=sector
; now: read one sector
mov ax,0201h
int 13h
jnc read_sectors_3
; disk error; recalibrate/reset drive
mov ah,0
int 13h
jc read_sectors_2
; try the read again. If it fails a second time, give up.
mov ax,0201h
int 13h
jnc read_sectors_3
read_sectors_2:
pop ax
pop cx
pop dx
jmp short read_sectors_5
; advance memory pointer
read_sectors_3:
mov ax,es
add ax,[bp - (over - para_per_sector)]
mov es,ax
pop ax
pop cx
pop dx
; increment DX:AX to advance to next sector
inc ax
jne read_sectors_4
inc dx
read_sectors_4:
loop read_sectors_1
; clear CY bit to signal success
clc
read_sectors_5:
pop bx
pop es
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 1st-stage data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
curr_sector: ; which sector is in the FAT buffer
dw -1
; name of the second stage bootloader
second_stage:
db SS_NAME
; pad with NOPs to offset 510
times (510 + $$ - $) nop
; 2-byte magic bootsector signature
db 55h, 0AAh
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -