flat assembler
Message board for the users of flat assembler.

Index > OS Construction > set an entry in fat12(memory buffer problem)

Author
Thread Post new topic Reply to topic
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf
Hi,

I'm trying to set a new value to an entry in the FAT12 table,
but I couldn't do that,I think my problem is in the memory address
which I'm passing to my setcluster func,
here's my code:

Code:
;-----------------------------------------------;
;set an entry in the FAT table                  ;
;AX=cluster number,value=entry value            ;
;FAT table must be loaded at [0x100:0x50]       ;
;-----------------------------------------------;        
setcluster:
        push    cx 
        mov     cx, ax                  ;copy current cluster 
        mov     dx, ax                  ;copy current cluster 
        shr     dx, 0x0001              ;divide by two 
        add     cx, dx                  ;cx=offset into FAT                      
        mov     bx,0x50                 ;address of fat table 
        add     bx, cx                  ;index into FAT
        push    bx 
        mov     dx, WORD [es:bx]        ;read two bytes from FAT(old value in dx) 
        test    ax, 0x0001 
        jnz     .odd 
.eve:    
        mov     bx,dx 
        and     bx,0xF000               ;bx holds the old value  
        and     word[value],0x0FFF      ;next cluster 
         
        or      word[value],bx 
        mov     dx,word[value]
        pop     bx 
        mov     word [es:bx],dx         ;save the new value
        jmp     donexx 
.odd: 
        mov     bx,dx 
        and     bx,0x000F               ;bx holds the old value 
        shl     word[value],4           ;next_cluster 
        or      word[value],bx 
        mov     dx,word[value] 
        pop     bx
        mov     word [es:bx],dx         ;save the new value 
donexx:          
        pop     cx  
        ret
    


Code:
;loads FAT table into memory at [0x100:0x50]
load_fat:
        push    ax bx cx es
        mov     bx,0x100
        mov     es,bx
        mov     bx,0x50                 ;load fat table into memory (0x100:0x50)
        mov     ax,1                    ;the starting sector of fat table
        mov     cx,9                    ;fat table occupys 9 sectors
        call    read_sectors
        pop     es cx bx ax
        ret
    


and here's how I call setclustre:
Code:
        push    es
        mov     bx,0x100                ;fat table is loaded at (0x100:0x50)
        mov     es,bx  
        mov     cx,0xFFF                ;value which indecates that this cluster is the last in FAT chain
        mov     word[value],cx 
        mov     bx,0x50 
        call    setcluster     
        pop     es
    


would you please help me...
Post 24 Oct 2008, 13:30
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
abuashraf,

What is the value in ax before call setcluster?
Code:
        org     0x100
; Mark cluster 2 as bad
        mov     di, 2
        mov     ax, 0xFF7
        call    fat12_set_cluster
; Mark cluster 3 as bad
        mov     di, 3
        mov     ax, 0xFF7
        call    fat12_set_cluster
        ret

fat12_set_cluster:
;;; di - cluster number
;;; ax - next cluster
        mov     bx, di
        shr     bx, 1                   ;CF is set if cluster number odd
        lea     di, [FAT12+bx+di]
        mov     dx, 0xF000
        jnc     @f
        shl     ax, 4                   ;cluster number odd - adjust
        xor     dx, 0xF00F
@@:     and     dx, [di]
        or      dx, ax
        mov     [di], dx
        ret

FAT12   db      0xF0, 0xFF, 0xFF
        db      0x03, 0xF0, 0xFF        ;2 -> 3(EOF)    
Post 26 Oct 2008, 05:45
View user's profile Send private message Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf
Ax holds the value of the free cluster number,


Code:
        call    load_fat
        mov     word[cluster],3
        mov     ax,word[cluster] 
   x1:
        push    es
        mov     bx,0x100                ;fat table is loaded at (0x100:0x00)
        mov     es,bx    
        call    getcluster              ;get the next cluster of the file 
        pop     es
        cmp     [cluster], 0x00         ;test for end of file
        je      xxx
        inc     ax
        jmp     x1
xxx:
        mov     word[cluster],ax        ;save the cluster of the folder
        push    es
        mov     bx,0x100                ;fat table is loaded at (0x100:0x00)
        mov     es,bx  
        mov     cx,0xFFF                ;value which indecates that this cluster is the last in FAT chain
        mov     word[value],cx 
        mov     bx,0x50 
        call    setcluster     
        pop     es
    

