Не в состоянии создать программу, которая перечисляет файлы на FAT (используя сборку) - PullRequest
0 голосов
/ 06 января 2020

Приведенный ниже код относится к программе, которая пытается вывести список файлов, расположенных на диске в формате FAT12.

Исходя из моего понимания c, я знаю, что для поиска файла сначала нужно посмотреть в каталог root, который находится в 19-м секторе на физическом диске. Этот каталог root имеет размер 14 секторов.

Существует определенная процедура, которую я использовал для вывода списка файлов в FAT12:

Шаг 1: подготовка ячейка памяти для загрузки каждого сектора каталога root, который является местоположением 0x0: 0x1000

Шаг 2: Определение размера каталога root - формуляр, который я использовал * Root_Directory_Size = (размер каждой записи * общее количество записей) / размер сектора *

Шаг 3: Определение начального номера сектора каталога root с использованием следующая формула = * (Количество жира * Размер каждого жира) + Зарезервированные сектора + скрытые сектора *

Шаг 4 : После вычисления вышеуказанного смещения, Затем программа начинает загружать каждый сектор в ячейку 0x0: 0x1000, в каждой записи программа проверяет следующие первые байты в каждой записи на пустую запись (0xe5), и 0x00 этот байт указывает, что либо root запись пуста, либо содержит удаленную файл

Итак, здесь проблема в том, что после всего этого я не получаю четный символ существующего файла на моем экране.

;This is a basic program which reads files on FAT12 and displays their names on the screen:

;This program is loaded into RAM by a bootloader not
;bios which I have managed to accomplish
[org 0x00]
[bits 16]

mov ax, 0x2000
mov ds, ax
mov es, ax

;since we ve been loaded by bootloader into memory obviously the value of dl which normally contains
;drive letter has been altered by bootloader program will skip this routine 
;and assume that our first boot drive is byte 0x80
;mov [drive_letter], dl

mov bx, file_name

mov si, bx  ; since bx points to the first entry of the root directory which contains the name of the file
mov di, buffer ; the location of root directory entry
add di, [next_section]
mov cx, 11 ; string length
cld

rep movsb

mov dx, buffer
mov cx, 14
call print_string

mov ah, 8   ; read disk parameter
mov dl, [drive_letter]
int 13h
jc read_error
and cx, 3fh
mov [SectorsPerTrack], cx
movzx dx, dh ; high word has been zeroed out
add dx, 1
mov [Head], dx

xor ax, ax
mov dl, [drive_letter]
int 13h
jc read_error

;#calculating the root start

mov ax, 19 ; root directory logical block begins at 19th sector

mov [root_start], ax ; now we have the starting sector of the root directory

;#load root director entry into memory sector by sector

mov cx, 14
mov ax, [root_start]
mov bx, 0x3000
mov es, bx
xor bx, bx

read_next_sector:
push cx
push ax   ; store lba address in the stack

xor bx, bx

call read_sectors

read_next_entry:
mov si, bx ; since bx points to the first entry of the root directory which contains the name of the file
mov di, buffer ; the location of root directory entry
add di, [next_section]
mov cx, 11 ; string length
cld

rep movsb

push bx
mov bx, [next_section]
add bx, 11
mov [next_section], bx
pop bx

add bx, 32 ; point to the next entry
cmp bx, 512 ; have we exceeded the sector size if yes excute the code below
jne read_next_entry

pop ax  ; retrive the current logical address from the stack
pop cx  ; retrive count from the stack
inc ax  ; load next sector when we loop back again
loop read_next_sector

mov ah, 0x0e
xor bh, bh
mov al, 'L'
int 10h

mov dx, buffer
mov cx, 1000

call print_string

jmp $


print_string:

push cx
out_char:
mov ah, 0x0e
mov bx, dx
mov al, [bx]
xor bh, bh
int 10h
inc dx
pop cx

loop print_string

ret

file_found:
mov ah, 0x0e
xor bh, bh
mov al, 'Z'
int 10h

hlt

jmp $

read_error:
mov ah, 0x0e
xor bh, bh
mov al, 'R'
int 10h

xor ah, ah
int 16h

int 19h

hlt 

jmp $

read_sectors:
push ax
push bx

xor dx, dx
mov bx, [SectorsPerTrack]; sectors per track
div bx

inc dx
mov cl, dl

xor dx, dx
mov bx, [Head] ; number of heads
div bx

