【问题标题】:Failing to create a program which lists files on FAT (using assembly)未能创建列出 FAT 文件的程序(使用程序集)
【发布时间】:2020-04-24 01:30:20
【问题描述】:

下面的代码是一个程序,它试图列出位于 FAT12 格式磁盘中的文件。

根据我的基本理解,我知道要找到一个文件,您需要首先查看位于物理磁盘第 19 个扇区的根目录。此根目录大小为 14 个扇区。

我已经采取了某种例程来列出 FAT12 中的文件:

步骤 1: 准备一个内存位置来加载根的每个扇区 位置 0x0:0x1000 的目录

第 2 步: 确定根目录的大小 - 我使用的公式 *Root_Directory_Size = (每个条目的大小 * 总数 条目)/扇区大小*

第三步:找出根目录的起始扇区号 使用以下公式 = *(脂肪数量 * 每个的大小 fat) + 保留扇区 + 隐藏扇区*

第四步:计算出上述偏移量后,程序开始 将每个扇区加载到位置 0x0:0x1000,在每个条目中 程序检查每个条目中的以下第一个字节 空条目(0xe5)和 0x00 这个字节表示根 条目为空或包含已删除的文件

所以这里的挑战是在完成所有这些事情之后,我的屏幕上没有现有文件的偶数字符。

;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

【问题讨论】:

  • Edit 包含您遇到的问题的详细信息的问题。

标签: assembly nasm x86-16 fat


【解决方案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
读取下一个扇区:
推送 cx
推斧;将 lba 地址存储在堆栈中
xor bx, bx
调用 read_sectors
read_next_entry:
移动 si, bx ;因为 bx 指向包含文件名的根目录的第一个条目
mov di, 缓冲区 ;根目录入口的位置
添加 di, [next_section]
移动 cx, 11 ;字符串长度
cld
rep movsb

这个最终的movsb 不会移动到位于段 0x2000 中的 缓冲区,因为 ES 段寄存器仍然指向 0x3000 段!

【讨论】:

  • 非常感谢你,我已经更正了代码,程序现在按照预期结果运行
【解决方案2】:

这是一个更正的代码,如果运行将按预期结果执行。该程序将显示存储在 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:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多