Page 1 of 1

file listing

Posted: Sun Oct 22, 2006 10:50 am
by joke
hi all,
i'm trying to implement a simple "ls" command in my real mode os ( it should print the filenames without dot extension, only the first 8 chars). but when i type in ls, i see my floppy drive working, then an empty line gets printed and after that my command line appears again. :cry:
heres my code for loading and (trying) to print a list of files in the root dir (its all FAT12)

Code: Select all

fat_read:
xor cx,cx 
xor dx,dx
mov ax,0x0020
mul word [Frootent]
div word [Fbps]

mov cx,ax
xor ax,ax
mov al, byte [Ffats]
mul word [Fspfat]
inc ax
mov word [datasect],ax 
call read_root
call write_root 
ret 
 
read_root:
cmp cx,0
je finished_reading
push ax
push bx
push cx
call lbachs
mov ah,0x02 
mov al,0x01
mov ch,byte [ABStrack]
mov cl,byte [ABSsector]
mov dh,byte [ABShead]
xor dl,dl
mov bx,0x500
int 13h
pop cx
pop bx
pop ax

dec cx
jmp read_root
finished_reading:
ret 

write_root:
mov ax, 0xE0
mov bx,0x500 
mov si,[es:bx]
mov cx,8
printloop:
push ax
mov ax,0E0Ah
int 10h
xor ax,ax
call printing
pop ax
dec ax
cmp ax,0
je finished_write
jmp printloop
finished_file:
push ax
mov ax,0E0Ah
int 10h
pop ax 
cmp ax,0
je finished_write		           
dec ax
mov cx,8 
add si,0x20
jmp printloop

finished_write:
jmp mainloop 
lbachs:
xor dx,dx
div word [Fspt]
inc dl
mov byte [ABSsector],dl
xor dx,dx
div word [Fheads]
mov byte [ABShead],dl
mov byte [ABStrack],al
ret		           

printing:
lodsb
cmp cx,0
je fileprintover
cmp al,0x00
je mainloop
mov ah,0Eh
mov bh,0Fh
xor bl,bl
int 10h 
jmp printing
fileprintover:
ret
and here are my vars used

Code: Select all

Fbps dw 0x200
Fspc db 0x01
Freserved db 0x01
Ffats db 0x02 
Frootent dw 0x00E0
Ftotalsec dw 0x0B40
Fspfat dw 0x0009
Fspt dw 0x0012
Fheads dw 0x0002
drive db 0
ABStrack db 0
ABShead db 0
ABSsector db 0
datasect dw 0
i'm not sure if im doing the correct things .. pointed si to 0x7C0:500 (where i hope i loaded my root dir correctly :D )

Thank you for your time

joke

Posted: Sun Oct 22, 2006 11:04 am
by Dex
Here is the fully working code from MiniDOS to do the same thing, it may help

Code: Select all

;====================================================;
; DirPrintFileNS.                                    ;
;====================================================;
DirPrintFile:
        pusha                               ; Save genral regs
        push  ds                            ; Save DS
        push  es                            ; Save ES
        mov   si,DirA                       ; Move the address of DirA in SI
        call  print                         ; call our print function
        mov   [cs:RdirFileCount],0x9000     ; Move the address of root dir into [cs:RdirFileCount]
        xor   si,si                         ; 0 SI
FileNamePrintLoop:
        xor   ax,ax                         ; 0 AX
        mov   ax,[cs:RdirFileCount]         ; Move whats in [cs:RdirFileCount] into AX
        mov   ds,ax                         ; Move whats in AX into DS
        add   si,32                         ; Add 32 to the address
        cmp   byte [ds:si],0xe5             ; Check for deleted file
        je    FileNamePrintLoop             ; If = loop
        cmp   byte [ds:si],'A'              ; Check for 'A'.
        je    FileNamePrintLoop             ; If = loop
        cmp   byte [ds:si],0x00             ; Check for 00
        je    DirSuccsess                   ; If = jume to exit
;====================================================;
; Print file/dir name.                               ;
;====================================================;
        pusha                               ; Save genral regs
        mov   cx,8                          ; Mov count 8
FilePrintLoop:
        lodsb                               ; load a letter into AL
        call  chrout                        ; Print it
        loop  FilePrintLoop                 ; loop 8 times
        mov   al,0x20                       ; print a space
        call  chrout
;====================================================;
; Print file exten.                                  ;
;====================================================;
        mov   cx,3                          ; Mov cx 3 for ext loop
FileExtenPrintLoop:
        lodsb                               ; Load al with letter
        call  chrout                        ; Print it
        loop  FileExtenPrintLoop            ; Loop 3 times.
