8 %define bsOemName
bp+0x03 ; OEM label (8)
9 %define bsBytesPerSec
bp+0x0B ; bytes/sector (dw)
10 %define bsSecsPerClust
bp+0x0D ; sectors/allocation unit (db)
11 %define bsResSectors
bp+0x0E ; # reserved sectors (dw)
12 %define bsFATs
bp+0x10 ; # of fats (db)
13 %define bsRootDirEnts
bp+0x11 ; Max # of root dir entries (dw)
14 %define bsSectors
bp+0x13 ; # sectors total in image (dw)
15 %define bsMedia
bp+0x15 ; media descriptor (db)
16 %define bsSecsPerFat
bp+0x16 ; # sectors in a fat (dw)
17 %define bsSecsPerTrack
bp+0x18 ; # sectors/track
18 %define bsHeads
bp+0x1A ; # heads (dw)
19 %define bsHidden
bp+0x1C ; # hidden sectors (dd)
20 %define bsSectorHuge
bp+0x20 ; # sectors if > 65536 (dd)
21 %define bsDriveNumber
bp+0x24 ; (dw)
22 %define bsSigniture
bp+0x26 ; (db)
23 %define bsVolumeSerial
bp+0x27 ; (dd)
24 %define bsVolumeLabel
bp+0x2B ; (11)
25 %define bsSysID
bp+0x36 ; (8)
27 times
0x3B db 0 ; Code starts at offset 0x3E
30 mov [bsDriveNumber
], dl ; BIOS passes drive number in DL
38 ; Make sure the screen is set to 80x25 color text mode
39 mov ax, 0x0003 ; Set to normal (80x25 text) video mode
46 ; read in the root cluster
47 ; check for the filename
48 ; if found save the starting cluster
51 ;fatstart = bsResSectors
53 ;rootcluster = bsResSectors + (bsFATs * bsSecsPerFat)
54 ; 4 + (2 * 254) = sector 512
56 ;datastart = bsResSectors + (bsFATs * bsSecsPerFat) + ((bsRootDirEnts * 32) / bsBytesPerSec)
57 ; 4 + (2 * 254) + ((512 * 32) / 512) = sector 544
59 ;cluster X starting sector
60 ; starting sector = (bsSecsPerClust * (cluster# - 2)) + datastart
62 ; 0x7C5C as of Jan 6, 2010
66 call readsector
; Read the MBR to 0x8000
67 mov eax, [0x81C6] ; Grab the dword at 0x01C6 (num of sectors between MBR and first sector in partition)
68 mov [secoffset
], eax ; Save it for later use
72 mov ax, [bsSecsPerFat
]
73 shl ax, 1 ; quick multiply by two
74 add ax, [bsResSectors
]
77 mov bx, [bsRootDirEnts
]
78 shr bx, 4 ; bx = (bx * 32) / 512
79 add bx, ax ; BX now holds the datastart sector number
89 ; Search for file name, and find start cluster.
94 jz ff_done
; note that di now is at dirent+11
98 cmp di, [bsBytesPerSec
]
101 dec dx ; next sector in cluster
106 mov ax, [di] ; AX now holds the starting cluster #
108 ; At this point we have found the file we want and know the cluster where the file starts
110 mov bx, 0x8000 ; We want to load to 0x0000:0x8000
113 cmp ax, 0xFFF8 ; Have we reached the end cluster marker?
114 jg loadfile
; If not then load another
120 ;------------------------------------------------------------------------------
121 ; Read a sector from a disk, using LBA
122 ; input: EAX - 32-bit DOS sector number
123 ; ES:BX - destination buffer
124 ; output: ES:BX points one byte after the last byte read
132 push eax ; Save the sector number
133 mov di, sp ; remember parameter block end
135 push byte 0 ; other half of the 32 bits at [C]
136 push byte 0 ; [C] sector number high 32bit
137 push eax ; [8] sector number low 32bit
138 push es ; [6] buffer segment
139 push bx ; [4] buffer offset
140 push byte 1 ; [2] 1 sector (word)
141 push byte 16 ; [0] size of parameter block (word)
144 mov dl, [bsDriveNumber
]
145 mov ah, 42h ; EXTENDED READ
146 int 0x13 ; http://hdebruijn.soo.dto.tudelft.nl/newpage/interupt/out-0700.htm#0651
148 mov sp, di ; remove parameter block from stack
149 pop eax ; Restore the sector number
151 jnc read_ok
; jump if no error
154 xor ah, ah ; else, reset and retry
160 inc eax ; next sector
161 add bx, 512 ; Add bytes per sector
162 jnc no_incr_es
; if overflow...
166 add dh, 0x10 ; ...add 1000h to ES
174 ;------------------------------------------------------------------------------
177 ;------------------------------------------------------------------------------
178 ; Read a cluster from a disk partition, using LBA
179 ; input: AX - 16-bit cluster number
180 ; ES:BX - destination buffer
181 ; output: ES:BX points one byte after the last byte read
185 mov [tcluster
], ax ; save our cluster value
186 ;cluster X starting sector
187 ; starting sector = (bsSecsPerClust * (cluster# - 2)) + datastart
190 mov cl, byte [bsSecsPerClust
]
191 imul
cx ; EAX now holds starting sector
192 add ax, word [datastart
] ; add the datastart offset
195 mov cl, byte [bsSecsPerClust
]
197 readcluster_nextsector:
201 jne readcluster_nextsector
203 ; Great! We read a cluster.. now find out where the next cluster is
204 push bx ; save our memory pointer
205 mov bx, 0x7E00 ; load a sector from the root cluster here
207 mov ax, [bsResSectors
]
210 pop bx ; bx points to 0x7e00 again
211 mov ax, [tcluster
] ; ax holds the cluster # we just read
212 shl ax, 1 ; multipy by 2
216 pop bx ; restore our memory pointer
220 ;------------------------------------------------------------------------------
223 ;------------------------------------------------------------------------------
224 ; 16-bit Function to print a sting to the screen
225 ; input: SI - Address of start of string
226 print_string_16: ; Output string in SI to screen
228 mov ah, 0x0E ; int 0x10 teletype function
230 lodsb ; Get char from string
232 je .done
; If char is zero, end of string
233 int 0x10 ; Otherwise, print it
238 ;------------------------------------------------------------------------------
241 msg_Load
db "Loading... ", 0
243 filename
db "PURE64 SYS", 0
247 secoffset
dd 0x00000000