mov ch, al
xchg dl, dh

;call other function routines
mov ah, 2
mov al, 1
pop bx
mov dl, [drive_letter]
int 13h
jc read_error
pop ax ; restore logical block address before exiting the read_sector routine

ret

drive_letter db 0x80   
SectorsPerTrack dw 0
Head dw 0

root_size dw 14
root_start dw 0

next_section dw 0

file_name db 'KERNEL  BIN', 0

buffer db 'No file found', 0
buffer1 times 1000 db 0

times 1024 db 0

Ответы [ 2 ]

1 голос
/ 09 января 2020

диск в формате FAT12.

; поскольку мы были загружены загрузчиком в память, очевидно, значение dl, которое обычно содержит; буква диска была изменена программой загрузчика, пропустит эту процедуру; предположим, что наш первый загрузочный диск имеет байт 0x80

Не будет ли это скорее кодом загрузочного диска для первого дисковода гибких дисков, поэтому 0x00?


Ваш код начинается с копирования 11-символьного имени файла KERNEL BIN через сообщение об ошибке Файл не найден . В результате получается 13-символьный текст KERNEL BINnd . Далее вы печатаете 14 символов на экране. Это все очень странно!


Проблема сегментации!

mov cx, 14
mov ax, [root_start]
mov bx, 0x3000
mov es, bx
xor bx, bx
read_next_sector:
pu sh cx
pu sh ax; сохранить адрес lba в стеке
xor bx, bx
call read_sectors
read_next_entry:
mov si, bx; поскольку bx указывает на первую запись в каталоге root, которая содержит имя файла
mov di, buffer ; расположение root записи каталога
add di, [next_section]
mov cx, 11; длина строки
cld
rep movsb

Этот окончательный movsb не будет перемещен в буфер , расположенный в сегменте 0x2000, поскольку регистр сегмента ES все еще указывает на сегмент 0x3000!

0 голосов
/ 14 января 2020

Это исправленный код, который при запуске будет выполняться в соответствии с ожидаемыми результатами. Эта программа будет отображать файлы и каталоги, хранящиеся в FAT12, сын программы проводника файлов

Вот код:

[org 0x4000] ; my bootloader loaded us at loc 0x00:0x4000, so this will be our starting loc of our code
[bits 16]

xor ax, ax
mov ds, ax
mov es, ax

mov bp, 0x9000
mov sp, bp       ; set the stack at the top of our code

%macro set_cursor 2

mov ah, 0x02
xor bh, bh
mov dl, %1
mov dh, %2
int 10h

%endmacro

%macro get_pos 0

mov ah, 03h
xor bh, bh
int 10h

%endmacro

mov ax, 0010h
int 10h

mov dl, 0
mov [drive_letter], dl

mov ah, 8
mov dl, [drive_letter]
int 13h
jc read_error
and cx, 3fh
mov [SectorsPerTrack], cx
movzx dx, dh ; high word has been zeroed out
add dx, 1
mov [Head], dx

xor ax, ax
mov dl, [drive_letter]
int 13h
jc read_error

;#calculating the root start

mov ax, 19 ; root directory logical block begins at 19th sector

mov [root_start], ax ; now we have the starting sector of the root directory

;#load root director entry into memory sector by sector

mov cx, 14
mov ax, [root_start]
xor bx, bx
mov es, bx

read_next_sector:
push cx
push ax   ; store lba address in the stack

mov bx, 0x5000
mov [entry_pointer], word 0
call read_sectors

check_if_empty:
mov al, [bx]
cmp al, 0xe5     ; thats a deleted file skip it
je read_next_entry

mov al, [bx]
cmp al, 0x00     ; there z no file here skip it
je read_next_entry

mov al, [bx+0x08]
cmp al, 'B'    ; wE WANT BINARY Files only
jne read_next_entry

mov al, [bx+0x0b]
cmp al, 0x0f
je read_next_entry     ; just skip the long file names

mov al, [bx+0x0b]
cmp al, 0x10           ; if it is a folder not a file skip it
je read_next_entry

mov al, [bx+0x0b]
cmp al, 0x08          ; if it is a volume label not a file skip it
je read_next_entry

mov al, [bx+0x0b]
cmp al, 0x04         ; if it is a volume label not a file skip it
je read_next_entry

mov al, [bx+0x0b]
cmp al, 0x02        ; if it is a volume label not a file skip it
je read_next_entry