;====================================================;
; Print files size in bytes.                         ;
;====================================================;
        push  cs                            ; Move CS on stack
        pop   ds                            ; Move CS into DS
        mov   si,nextline                   ; Move the address of nextline in SI
        call  print                         ; Call print function
        popa                                ; Restore regs
        jmp   FileNamePrintLoop             ; Jump to label FileNamePrintLoop
DirSuccsess:
        pop   es                            ; Restore ES
        pop   ds                            ; Restore DS
        popa                                ; Restore general regs
        clc                                 ; Do not set CF to 1
        ret                                 ; Return

DirError:
        pop  es                             ; Restore ES
        pop  ds                             ; Restore DS
        popa                                ; Restore general regs
        stc                                 ; Set CF to 1
        ret                                 ; Return
 ;----------------------------------------------------;
 ; Convert File Name.                                 ;
 ;----------------------------------------------------;
ConvertFileName:
        pusha                               ; Save genral regs
        push  es                            ; Save ES
        push  ds                            ; Save DS
 ;----------------------------------------------------;
 ; Convert command line Name to root name.            ;
 ;----------------------------------------------------;
        mov   si,CommandBuffer              ; Move the address of CommandBuffer in SI
        mov   di,RootConvertedFileName      ; Move the address of RootConvertedFileName in DI
        mov   cx,8                          ; Move count 8
ConvertCliFileName:
        cmp   byte [ds:si],'.'              ; Check for a '.'
        je    @f                            ; If = jump to label
        cld                                 ; Make movs prosess from left to right.
        movsb                               ; Move what ds:si points to, to what es:di points to
        dec   cx                            ; Decreass counter.
        jnz   ConvertCliFileName            ; If counter not 0, loop
        jmp   FinConertCliFname             ; If 0 jump label
@@:
        mov   al,0x20                       ; Move  ' ' into AL
        cld                                 ; Make movs prosess from left to right.
        rep   stosb                         ; Move what in AL, to the address es:di points to
FinConertCliFname:
        cmp   byte [ds:si],'.'              ; Check for a '.'
        jne   @f                            ; If not jump label
        inc   si                            ; If = add a byte to SI
@@:
        mov   cx,6                          ; Move 6 into count reg
        cld                                 ; Make movs prosess from left to right.
        rep   movsb                         ; Move what ds:si points to, to what es:di points to
        mov   di,RootConvertedFileName      ; Move the address of RootConvertedFileName in DI  
        add   di,8                          ; Point to the ext
        cmp   word[es:di],'DE'              ; Check for "DEx"
        je    ConvertCliFileNameError       ; If = jump error
        cmp   word[es:di],'BI'              ; Check for "BIn"
        je    ConvertCliFileNameError       ; If = jump error
        cmp   word[es:di],'MO'              ; Check for "MOd"
        je    ConvertCliFileNameError       ; If = jump error
        pop   ds                            ; Restore DS
        pop   es                            ; Restore ES
        popa                                ; Restore general regs
        clc                                 ; Do not set CF to 1
        ret                                 ; Return
ConvertCliFileNameError:
        pop   ds                            ; Restore DS
        pop   es                            ; Restore ES
        popa                                ; Restore general regs
        stc                                 ; Set CF to 1
        ret                                 ; Return
;====================================================;
; Data.                                              ;
;====================================================;
DirA:      db 10,13,"Directory of A:\ ",10,13,10,13,0
LabelDir:  db "<Dir>",10,13,0
nextline:  db 10,13,0
RdirFileCount dw 0
count  db 0
count2 dw 0


Posted: Sun Oct 22, 2006 4:42 pm
by Mikae
I noticed, that you can loose a part of root dir, cause 'div word [Fbps]' rounds down, so last sector of root dir, which may contain information will not be loaded.

Generally, algo should be such:

1. Calculate beginning of root directory: 'dirstart = size of fat * count of fat + reserved sectors + hidden sectors'. Now 'dirstart' points to beginning of root dir on disk.

2. Calculate size of root directory 'sizeofdir = (count of entries * size of entries + size of sector - 1) / size of sector'. 'sizeofdir' contains size of root directory in sectors.

3. Load 'sizeofdir' sectors beginning from 'dirstart' disk location.

4. Go through loaded sectors, printing file names until a file name found, which contains '0x0' in 1st byte.

In addition to Dex's example, also you can look at my FAT12 loader, posted here.

Posted: Tue Oct 24, 2006 8:29 am
by joke
ok, i changed my code using dex's code as a template and mikae's steps for the algorithm :wink: but still it doesn't work correctly :cry:

