无法创建一个列出FAT文件的程序(使用汇编)。

huangapple go评论63阅读模式
英文:

Failing to create a program which lists files on FAT (using assembly)

问题

以下是一个尝试列出位于FAT12格式磁盘上文件的程序的代码部分:

;这是一个基本程序,用于读取FAT12上的文件并在屏幕上显示它们的名称:

;这个程序是由引导加载程序加载到RAM中的,而不是
;我已经设法完成的BIOS
[org 0x00]
[bits 16]

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

;由于我们已经被引导加载程序加载到内存中,显然包含
;驱动器号的dl的值已经被引导加载程序修改,程序将跳过此例程
;并假设我们的第一个引导驱动器是0x80
;mov [drive_letter], dl

mov bx, file_name

mov si, bx  ;因为bx指向根目录的第一个条目,其中包含文件的名称
mov di, buffer ;根目录条目的位置
add di, [next_section]
mov cx, 11 ;字符串长度
cld

rep movsb

mov dx, buffer
mov cx, 14
call print_string

mov ah, 8   ;读取磁盘参数
mov dl, [drive_letter]
int 13h
jc read_error
and cx, 3fh
mov [SectorsPerTrack], cx
movzx dx, dh ;高字已经清零
add dx, 1
mov [Head], dx

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

;#计算根目录开始

mov ax, 19 ;根目录逻辑块从第19个扇区开始

mov [root_start], ax ;现在我们有了根目录的起始扇区

;#逐扇区加载根目录条目到内存

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

read_next_sector:
push cx
push ax   ;将lba地址存储在堆栈中

xor bx, bx

call read_sectors

read_next_entry:
mov si, bx ;因为bx指向根目录的第一个条目,其中包含文件的名称
mov di, buffer ;根目录条目的位置
add di, [next_section]
mov cx, 11 ;字符串长度
cld

rep movsb

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

add bx, 32 ;指向下一个条目
cmp bx, 512 ;我们是否超出了扇区大小,如果是,执行下面的代码
jne read_next_entry

pop ax  ;从堆栈中检索当前逻辑地址
pop cx  ;从堆栈中检索计数
inc ax  ;当我们再次循环回来时,加载下一个扇区
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];每个磁道的扇区数
div bx

inc dx
mov cl, dl

xor dx, dx
mov bx, [Head] ;磁头数
div bx

mov ch, al
xchg dl, dh

;调用其他函数例程
mov ah, 2
mov al, 1
pop bx
mov dl, [drive_letter]
int 13h
jc read_error
pop ax ;在退出read_sector例程之前恢复逻辑块地址

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

这是程序的代码部分,用于尝试列出FAT12格式磁盘上的文件。请注意,这只是代码的一部分,不包括完整的程序。

英文:

The code below is of a program which tries to list files located in as FAT12 formatted disk.

From my basic understanding I know that in order to find a file you need to look first in the root directory which is located at 19th sector in a physical disk. This root directory is 14 sectors in size.

There is a certain routine I've taken to list files in a FAT12:

Step 1: preparing a memory location to load each sector of the root
directory which is location 0x0:0x1000

Step 2: Determining the size of root directory - formular i've used
Root_Directory_Size = (size of each entry * total number of
entries) / size of sector

Step 3: Figuring out the starting sector number of the root directory
using the following formular = (Number of fat * Size of each
fat) + Reserved sectors + hidden sectors

Step 4: After calculating the above offset, the program then starts to
load each sector into location 0x0:0x1000, in each entry the
program checks for the following first bytes in each entry the
empty entry(0xe5) and the 0x00 this bytes indicates either root
entry is empty or contains a deleted file

So here the challenge is after doing all this stuff I'm not getting a even character of a existing file on my screen.

;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

答案1

得分: 1

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:
push cx
push ax ; 将LBA地址存储在堆栈中
xor bx, bx
call read_sectors
read_next_entry:
mov si, bx ; 由于bx指向根目录的第一个条目,其中包含文件的名称
mov di, buffer ; 根目录条目的位置
add di, [next_section]
mov cx, 11 ; 字符串长度
cld
rep movsb

这最后的movsb不会移动到位于段0x2000的buffer,因为ES段寄存器仍然指向0x3000段!

英文:

FAT12 formatted disk.

> ;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

Wouldn't this be sooner a boot drive code for the first floppy drive, so 0x00?


Your code begins with copying the 11-characters filename KERNEL BIN over the error message No file found. This produces the 13-characters text KERNEL BINnd. Hereafter you print 14 characters to the screen. This is all very strange!


A segmentation problem!

> 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

This final movsb wil not move to the buffer that is located in segment 0x2000 because the ES segment register is still pointing at the 0x3000 segment!

答案2

得分: 0

