Page 1 of 2

Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 6:47 am
by ich_will
Hey, first i will thank those people which check my code and help me to find the problem.

Now I have a problem with Fat12:

I search for a kernel on a Floppy (with my bootloader), when the kernel isn't found the kernel outs an error message.

Here are the functions I use (the read_sector is my own, the FindName is from someone in this Forum):

Code: Select all

;----------------------------------------------;
;------------- read_sector --------------------;
;----------------------------------------------;
;------ es = buffer address -------------------;
;------ bx = buffer offset  -------------------;
;------ cx = sector to read -------------------;
;------ dl = drive          -------------------;
;----------------------------------------------;
;------ for 1.44MB Floppys 80 Sectors ---------;
;----------------------------------------------;
read_sector:
   pusha
   push bx         ; save buffer offset

   ; compute the sector number:   sector_number%sectors_per_track + 1
   mov ax, cx      ; ax = sector number
   mov bl, 18      ; bl = number of sectors per track
   div bl         ; al = ax / bl
   mov cl, ah      ; cl = real sector number (cl is used by int 13)
   add cl, 1

   ; compute the head number: (sector_number/sector_per_track) just in ax mod number_of_heads
   ; and the track number:    (sector_number/sector_per_track) / number_of_heads

   xor ah, ah      ; del the rest of the div before
   mov bl, 2      ; bl = number of heads
   div bl         ; ah = rest of ( ax / bx ), al = ax / bx
   mov ch, al      ; ch = number of track
   mov dh, ah      ; dh = the head number (dh is used by int 13)

   pop bx         ; restore the buffer offset

   mov ax, cx      ; save cx in ax
   mov cx, 5      ; try to read the sector 5 times ;!!! overwrite the num of track and num of sec
   
    read_sector_next_try:
   pusha

   mov cx, ax      ; restore cx

   mov ah, 0x02      ; function number 2 (read from disk)
   mov al, 0x01       ; number of sectors to read
   int 0x13

   jnc load_ok      ; if all is ok return
   
   popa
   loop read_sector_next_try; else try once again if there is an error
   jmp error      ; if cx = 0 and the read operation always failed, halt

load_ok:
   popa
   popa
   ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Looks for a file with particular name ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Input:  DS:SI -> file name (11 chars) ;;
;;        ES:DI -> root directory array  ;;
;;        DX = number of root entries    ;;
;; Output: SI = cluster number           ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

FindName:
   cld
        mov    cx, 11
FindNameCycle:
        cmp    byte [es:di], ch
        je      FindNameFailed          ; end of root directory
        pusha
        repe    cmpsb
        popa
        je      FindNameFound
        add    di, 32
        dec    dx
        jnz    FindNameCycle          ; next root entry
FindNameFailed:
        mov ax, 0
   ret
FindNameFound:
;        mov si, [es:di+1Ah]        ; si = cluster no.
   mov ax, di
   add ax, 0x1A
   mov si, ax
   mov ax, 1
   ret
How you can see the FindName function returns the number of the Start Sector of the searched file in si.
If I try to read the sector returned in si:

mov cx, [si] ; cx = sector number

i got an empty buffer (where the sector is load in). Should I do other things before with the sector number ??? Additional I find out that if I read a the sector 33 (where the file begins, i checked this with an Image I make from the current disk) first a few zeros are loaded not directly the begin of the kernel.

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 7:54 am
by Pype.Clicker
keep in mind that sectors and clusters are *not* the same things. Especially, clusters are all in the 'data' section of the partition (thus no cluster numbers are allocated for the FAT copies nor for the original FAT). Check out official MS documentation about FATs on OSRC.

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 7:57 am
by aladdin

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Looks for a file with particular name ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Input:  DS:SI -> file name (11 chars) ;;
;;        ES:DI -> root directory array  ;;
;;        DX = number of root entries    ;;
;; Output: SI = cluster number          ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
have you initialised es:di with the correct root entry, and DX, with the number of entries ?

if you really need to read fat12 I've wrote a bootsector witch do that, all what you have to do is to modify, the kernel name and, the load address,
hear is the link to my OS http://h.world.free.fr/hw/xos/xossrc_13032004.tar.gz

the boot sector is in boot directory, you must use boot.asm and boot.inc.

comments are in french.

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 8:01 am
by ich_will
Thanks but I would learn all this things by myself. I don't want to copy some code, so that I don't understand it.

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 9:00 am
by Pype.Clicker
you may also experience problems while "'mov cx,[si]" if ds and es are not the same (as you saved the offset of a es-related data in a ds-bound register :)

Code: Select all

mov cx,[es:si]
might help ... using the video memory as buffer may also help you checking for free if you're working on the expected root directory data or on garbage ...

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 9:31 am
by Solar
ich_will wrote: Thanks but I would learn all this things by myself. I don't want to copy some code, so that I don't understand it.
But code known to be functioning can be an excellent resource for achieving such knowledge...

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 9:51 am
by ASHLEY4
Solar's right !.

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Looks for a file with particular name ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Input:  DS:SI -> file name (11 chars) ;;
;;         ES:DI -> root directory array ;;
;;         DX = number of root entries   ;;
;; Output: SI = cluster number           ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

FindName:
        mov     cx, 11
FindNameCycle:
        cmp     byte [es:di], ch
        je      FindNameFailed          ; end of root directory
        pusha
        repe    cmpsb
        popa
        je      FindNameFound
        add     di, 32
        dec     dx
        jnz     FindNameCycle           ; next root entry
FindNameFailed:
        jmp     ErrFind
FindNameFound:
        mov     si, [es:di+1Ah]         ; si = cluster no.