inc word [no_files]    ; get number of files

mov si, bx  ; copy entry
mov di, existing_files ; the location of root directory entry
add di, [next_section]
mov cx, 32 ; copy the whole entry
cld

rep movsb

add [next_section], word 32      ; skip by size of each entry to avoid overriding

read_next_entry:
add [entry_pointer], word 32
add bx, 32 ; point to the next entry
cmp [entry_pointer], word 512 ; have we exceeded the sector size if yes execute the code below
jnae check_if_empty

pop ax  ; retrieve the current logical address from the stack
pop cx  ; retrieve count from the stack
inc ax  ; load next sector when we loop back again
loop read_next_sector

jmp _done

_done:

mov cx, [no_files]
mov [save_no], word cx

call update_menu

jmp show_h_item  ; default highlighted item on the menu

h_item:      ; highlight the desired item using up or down keys
xor ah, ah
int 16h

cmp ah, 0x48     ; up_key
je dec_index

cmp ah, 0x50
je inc_index    ; down key       

cmp ah, 0x1c    ; Enter key
je execute_file 

jmp h_item

inc_index:
add [file_pointer], word 32  ; points to the actual entry

jmp show_h_item

dec_index:
sub [file_pointer], word 32  ; points to the actual entry

jmp show_h_item

show_h_item:

call update_menu

mov dx, [file_pointer]
shr dx, 4 ; same as (file_pointer value / 32) * 2
xchg dl, dh

set_cursor 1, dh
mov dx, existing_files
add dx, [file_pointer]
mov cx, 11
mov bl, 4
call print_string

jmp h_item

execute_file:
pusha

mov bx, existing_files
add bx, [file_pointer]   ;  get details of the selected file entry
mov cx, [bx+0x1a]        ; get first cluster number of a file

xor ax, ax
mov es, ax               ; set es segment to zero

mov bx, 0x8000           ; load our file at location 0x00:0x4500

read_file_next_sector:
mov ax, cx               ; copy cluster number to ax - lba register
add ax, 31               ; align our cluster with the data area
push cx
call read_sectors
pop cx
add bx, 512

mov ax, cx
shr ax, 1
add ax, cx

mov si, ax               ; copy cluster number to si

mov dx, [0x1000+si]      ; get cluster number or end_of_file byte from fat table
test cx, 1
jnz .odd
and dx, 0fffh
jmp .done
.odd:
shr dx, 4

.done:
mov cx, dx
cmp cx, 0xff8
jl read_file_next_sector

mov ah, 0x0e
xor bh, bh
mov al, '='
mov bl, 15
int 10h

jmp 0x00:0x8000

jmp $

update_menu:

mov [pointer], word 0

mov cx, [save_no]
mov [no_files], word cx  ; will fix this when we return 

set_cursor  1, 0
mov dh, 0

.display_files1:

set_cursor 1, dh
mov dx, existing_files
add dx, [pointer]
mov cx, 11
mov bl, 15 ; white on text
call print_string

add [pointer], word 32   ; get the next entry
dec word [no_files]

get_pos
add dh, 2

cmp [no_files], word 0
jne .display_files1

ret

print_string:

sub dx, 1

.print_char:
push cx
inc dx
mov ah, 0x0e
mov si, dx
mov al, [si]
xor bh, bh

int 10h
pop cx
loop .print_char

ret

jmp $

read_error:
mov ah, 0x0e
xor bh, bh
mov al, 'R'
int 10h

xor ah, ah
int 16h

int 19h

hlt 

jmp $

read_sectors:
push ax
push bx

xor dx, dx
mov bx, [SectorsPerTrack]; sectors per track
div bx

inc dx
mov cl, dl

xor dx, dx
mov bx, [Head] ; number of heads
div bx

mov ch, al
xchg dl, dh

;call other function routines
mov ah, 2
mov al, 1
pop bx
mov dl, [drive_letter]
int 13h
jc read_error
pop ax ; restore logical block address before exiting the read_sector routine

ret

drive_letter db 0
SectorsPerTrack dw 0
Head dw 0

root_size dw 14
root_start dw 0
entry_pointer dw 0

next_section dw 0

next_sectionb dw 0

no_files dw 0

save_no dw 0

pointer dw 0

file_pointer dw 0

file_name db 'KERNEL  BIN', 0

existing_files:
...