📄 bdosldr.a86
字号:
inc cluster_count ; else read one more cluster
jmps rd_file2 ; try again with next cluster
rd_file3: ; CX = next chain, multi cluster read
push cx ; save start of next chain
les bx,dta_ptr ; ES:BX -> transfer address
mov cx,start_cluster ; previous contiguous chain starts here
mov dx,cluster_count ; length of chain in clusters
call rd_cluster ; read DX clusters
mov al,BT_sctr_per_cluster
mov ah,0 ; AX = sectors per cluster
mul cluster_count ; AX = sectors in chain to read
mul BT_bytes_per_sector ; AX = bytes in chain to read
add dta_off,ax
pop cx ; CX = next (noncontiguous) cluster
mov start_cluster,cx ; start of new chain
inc cx ; was it end of file cluster number?
jnz rd_file1 ; go back for more if not
; else all clusters done
ret
get_FAT_byte:
;------------
; entry: BX = offset into FAT
mov ax,bx ; BX = offset into FAT
sub dx,dx ; AX/DX = 32 bit offset
div BT_bytes_per_sector ; AX = sector, DX = offset in sector
push dx ; save offset in sector
call locate_FAT ; read FAT sector AX
pop bx ; BX = offset in FAT sector
mov al,sector_buffer[bx] ; get byte from FAT buffer
ret
locate_FAT:
;----------
; entry: AX = FAT sector to locate
cmp ax,current_fatsec ; AX = sector offset into FAT
je locate_FAT_match ; O.K. if same as last time
mov current_fatsec,ax ; set new sector for next time
push cx ! push si ; preserve FAT index
mov cx,ax ; CX = sector number
mov bx,offset sector_buffer
push ds ! pop es ; ES:BX -> sector buffer
mov dx,1 ; DX = single sector
call rd_sector_rel ; read FAT sector
pop si ! pop cx ; restore FAT index
locate_FAT_match: ; return with right sector in buffer
ret
eject
; reads sectors relative to start of DOS area on disk (start=0)
; same parameters as rd_sector
rd_sector_rel:
;-------------
; entry: CX = sector address relative to first FAT sector
; DX = sector count
sub bp,bp ;overflow word = 0
add cx,BT_reserved_sectors
adc bp,0
; jmps rd_sector
; reads absolute sectors from hard disk using rom bios
rd_sector:
;---------
; entry: DX = number of sectors
; ES:BX -> data transfer buffer
; DS -> program global data segment
; CX/BP = absolute sector # (32 bit) (low/high)
push cx ! push dx ; save parameters
mov req3_bufoff,bx ; save transfer offset
mov req3_bufseg,es ; save transfer segment
mov req3_count,dx ; set sector count
mov bx,offset req_hdr ; BX -> request header
mov ds:RH_CMD,CMD_INPUT ; read from disk device
mov req3_sector,cx ; set requested sector address
if DOS5
mov req_hdr,RH4_LEN
mov req3_sector32,cx ; with 32 sector number
mov req3_sector32+2,bp
test bp,bp ; large sector number?
jz rd_sec1 ; no, normal request header
mov req3_sector,0FFFFh ; mark as a large request
rd_sec1:
else
mov req3_sector+2,bp ; (support large DOS drives)
mov req_hdr,24 ; indicate large request
endif
call device_request ; tell it to read sectors
pop cx ! pop dx
ret ; if CY, AH=error code
rd_cluster:
;----------
; entry: CX = DOS cluster number.
; DX = cluster count
; ES:BX -> transfer buffer
push bx ! push es
mov al,BT_sctr_per_cluster
mov ah,0 ; AX = sectors per cluster
mul dx ; AX = sectors in all clusters
push ax ; save the sector count
sub cx,2 ; cluster 2 is data area start
mov al,BT_sctr_per_cluster
cbw
mul cx ; AX,DX = relative sector #
mov cx,ax
mov bp,dx ; CX,BP = data area sector #
mov al,BT_nfats ; compute FAT size
mov ah,0 ; AX = # of FAT copies (usually 2)
mul BT_fat_size ; AX/DX = size of FAT in sectors
add cx,ax
adc bp,dx ; CX,BP = end of FAT sectors
mov ax,32
mul BT_dirsize ; AX,DX = bytes in root directory
mov bx,BT_bytes_per_sector
dec bx
add ax,bx ; round up directory size
adc dx,0
inc bx
div bx ; AX = root directory sectors
add cx,ax
adc bp,0 ; add root directory size
add cx,BT_reserved_sectors ; add in boot sector(s)
adc bp,0
pop dx ! pop es ! pop bx ; sector count, disk address
jmp rd_sector ; DX secs from CX/BP to ES:BX
; Finds the NEXT cluster after the one passed in CX in an allocation
; chain by using the FAT. Returns the carry set if the end of chain
; mark is found, otherwise returns the NEW cluster # in CX.
next_cluster:
;------------
push dx ! push bx ; save some registers
cmp fat16,0 ; check if this is 12 bit media
je next_cluster12 ; skip if old fashioned 12 bit
mov ax,2
mul cx ; AX/DX = byte offset in FAT (max. 128K)
div BT_bytes_per_sector ; AX = FAT sector #, DX = byte offset
push dx ; save byte offset within sector
call locate_FAT ; get FAT sector AX
pop bx ; BX = offset within sector
mov cx,word ptr sector_buffer[bx]
; get 16 bit from FAT
cmp cx,0FFF7h ; check if too large for #
jae next_cluster_eof ; set carry, EOF
clc
jmps next_cluster_ret ; good link
next_cluster12: ; DOS 2.x disk
push cx ; save cluster number
mov bx,cx
add bx,bx ; BX = cluster# * 2
add bx,cx ; BX = cluster# * 3
shr bx,1 ; BX = cluster# * 1.5
push bx ; save offset in the FAT
inc bx ; BX = offset of high byte
call get_FAT_byte ; get the high byte in AL
pop bx ; BX = offset of low byte
push ax ; save high byte on stack
call get_FAT_byte ; get the low byte in AL
pop bx ; pop off high byte into BL
mov ah,bl ; set high byte, AX = word
pop cx ; restore cluster number
shr cx,1 ; test if even or odd
jnc even_fat ; if even entry, done
mov cl,4 ; odd entry, shift down one nibble
shr ax,cl ; else need to justify
even_fat: ; even entry, strip off top bits
and ax,0fffh ; bx[0..11] are cluster
mov cx,ax ; CX = cluster number
cmp cx,0ff7h ; compare with largest legal 12 bit #
jae next_cluster_eof ; check for end mark
clc
jmps next_cluster_ret ; return value in CX, CY = 0
next_cluster_eof:
mov cx,-1 ; indicate end of chain
stc ; end of chain
next_cluster_ret:
pop bx ! pop dx
ret
eject
;
; INITIALIZED DATA SEGMENT
; ========================
INITDATA dseg 'INITDATA'
extrn resdev_chain:dword ; resident device driver root
extrn current_dos:word ; current BDOS segment
extrn boot_device:dword ; device driver we boot from
extrn boot_drv:byte ; boot drive
extrn dos_name:byte ; name of BDOS file
strat_ptr rd 0
strat_off rw 1
strat_seg rw 1
intrpt_ptr rd 0
intrpt_off rw 1
intrpt_seg rw 1
dta_ptr rd 0
dta_off rw 1
dta_seg rw 1
start_cluster rw 1
cluster_count rw 1
current_fatsec dw -1 ; no FAT sector read yet
fat16 dw 0 ; defaults to 12 bit FAT
; single error message if BDOS can't be loaded:
include initmsgs.def ; Include TFT Header File
;dos_msg db CR,LF,'Can''t load DOS file.$'
; static request header for DOS device driver I/O
req_hdr db 22
req_unit rb 1
req_cmd rb 1
req_status rw 1
rd 2
req_media rb 1
rb 16
req1_return equ byte ptr req_media+1
req1_volid equ word ptr req_media+2
req2_bufoff equ word ptr req_media+1
req2_bufseg equ word ptr req_media+3
req2_bpb equ word ptr req_media+5
req3_buffer equ dword ptr req_media+1
req3_bufoff equ word ptr req_media+1
req3_bufseg equ word ptr req_media+3
req3_count equ word ptr req_media+5
req3_sector equ word ptr req_media+7
req3_volid equ word ptr req_media+9
req3_sector32 equ word ptr req_media+13
; local copy of the BPB for the boot device
local_bpb rb 0
BT_bytes_per_sector rw 1
BT_sctr_per_cluster rb 1
BT_reserved_sectors rw 1
BT_nfats rb 1
BT_dirsize rw 1
BT_total_sectors rw 1
BT_fatid rb 1
BT_fat_size rw 1
BT_sectors_per_track rw 1
BT_nheads rw 1
BT_hidden_sectors rw 2
BT_total_long rw 2
BPB_LENGTH equ (offset $-offset local_bpb)
extrn sector_buffer:byte
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -