Right, i know its been quite some time since I last posted here, I just started my first year on a Computer Science course at Kings and its honestly a lot more work than anticipated so my little OS project has been laying neglected for quite some time. But, i think i figured out what the issue was after looking over the code with some fresh eyes. So, first things first, I use this piece of code:
Code: Select all
FATFindEntry: ;0001)
pusha ;0002) Preserver all the registers before the function
mov si, FileName ;0003) Move the name of the file into source index for comparison
mov bx, ROOTDIR ;0004) move the memory address into the bx register
mov ch, 0x0A ;0005) Counter for the letters in an entry
mov cl, 0xE1 ;0006) Counter for the number of file entries
push bx ;0007) Preserve the starting address of the file name
.FATFECompareString: ;0008)
mov ah, [si] ;0009) get a byte, the first character, from the source index
mov al, [bx] ;0010) get a byte, the first character in the root directory, from the memory address
inc si ;0011) increment the source index for the next character of the file name
inc bx ;0012) increment the memory address for the next letter u=in the root directory
call WriteHex ;0000) DEBUGGING Write the letter from the FAT to the console co i can see what byte we are on.
push ax ;0000) DEBUGGING
mov al, ah ;0000) DEBUGGING
call WriteHex ;0000) DEBUGGING
pop ax ;0000) DEBUGGING
cmp al, ah ;0013) compare the two values.
jne .FATFEWrongEntry ;0014) if they're not the same, we have the wrong entry so we jump out of the loop
cmp ch, 0x00 ;0015) check to see if we have reached the last character in the file name
je .FATFERightEntry ;0016) if it is, we have found the file and jump out of the loop and start getting the block of the first sector
dec ch ;0017) if not, we mark of the current letter by taking one off the counter
jmp .FATFECompareString ;0018) then we repeat the loop that compares the filename with the entry in the root directory.
.FATFEWrongEntry: ;0019)
cmp cl, 0x00 ;0020) Check to see if we have checked all the entries in the root directory
je .FATFEEntryNotFound ;0021) if we have, then we haven't found the entry on the disk so we jump out of the loop
dec cl ;0022) if we haven't looked at allthe entries, we mark the one we just checked off the list
mov ch, 0x0A ;0023) reset the counter for checking the entry in the root directory.
pop bx ;0024)
add bx, 0x20 ;0025)
push bx ;0026)
mov si, FileName ;0027)
jmp .FATFECompareString ;0028)
.FATFEEntryNotFound: ;0029)
pop bx ;0030)
mov di, FATFEStatus ;0031)
mov al, 0x00 ;0032)
stosb ;0033)
popa ;0034)
ret ;0035)
.FATFERightEntry: ;0036)
pop bx ;0037)
add bx, 0x1A ;0038)
mov al, [bx] ;0039)
mov ah, [bx + 1] ;0040)
mov di, FATOffSet ;0041)
stosw ;0042)
add ax, 0x001F ;0043)This converts the next sector to LBA
mov di, NxtSect ;0044)
stosw ;0045)
mov al, 0x01 ;0046)
mov di, FATFEStatus ;0047)
stosb ;0048)
popa ;0049)
ret ;0050)
to find the file inside the FAT table. The function is called with SI being set by what ever is calling this function. ROOTDIR is a variable which stores the location of the FAT table, which in my case is always 0x9000, meaning every every entry starts at every 0x0020 interval. As such i know that every Sector value is stored at bytes 0x001A and 0x001B respectively. I know its confusing but it works for me. Now, every time i call this function, the file is found, which is good. This works, however, the issue arose whenever i tried loading the actual data. Whenever i calculated the CHS from the LBA i got some absurd number and as a result I got the Error code 0x01 when calling interrupt 0x13, invalid command. After spending hours going through each individual byte of the FAT making sure that i got them all correct when finding the file, i deduced the issue must be with my LBA to CHS calculations, which is done here:
Code: Select all
ConvertLBAToCHS: ;0049)
pusha ;0050)Preserve all the registers by moving them to the stack
xor dx, dx ;0000) Zero out the dx register
cld ;0000) clear the direction flag
mov si, NxtSect ;0051)Set the source index to the memory location of the next LBA
mov ax, FIHPT ;0052)
mov bx, FISPT ;0053)
mul bx ;0054)
mov bx, ax ;0055)
lodsw ;0056)
div bx ;0057)
mov di, CylinderTMP ;0058)
stosw ;0059) the lower ten bits of AX is the cylinder the data is stored on
mov ax, dx ;0060) take the remainder from the divide operation and store it in ax
mov bx, FISPT ;0061)
div bx ;0062)
mov di, Head ;0063)
stosb ;0064)AL should be the head of the disk.
inc dx
mov ax, dx
mov di, SectorTMP
mov si, CylinderTMP
xor ax, ax
xor bx, bx
lodsw
mov word ax, [si]
shr ax, 6
mov di, SectorTMP
mov bx, ax
lodsw
shr ax, 10
shl ax, 10
or ax, bx
mov si, CylinderSector
stosw
popa
ret
I know this is long and very inefficient, but at the time I was writing this code, I just wanted it to work, and after spending hours looking through this code, and writing it out by hand to make sure all the maths was correct, I couldn't find an issue here either. So I took a brake and focused on uni work, but then I had the urge to come back again tonight to see if I can fix the issue, and I instantly notice in the LBA calculations, I miss a very important step. I don't clear the upper four bits. Instead of using a 12 bit address, i get a 16 bit address. This extra four bits at the start or end of the sector number must have been throwing off my entire calculations. I haven't tested this yet, its half one in the morning so I need sleep, i just wanted to post this here so I can one, reference this when I inevitably forget what was wrong and break down in tears, and to secondly, get your guys opinion on this. Can you guys spot any other issues in my code? or does that seem to fix it? Ill post another update when I write the code to check if i need to clear the upper four bits of the cluster number or the lower and all that fun stuff. Its at this point in time I really wish i used FAT16 instead of FAT12.