the output of the command for my test floppy is (it contains my kernel , osloader.com and a dir called .Trash-joke)
TRASH-~
<garbage> <garbage> <garbage>
<garbage> <garbage>
(the forum doesn't handle my spaces correctly :evil: the real program prints the first garbage row tabbed and the second garbage row double tabbed)
my new code is

Code: Select all

fat_read:
xor bx,bx
xor ax,ax
xor cx,cx 
xor bp,bp ; The base pointer contains the first root sector
mov ax,[Fspfat]
mov bx,2
mul bx
inc ax
mov bp,ax
xor ax,ax
mov ax,[Frootent]
mov bx,32
mul bx
add ax,[Fbps]
dec ax
div word [Fbps]
mov cx,ax 
xor bx,bx 
mov ax,bp ;let's start! :)
push es
call read_root
pop es
xor si,si
push ds
call list_it
pop ds
ret
read_root:
cmp cx,0
je finished_reading
push ax
push bx
push cx
call lbachs
mov ah,0x02 
mov al,0x01
mov ch,byte [ABStrack]
mov cl,byte [ABSsector]
mov dh,byte [ABShead]
xor dl,dl
mov bx,0x300 ; 0x300 is the segment we're loading the root dir
mov es,bx
xor bx,bx 
int 13h
pop cx
pop bx
pop ax

dec cx
jmp read_root
finished_reading:
ret 

lbachs:
xor dx,dx
div word [Fspt]
inc dl
mov byte [ABSsector],dl
xor dx,dx
div word [Fheads] 
mov byte [ABShead],dl 
mov byte [ABStrack],al 
ret                  

list_it:
xor ax,ax
mov ax,0x300
mov ds,ax
add si,32
cmp byte [ds:si],0xe5
je list_it
cmp byte [ds:si],'A'
je list_it 
cmp byte [ds:si],0x00
je list_finished
 
mov cx,8
list_file_loop:
lodsb
call chrout
loop list_file_loop
mov al,0x20
call chrout

mov cx,3
list_extension:
lodsb
call chrout
loop list_extension
jmp list_it

list_finished:
ret

chrout:
mov ah,0Eh
int 0x10
ret 
Thank you

Posted: Tue Oct 24, 2006 1:52 pm
by Cheery
Wow. That's so 'simple' I don't bother to even read it. :P

Posted: Tue Oct 24, 2006 2:47 pm
by Dex
Maybe you could try something like this in your code

Code: Select all

NotThisOne:    rb 32
LdTest0        db 'MY  FILETXT'
dirAttr        rb	1		; 0x0B
dirReserved    rb	1		; 0x0C
dirCreate10MS  rb	1		; 0x0D
dirCreateTime  rw	1		; 0x0E
dirCreateDate  rw	1		; 0x10
dirAccessDate  rw	1		; 0x12
dirClusterHigh rw	1		; 0x14
dirTime        rw	1		; 0x16
dirDate        rw	1		; 0x18
dirCluster     rw	1		; 0x1A
dirSize        rd	1		; 0x1C
LdTest0:       db   0
Load it to where your root dir is loaded (instead of your root dir) and see if it works.
It works then your root dir is not loaded to the right place.

Posted: Tue Oct 24, 2006 2:50 pm
by chase
Cheery wrote:Wow. That's so 'simple' I don't bother to even read it. :P
I'd say that it is simple. If he was trying to display file sizes or other extended information it would not be. Some people start OS development with boot sectors and assembly and others use grub and C.

My boot sector that I smashed some FAT12 root directory searching code into is at http://www.osdev.org/f12boot.asm

I'd suggest modifying ls to display the sectors it's trying to read. Then hexedit your floppy to see if your reading the right sectors.

(Most forums strip out white space unless you put your preformatted text in a

Code: Select all

 block)

Posted: Tue Oct 24, 2006 4:01 pm
by Mikae
joke, the first, why don't you increase buffer offset between readings? I think, that you have insert:

Code: Select all

xor bx,bx
int 13h
pop cx
pop bx
pop ax
[b]add bx, [Fbps][/b]

dec cx
jmp read_root
The second, you have to not print entries, which are parts of a long name. To do this, check 'attribute' field of every entry (relative offset is 0xB). If it equals 0xF (ATTR_LONG_NAME) -- just pass to the next entry.

Code: Select all

;Attributes of an entry in directory files.
ATTR_READ_ONLY = 0x1
ATTR_HIDDEN    = 0x2
ATTR_SYSTEM    = 0x4
ATTR_VOLUME_ID = 0x8
ATTR_DIRECTORY = 0x10
ATTR_ARCHIVE   = 0x20
ATTR_LONG_NAME = 0xF ;ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID
The third, give more meaningfull names to your constants! It is very hard to understand 'who is who' :). You can find a good example of naming (and BTW FAT specification itself) at http://download.microsoft.com/download/ ... gen103.doc