这是一段已经修正的代码,如果运行,将按预期的结果执行。这个程序将显示存储在FAT12中的文件和目录,是一个文件资源管理器程序的一部分。

以下是代码的一部分翻译:

[org 0x4000] ; 我的引导程序加载我们到位置0x00:0x4000,所以这将是我们代码的起始位置
[bits 16]
xor ax, ax
mov ds, ax
mov es, ax
mov bp, 0x9000
mov sp, bp ; 将栈设置在我们代码的顶部
%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 ; 高位被清零
add dx, 1
mov [Head], dx
xor ax, ax
mov dl, [drive_letter]
int 13h
jc read_error
;#计算根目录的起始位置
mov ax, 19 ; 根目录逻辑块从第19个扇区开始
mov [root_start], ax ; 现在我们有了根目录的起始扇区
;#逐扇区将根目录条目加载到内存
mov cx, 14
mov ax, [root_start]
xor bx, bx
mov es, bx
read_next_sector:
push cx
push ax ; 将LBA地址存储在堆栈中
mov bx, 0x5000
mov [entry_pointer], word 0
call read_sectors
check_if_empty:
mov al, [bx]
cmp al, 0xe5 ; 这是一个已删除的文件,跳过它
je read_next_entry
mov al, [bx]
cmp al, 0x00 ; 这里没有文件,跳过它
je read_next_entry
mov al, [bx+0x08]
cmp al, 'B' ; 我们只希望二进制文件
jne read_next_entry
mov al, [bx+0x0b]
cmp al, 0x0f
je read_next_entry ; 跳过长文件名
mov al, [bx+0x0b]
cmp al, 0x10 ; 如果是文件夹而不是文件,请跳过
je read_next_entry
mov al, [bx+0x0b]
cmp al, 0x08 ; 如果是卷标而不是文件,请跳过
je read_next_entry
mov al, [bx+0x0b]
cmp al, 0x04 ; 如果是卷标而不是文件,请跳过
je read_next_entry
mov al, [bx+0x0b]
cmp al, 0x02 ; 如果是卷标而不是文件,请跳过
je read_next_entry
inc word [no_files] ; 获取文件数量
mov si, bx ; 复制条目
mov di, existing_files ; 根目录条目的位置
add di, [next_section]
mov cx, 32 ; 复制整个条目
cld
rep movsb
add [next_section], word 32 ; 跳过每个条目的大小以避免覆盖
read_next_entry:
add [entry_pointer], word 32
add bx, 32 ; 指向下一个条目
cmp [entry_pointer], word 512 ; 我们是否超出了扇区大小,如果是,请执行下面的代码
jnae check_if_empty
pop ax ; 从堆栈中恢复当前逻辑地址
pop cx ; 从堆栈中恢复计数
inc ax ; 当我们再次循环时加载下一个扇区
loop read_next_sector
jmp _done
_done:
mov cx, [no_files]
mov [save_no], word cx
call update_menu
jmp show_h_item ; 菜单上默认高亮显示的项目
h_item: ; 使用上下键高亮所需的项目
xor ah, ah
int 16h
cmp ah, 0x48 ; 上键
je dec_index
cmp ah, 0x50 ; 下键
je inc_index ; 
cmp ah, 0x1c ; 回车键
je execute_file
jmp h_item
inc_index:
add [file_pointer], word 32 ; 指向实际条目
jmp show_h_item
dec_index:
sub [file_pointer], word 32 ; 指向实际条目
jmp show_h_item
show_h_item:
call update_menu
mov dx, [file_pointer]
shr dx, 4 ; 相当于(file_pointer值/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] ; 获取所选文件条目的详细信息
mov cx, [bx+0x1a] ; 获取文件的第一个簇号
xor ax, ax
mov es, ax ; 将es段设置为零
mov bx, 0x8000 ; 将我们的文件加载到位置0x00:0x4500
read_file_next_sector:
mov ax, cx ; 将簇号复制到ax - lba寄存器
add ax, 31 ; 将我们的簇与数据区对齐
push cx
call read_sectors
pop cx
add bx, 512
mov ax, cx
shr ax, 1
add ax, cx
mov si, ax ; 将簇号复制到si
mov dx, [0x1000+si] ; 从fat表中获取簇号或end_of_file字节
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,
<details>
<summary>英文:</summary>
This is a corrected code, that if runs will execute as per expected results. This program will display files and directories stored in FAT12, Son of a file explorer program 
Here is the code:
[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, &#39;B&#39;    ; 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, &#39;=&#39;
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, &#39;R&#39;
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 &#39;KERNEL  BIN&#39;, 0
existing_files:
</details>

huangapple
  • 本文由 发表于 2020年1月6日 21:44:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/59613218.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定