;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Load entire a program ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;

ReadNextCluster:
        call    ReadCluster
        cmp     si, 0FF8h
        jc      ReadNextCluster         ; if not End Of File

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Reads a FAT12 cluster      ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Inout:  ES:BX -> buffer    ;;
;;         SI = cluster no    ;;
;; Output: SI = next cluster  ;;
;;         ES:BX -> next addr ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ReadCluster:
        mov     bp, sp

        lea     ax, [si-2]
        xor     ch, ch
        mov     cl, [bpbSectorsPerCluster]
                ; cx = sector count
        mul     cx

        add     ax, [ss:bp+1*2]
        adc     dx, [ss:bp+2*2]
                ; dx:ax = LBA

        call    ReadSector

        mov     ax, [bpbBytesPerSector]
        shr     ax, 4                   ; ax = paragraphs per sector
        mul     cx                      ; ax = paragraphs read

        mov     cx, es
        add     cx, ax
        mov     es, cx                  ; es:bx updated

        mov     ax, 3
        mul     si
        shr     ax, 1
        xchg    ax, si                  ; si = cluster * 3 / 2

        push    ds
        mov     ds, [ss:bp+3*2]         ; ds = FAT segment
        mov     si, [ds:si]             ; si = next cluster
        pop     ds

        jnc     ReadClusterEven

        shr     si, 4

ReadClusterEven:
        and     si, 0FFFh               ; mask cluster value
ReadClusterDone:
        ret



ASHLEY4.

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 10:33 am
by ich_will
First my own bootloader seems to work complete but now it seems that the cpu hangs by a div instruction (marked in the b2oot.asm) it seems that the values are: 0x300 / 0x200. Its in the load_kernel function at the label found_kernel:.

The function ASHLEY4 posts is to big for my bootloader! Can someone help me to make it smaller (the bootloader)?

[attachment deleted by admin]

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 11:26 am
by ASHLEY4
HI
The code is from a 512 byte boot loader,to me you would be better off having a second stage loader that enters pmode.

Has for the DIV here are some notes:

If the divisor is a byte,its value must be greater than the left byte (AH) of the dividend,if the divisor is a word,its value must be greater than the left word(DX)of the dividend, If the devisor is a doubleword, its value must be greater than the left doubleword (EDX) of the dividend.

ASHLEY4.

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 11:50 am
by Candy
ich_will wrote:

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Looks for a file with particular name ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Input:  DS:SI -> file name (11 chars) ;;
;;        ES:DI -> root directory array  ;;
;;        DX = number of root entries    ;;
;; Output: SI = cluster number           ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

FindName:
   cld
        mov    cx, 11
FindNameCycle:
        cmp    byte [es:di], ch
        je      FindNameFailed          ; end of root directory
        pusha
        repe    cmpsb
        popa
        je      FindNameFound
        add    di, 32
        dec    dx
        jnz    FindNameCycle          ; next root entry
FindNameFailed:
        mov ax, 0
   ret
FindNameFound:
;        mov si, [es:di+1Ah]        ; si = cluster no.
   mov ax, di
   add ax, 0x1A
   mov si, ax
   mov ax, 1
   ret
Interesting part:

Code: Select all

;        mov si, [es:di+1Ah]        ; si = cluster no.
   mov ax, di
   add ax, 0x1A
   mov si, ax
You add 0x1A(26) to the cluster. They start at 0x21(33), and the first number is 0x2(2), so I would guess you'd have to add 0x1F(31). Now you're reading 0x1A+0x2 = 0x1C (26 + 2 = 28) ending you 5 sectors too early.

Might be something?

Code suggestion:
mov si, [es:di]
lea si, [si + byte 0x1F] ; allows you to add another register if you'd like, if you don't want that but want readable bootsector code (which is unlikely) try add si, byte 0x1F (saving you a byte!)

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 12:38 pm
by ich_will
Interesting part:
Code:
; mov si, [es:di+1Ah] ; si = cluster no.
mov ax, di
add ax, 0x1A
mov si, ax

You add 0x1A(26) to the cluster.
That isn't right, i add 0x1A to the value di containes. di containes the begin of the current directory entry else i can't move [si] to cx. (I check the value with an Image and print cx to the screen, they are the same)

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Wed Mar 17, 2004 12:57 pm
by Candy
ich_will wrote: That isn't right, i add 0x1A to the value di containes. di containes the begin of the current directory entry else i can't move [si] to cx. (I check the value with an Image and print cx to the screen, they are the same)
Ok, sorry. didn't read. Then you're not programming by contract, you say you return the cluster number, but you return an offset to the cluster number. Try replacing the mov si, ax with mov si, [es:di + 0x1A]. That at least fixes up that. (yes, this is modr/m syntax, and is legal in 16-bit mode).

I seem to miss the link between the two functions. Do you have it?

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Thu Mar 18, 2004 8:31 am
by ich_will
Ok, sorry this is an old comment I forget to update it after i have changed the function. Between which two functions? If you mean load_kernel and FindName, the FindName function is called in the next_sector loop after the call for read_sector.

Sorry if I missunderstod you but I'm german and I don't really know what you mean.

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Fri Mar 19, 2004 5:38 am
by ich_will
If I use a Second Stage bootloader, at which address should I load it? But this doesn't fix the problem.

Re:Yet Another Fat12 Problem YaFP 12 :-)

Posted: Fri Mar 19, 2004 8:20 am
by ich_will
Ok there was only a simple command missing to get all work:

xor dx,dx ; dx = 0

before i div. the numbers ( see the load_kernel function, label found_kernel)