Code:
;-- ---------------------------------------------;
;returns next cluster of a specific file        ;
;ax=starting cluster                            ;
;returns the cluster value  in [cluster]        ;
;assuming FAT is loaded at [100:0x50]           ;
;-----------------------------------------------;      
getcluster:
        push    cx dx bx    
        mov     cx, ax                  ;copy current cluster
        mov     dx, ax                  ;copy current cluster
        shr     dx, 0x0001              ;divide by two
        add     cx, dx                  ;sum for (3/2)
        mov     bx,0x50                 ;address of fat table into memory
        add     bx, cx                  ;index into FAT
        mov     dx, WORD [es:bx]           ;read two bytes from FAT(dx=old value)
        test    ax, 0x0001
        jnz     .odd_ctr          
 .even_ctr:     
        and     dx, 0000111111111111b    ;take low twelve bits
        jmp     .@.done        
 .odd_ctr:
        shr     dx, 0x0004 
 .@.done:        
        mov     WORD [cluster], dx      ;store new cluster        
        pop     bx dx cx
        ret        
            
Post 26 Oct 2008, 11:57
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
abuashraf,

Just wrapped your code into .Com and debugged it… Nothing wrong, it successfully found free cluster 0x11D on my scratch floppy and updated corresponding FAT12 entry at 0x50+0x1AB with EOC mark.

The only difference from your code was that mine set up es as ds+0x100 at the very beginning (100:50+1200 belongs to DOS, so I definitely will destroy something useful reading FAT there).
Post 29 Oct 2008, 12:26
View user's profile Send private message Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf
Thank you baldr very much for your help,and sorry I couldn't reply
faster because I was ill...any way,here's my whole make directory function,every time I execute it my os just hung,would you please take a
look at it and tell me if there's any thing wrong:
Code:
md:
        
        push    es  ds 
        call    ffentry                 ;gets first free entry in the root directory save it in BX
        push    bx                      

     
        call    load_fat                ;load fat table into memory at (0x100:0x50)
        mov     word[cluster],3
        mov     ax,word[cluster] 
   x1:
        push    es
        mov     bx,0x100                ;fat table is loaded at (0x100:0x00)
        mov     es,bx    
        call    getcluster              ;get the next cluster of the file 
        pop     es
        cmp     [cluster], 0x00         ;test for end of file
        je      xxx
        inc     ax
        jmp     x1
xxx:
        mov     word[cluster],ax        ;save the cluster of the folder
        push    es
        mov     bx,0x100                ;fat table is loaded at (0x100:0x00)
        mov     es,bx  
        mov     cx,0xFFF                ;value which indecates that this cluster is the last in FAT chain
        mov     word[value],cx 
        mov     bx,0x50 
        call    setcluster     
       
        mov     bx,0x100                ;write fat taable back to disk
        mov     es,bx
        mov     bx,0x50                 ;at table is loaded into memory at (0x100:0x50)
        mov     ax,1                    ;the starting sector of fat table
        mov     cx,9                    ;fat table occupys 9 sectors
        call    write_sectors           ;call BIOS
        
        pop     es                      
   xor     ax,ax                   ;zero ax
        mov     cx,ax                   ;zero cx
        mov     dx,ax                   ;zero dx
        mov     bx,0x500            ;set the buffer (es:bx)
        mov     es,bx                    ;es=0x500,bx=0x50
        mov     bx,0x50       
        mov     ax,19                   ;first sector of the root directory
        mov     cx,1                                    
        call    read_sectors            ;call bios     
        
        xor     ax,ax                   ;zero ax
        mov     bx,ax                   ;zero bx
        mov     si,ax                   ;zero di
        mov     bx,0x500 
        mov     ds,bx 
        mov     si,0x50                 ;si points to the buffer
        pop     bx                      ;get the first free entry
        add     si,bx                   
        or      byte [si+0x0b],0x10     ;make it directory 
        mov     ax,word[cluster]
        mov     word [si+26],ax         ;save the starting cluster
        mov     cx,11
        mov     di,cname
   empty:                               ;pad folder name with spaces
        mov     al,0x20
        mov     byte[di],al
        inc     di
        loop    empty
        call    getname                 ;input folder name(user input)
        mov     di,cname
        mov     cx,11
    cpyname:                            ;copy the folder name to the buffer 
        mov     al,byte[di]
        mov     byte[si],al
        inc     di
        inc     si
        loop    cpyname         
        
        mov     ax,0x500                ;write the buffer back to the disk
        mov     es,ax
        mov     ax,19
        mov     cx,1
        mov     bx,0x50
        call    write_sectors
        pop     ds es
        ret        
    


Thank you very much.
Post 01 Nov 2008, 10:07
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
abuashraf,

Hope you feel healthier today.

You may add some debug output in your code to see where it hung.

Stack seems to be balanced, but ffentry and getname functions are black boxes for me.

ffentry function returns displacement from 0x500:0x50 or offset into segment 0x500 in bx? I.e. free root directory entry is at 500:bx or at 0x500:0x50+bx (as following code expects)?

