@ -8,7 +8,7 @@
loadf:
;Store the initial registers in the stack
;Store BX, DX, SI, and DI in the stack
push bx
push dx
push si
@ -22,24 +22,28 @@ mov byte [.drive], dl
;Change the drive if needed
;Check for a drive specification
cmp byte [si + 0x1], ":"
jne .start
jne .convert
;Get the BIOS equipment list
int 0x11
;Get the number of floppy drives
times 0x6 shr ax, 0x1
and ax, 0x3
inc ax
;Set the loop and drive letter counters and the drive letter and number
mov cx, ax
mov di, driveletters
mov al, [si]
mov dl, 0x0
;Check which drive to change to
cmp byte [si], "a"
je .cha
cmp byte [si], "A"
je .cha
cmp byte [si], "b"
je .chb
cmp byte [si], "B"
je .chb
cmp byte [si], "c"
je .chc
cmp byte [si], "C"
je .chc
cmp byte [si], "d"
je .chd
cmp byte [si], "D"
je .chd
.checkdrive:
cmp al, [di]
je .contchdrive
inc di
cmp al, [di]
je .contchdrive
inc di
inc dl
loop .checkdrive
;Set AL to 0x1, CX to 0x0, and print an error message
mov si, .driverrormsg
mov ah, 0x2
@ -47,57 +51,41 @@ int 0x21
mov al, 0x1
mov cx, 0x0
jmp .done
;Change
.cha:
mov dl, 0x0
mov byte [.drive], dl
jmp .drivechanged
.chb:
mov dl, 0x1
mov byte [.drive], dl
jmp .drivechanged
.chc:
mov dl, 0x2
mov byte [.drive], dl
jmp .drivechanged
.chd:
mov dl, 0x3
mov byte [.drive], dl
.drivechanged:
;Change the drive
.contchdrive:
mov [.drive], dl
;Move to the file name
add si, 0x2
.start:
;Set DI at .file and initialise it with spaces
.convert:
mov di, .file
mov cx, 0xb
mov al, 0x20
rep stosb
sub di, 0xb
;Convert .file into FAT formatting
;Initialise the length counter for the main part of the file name
;Convert the main part of the file name into FAT format
;Set the length counter
mov bl, 0x8
;Convert the main part of the file name
.nameloop:
;Load a character
.nameloop:
lodsb
;Check for a period
cmp al, 0x2e
je .initext
;Check for everything else and convert to upper case
call .checkconv
;Load the next character
jmp .nameloop
;Convert the extension
;Convert the extension into FAT format
;Set DI and the length counter for the extension
.initext:
;Set DI and initialise the length counter for the extension
mov bl, 0x3
mov di, .file+0x8
.extloop:
;Load a character
.extloop:
lodsb
;Check for a period
push ax
@ -106,6 +94,7 @@ je .error
pop ax
;Check for everything else and convert to upper case
call .checkconv
;Load the next character
jmp .extloop
;Set AL to 0x4, CX to 0x0, and print an error message
.error:
@ -118,7 +107,6 @@ mov cx, 0x0
jmp .done
;Find and load the file
.load:
pop ax
@ -133,7 +121,7 @@ mov si, buffer
mov bx, si
;Set the size
mov al, 0x1
;Load
;Load the disk description table
mov ah, 0x2
int 0x13
jnc .storevalues
@ -147,79 +135,91 @@ jmp .done
;Store the disk values used for the rest of the call
.storevalues:
mov ax, word [buffer + 0xb]
mov word [.sectorsize], ax
mov al, byte [buffer + 0xd]
mov byte [.clustersize], al
mov ax, word [buffer + 0xe]
mov word [.boot sectors], ax
mov al, byte [buffer + 0x10]
mov byte [.fats], al
mov ax, word [buffer + 0x11]
mov word [.rootentries], ax
mov ax, word [buffer + 0x16]
mov word [.sectorsperfat], ax
mov ax, word [buffer + 0x18]
mov word [.sectorspertrack], ax
mov ax, word [buffer + 0x1a]
mov word [.side s], ax
mov ax, [buffer + 0xb]
mov [.sectorsize], ax
mov al, [buffer + 0xd]
mov [.clustersize], al
mov ax, [buffer + 0xe]
mov [.reserved sectors], ax
mov al, [buffer + 0x10]
mov [.fats], al
mov ax, [buffer + 0x11]
mov [.rootentries], ax
mov ax, [buffer + 0x16]
mov [.sectorsperfat], ax
mov ax, [buffer + 0x18]
mov [.sectorspertrack], ax
mov ax, [buffer + 0x1a]
mov [.head s], ax
;Load the root
;Set the source
;Calculate and store variables not found in the BPB
;Start of the root
mov ah, 0x0
mov al, [.fats]
mul word [.sectorsperfat]
add ax, [.bootsectors]
push ax
;Set the destination
mov si, buffer
mov bx, si
;Set the size
add ax, [.reservedsectors]
mov [.rootstart], ax
;Size of the root in sectors
mov ax, [.rootentries]
mov dx, 0x20
mul dx
mov dx, 0x0
div word [.sectorsize]
mov cx, ax
pop ax
mov [.rootsectors], ax
;Start of data
add ax, [.rootstart]
mov [.datastart], ax
;Load the root
;Set the source
mov ax, [.rootstart]
;Set the destination
mov si, buffer
mov bx, si
;Set the size
mov cx, [.rootsectors]
;Store the source and the loop counter in the stack
.loadrootsector:
push ax
push cx
.loadroot:
push cx
;Set the source
call .calcsource
;Set the size
push ax
mov al, 0x1
;Load
;Load a sector
mov ah, 0x2
int 0x13
;Load the loop counter and the source from the stack
pop cx
pop ax
;Set the next sector
add ax, 0x1
add bx, word [.sectorsize]
pop cx
loop .loadroot
;Load the next sector
loop .loadrootsector
;Search the root for the file entry
;Set DI to the root
mov di, buffer
;Initialise the search loop
;Set the number of root entries
mov cx, word [.rootentries]
;Set the entry pointer
mov ax, 0x0
;Store the loop counter in the stack
.search:
;Store CX in the stack
push cx
;Check for the file entry
mov si, .file
mov cx, 0xb
rep cmpsb
je .checksize
;Set DI to the next entry
;Set DI a t the next entry
add ax, 0x20
mov di, buffer
add di, ax
;Load CX from the stack
;Load the loop counter from the stack
pop cx
;Search the next entry
loop .search
;Set AL to 0x4, CX to 0x0, and print an error message
mov si, .filerrormsg
@ -227,11 +227,11 @@ mov ah, 0x2
int 0x21
mov al, 0x4
mov cx, 0x0
jmp .clearstack
jmp .done
;Check and store the file size
.checksize:
;Load CX from the stack
.checksize:
pop cx
;Check for files larger than 64 KiB
cmp word [di + 0x13], 0x0
@ -259,61 +259,58 @@ mov ah, 0x2
int 0x21
mov al, 0x8
mov cx, 0x0
jmp .clearstack
jmp .done
;Load the FAT
.loadfat:
;Store the first cluster of the file
mov ax, word [di + 0xf]
mov word [.cluster], ax
;Store the address of the first cluster
mov ax, [di + 0xf]
mov [.cluster], ax
;Set the source
mov ax, 0x1
mov ax, [.reservedsectors]
call .calcsource
;Set the destination
mov di, buffer
mov bx, di
mov bx, buffer
;Set the size
mov ax, [.sectorsperfat]
;Load
;Load the FAT
mov ah, 0x2
int 0x13
;Load the file
;Load a cluster
.loadcluster:
;Set the source
pop cx
pop bx
mov ax, word [.cluster]
sub ax, 0x2
mul byte [.clustersize]
add ax, bx
add ax, cx
push bx
push cx
add ax, [.datastart]
;Set the destination
mov bx, word [.pointer]
;Load a sector
;Set the size
mov ch, 0x0
mov cl, byte [.clustersize]
;Store the loop counter in the stack
.loadsector:
push cx
;Set the source
call .calcsource
;Set the size
push ax
mov al, 0x1
;Load
;Load a sector
mov ah, 0x2
int 0x13
pop ax
;Set the next sector
add ax, 0x1
add bx, word [.sectorsize]
;Load the loop counter from the stack
pop cx
;Load the next sector
loop .loadsector
;Calculate the next cluster
;Check if the cluster is even or odd
mov ax, [.cluster]
mov dx, 0x0
mov bx, 0x3
@ -322,23 +319,26 @@ mov bx, 0x2
div bx
mov si, buffer
add si, ax
mov ax, word [ds: si]
mov ax, word [si]
or dx, dx
jz .even
shr ax, 1
shr ax, 1
shr ax, 1
shr ax, 1
;If the cluster is odd shift out the first four bits
times 0x4 shr ax, 0x1
jmp .contcalc
;If the cluster is even mask out the final four bits
.even:
and ax, 0xfff
.contcalc:
mov word [.cluster], ax
;Check for the file end
cmp ax, 0xff8
jge .success
;Store the address of the next cluster
mov word [.cluster], ax
;Set the destination of the next cluster
mov ax, [.sectorsize]
mul word [.clustersize]
add word [.pointer], ax
;Load the next cluster
jmp .loadcluster
;Set AL to 0x0 and load the file size to CX if the load was succesful
@ -347,13 +347,9 @@ mov al, 0x0
mov cx, [.size]
;Clear the stack
.clearstack:
pop bx
pop bx
.done:
;Load the initial registers from the stack
;Load DI, SI, DX, and BX from the stack
pop di
pop si
pop dx
@ -362,18 +358,22 @@ pop bx
;Set AH to its initial value
mov ah, 0x0
;Return
iret
;Data
.drive db 0x0
.sectorsize dw 0x0 ;bytes
.clustersize db 0x0 ;sectors
.bootsectors dw 0x0
.reservedsectors dw 0x0
.fats db 0x0
.rootentries dw 0x0
.sectorsperfat dw 0x0
.sectorspertrack dw 0x0
.sides dw 0x0
.heads dw 0x0
.rootstart dw 0x0
.rootsectors dw 0x0
.datastart dw 0x0
.file times 0xb db 0x20
.size dw 0x0
.cluster dw 0x0
@ -383,8 +383,12 @@ iret
.filerrormsg db "File or command not found", 0x0
.sizerrormsg db "Not enough memory", 0x0
;***
;Check the file name and convert to upper case
.checkconv:
;Check for the string end, length limit, and invalid characters
;Check for the string end
cmp al, 0x0
je .load
@ -416,6 +420,8 @@ jmp .error
.contcheck3:
cmp al, 0x7c
je .error
;Check for lower case and convert it to upper case
;Check for lower case
cmp al, 0x61
jl .storech
@ -423,30 +429,50 @@ cmp al, 0x7a
jg .storech
;Convert lower to upper case
sub al, 0x20
.storech:
;Store the character
.storech:
stosb
;Decrease the counter
dec bl
;Return
ret
;***
;Calculate the source arguments for loading data from the disk
.calcsource:
;Store AX and BX in the stack
push ax
push bx
;Calculate the cylinder, head, and sector
;Store the logical sector in BX
mov bx, ax
;Calculate the sector
mov dx, 0x0
div word [.sectorspertrack]
add dl, 0x1
mov cl, dl
;Load the logical sector from BX
mov ax, bx
;Calculate the head and cylinder
mov dx, 0x0
div word [.sectorspertrack]
mov dx, 0x0
div word [.sides]
mov dh, dl
mov ch, al
div word [.heads]
mov dh, dl ;Head
mov ch, al ;Cylinder
;Load the drive number
mov dl, byte [.drive]
;Load BX and AX from the stack
pop bx
pop ax
mov dl, byte [.drive]
;Return
ret