Are you sure that free root directory entry will be among the first 16? May be you should read entire root directory (14 sectors for standard 3.5" HD floppy).

This md function will definitely invalidate FAT12 file system on floppy: desynchronised FAT copies, garbage as contents of just created subdirectory.

And most of all: please clean up your code.

There are many unnecessary instructions that add only confusion, with comments like ;zero ax that are superfluous at least.

Carefully check segment registers' contents: in this fragment
Code:
        mov     bx,0x500 
        mov     ds,bx 
        mov     si,0x50                 ;si points to the buffer
        pop     bx                      ;get the first free entry
        add     si,bx                   
        or      byte [si+0x0b],0x10     ;make it directory 
        mov     ax,word[cluster]
        mov     word [si+26],ax         ;save the starting cluster
        mov     cx,11
        mov     di,cname
   empty:                               ;pad folder name with spaces
        mov     al,0x20
        mov     byte[di],al
        inc     di
        loop    empty
        call    getname                 ;input folder name(user input)
        mov     di,cname
        mov     cx,11
    cpyname:                            ;copy the folder name to the buffer 
        mov     al,byte[di]
        mov     byte[si],al
        inc     di
        inc     si
        loop    cpyname    
label cname refers to offset in segment 0x500?

Does getname ensure proper 8.3 padding? I.e.
Code:
0123456789a
NAME    EXT    
?

You must expect that only first byte of the free directory entry contains determined value, other 31 can be any garbage. Update all fields with meaningful values (or byte [si+0x0b],0x10 only sets "directory" bit, what about the rest?).
Post 03 Nov 2008, 20:48
View user's profile Send private message Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf
Hi baldr,thank you very much for your help,
and I'm really sorry about my confusing code,I'll try to make it more clean.

Also about the ffentry,here it is:

Code:
;-----------------------------------------------;
;returns first free entry of the root in bx     ;
;searchs only in the first sector               ;
;-----------------------------------------------;
ffentry:
        
        push    es ds
        mov     ax,19  
        mov     cx,1                    ;read one sector       
        mov     bx,0x200                ;set the buffer (es:bx)
        mov     es,bx                    ;es=0x200,bx=0x50   
        mov     bx,0x50     
        call    read_sectors        
        mov     bx,0x200 
        mov     ds,bx 
        mov     si,0x50                 ;si points to the buffer
        mov     cx,16                   ;number of root directory entries
  @@.loop: 
        inc     dx                      ;counts the entries,till we get free entry...
        test    byte[si+0x0b],1 shl 3   ;is it a volume label? 
        jnz     .next                  
        cmp     byte [si],0xE5          ;is it deleted file?
        je      @del                    ;yes,
        cmp     byte [si],0x00          ;is this the end of files/directories?
        je      @del                    ;yes,

        add     si,32                   ;go to the next entry
        jmp     @@.again                ;continue looping
     @del:
        mov     bx,dx                   ;save the first free entry number in bx
        jmp     @@.quit                 ;quit 
     .next:                             ;it is a volume label...
        add     si,32                   ;just go to the next entry         
    @@.again:   
        loop    @@.loop                 ;continue looping! 
        mov     bx,00                   ;no free space any more                    
@@.quit:
        dec     bx
        mov     ax,bx                   ;entry number * 32
        mov     bx,32
        mul     bx
        mov     bx,ax
        pop     ds es                
        ret
    

in this code I'm looking for the first free entry only in the
first sector of the root ,just for simplicity.

Also here's the getname :
Code:
;-----------------------------------------------;
;gets file/folder name from user                ;
;store the name in cname                        ;
;whith converting it to capital letters         ;
;-----------------------------------------------;        
getname:
        push    si di ax bx             ;push registers in the stack
        xor     bx,bx
        mov     di,bx
        mov     si,bx                   ;make si equal to zero
      mov     bx,cname
 .again:
        xor     ah,ah                   ;gets input from the user
        int     16h
        cmp     al,0x0D                 ;is it enter
        je      .enter
      cmp     al,0x20                 ;is it spacebar?
    je      .save                   ;yes,just save it...
        sub     al,20h                  ;convert the letter to to caps
  .save:
        mov     [bx + si],al            ;save the char in the buffer (cname)
        inc     si                      ;increament the pointer
        mov     ah,0Eh                  ;print out the char
        int     10h
        jmp     .again                  ;try to input more chars
  .enter:
        pop     bx ax di si             ;pop registers frmo the stack
        ret                             ;return!
    
Post 05 Nov 2008, 13:58
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
abuashraf,

It will help me to help you Wink if you provide complete sources. In order to compile the aforementioned test I have to write read_sectors by myself (it's not difficult, but my implementation almost surely is different from yours). write_sectors is just another example.

I will not distribute your sources or any part thereof, I swear. Wink

By the way, your code use global variables for parameter passing every now and then. My opinion is that parameter passing should be done only through function's parameters, everything else is a side effect and should be avoided at any cost.
Post 05 Nov 2008, 18:55
View user's profile Send private message Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf
Hi baldr,thank you very much...
here's a complete file with all the functions you need,I'v been trying to
solve my problem ,but till now I didn't find the bug Embarassed ,I hope you could find the problem.and end my tragedy Wink

Thanx.
Post 06 Nov 2008, 14:22
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.