- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在修复我为加载自定义实模式 x86 内核 (SYS.BIN
) 而编写的引导加载程序。我设法让它读取根目录和 FAT,并从文件系统加载一个小型内核,所有这些都在引导扇区内。但是,我开始用更大的内核对其进行测试,似乎引导加载程序不会加载多个集群。我根据另一个类似的引导加载程序检查了我的代码,在加载多集群文件时,它似乎在有效地做同样的事情。主要区别在于我将第一个 FAT 加载到段 0x3000
中。和根目录成段0x3800
,以便内核可以访问它们。 (我完全搞砸了分割吗?)
我可能应该提一下,我正在通过使用 NASM 编译来测试它,编写结果 BOOT.BIN
文件到原始 32M 镜像的第一个扇区,将其挂载到循环设备上,复制 SYS.BIN
结束,并创建该循环设备的新镜像,然后我将其作为硬盘驱动器放入 QEMU。我确信它只是加载文件的第一个集群。
特别是,我相信导致问题的代码可能在这里:
.load_cluster:
mov si, msg_load_cluster
call print_str ; Print message
mov ax, word [cluster] ; Our cluster number
sub ax, 0x0002 ; Clusters begin at #2
mul byte [sectors_cluster] ; Multiply by number of sectors
mov dx, ax ; Save in DX
call calc_root_start ; Start of root directory
add ax, 0x20 ; Root directory is 32 sectors
add ax, dx ; Add to the number of sectors
call calc_chs_ls ; Convert this Logical sector to CHS
mov ax, 0x2000
mov es, ax ; Load the kernel into this segment
mov bx, word [buffer_pointer] ; At this offset
mov ah, 0x02 ; Read disk sectors
mov al, byte [sectors_cluster] ; 1 cluster
int 0x13 ; BIOS disk interrupt
jnc .next_cluster ; If no error, set up for the next cluster
call reset_disk ; Otherwise, reset the disk
mov ah, 0x02 ; Read disk sectors
mov al, byte [sectors_cluster] ; 1 cluster
int 0x13 ; Try again
jc reboot ; If failed again, reboot
.next_cluster:
mov ax, 0x3000
mov ds, ax ; Segment where the FAT is loaded
mov si, word [cluster] ; Our cluster number
shl si, 0x1 ; There are two bytes per entry in FAT16
mov ax, word [ds:si] ; DS:SI is pointing to the FAT entry
mov word [cluster], ax ; The entry contains our next cluster
cmp ax, 0xFFF8 ; Is this the end of the file?
mov ax, 0x0200
mul word [sectors_cluster]
add word [buffer_pointer], ax ; Advance pointer by one cluster
jb .load_cluster ; If not, load next cluster
这是我的完整代码,包括 BPB:
BITS 16
jmp strict short main
nop
; BIOS Parameter Block
; This was made to match up with the BPB of a blank 32M image formatted as FAT16.
OEM db "HDOSALPH" ; OEM ID
bytes_sector dw 0x0200 ; Number of bytes per sector (DO NOT CHANGE)
sectors_cluster db 0x04 ; Number of sectors per cluster
reserved dw 0x0001 ; Number of sectors reserved for bootsector
fats db 0x02 ; Number of FAT copies
root_entries dw 0x0200 ; Max number of root entries (DO NOT CHANGE)
sectors dw 0x0000 ; Number of sectors in volume (small)
media_type db 0xF8 ; Media descriptor
sectors_fat dw 0x0040 ; Number of sectors per FAT
sectors_track dw 0x0020 ; Number of sectors per Track (It's a LIE)
heads dw 0x0040 ; Number of heads (It's a LIE)
sectors_hidden dd 0x00000000 ; Number of hidden sectors
sectors_large dd 0x00010000 ; Number of sectors in volume (large)
drive_num db 0x80 ; Drive number
db 0x00 ; Reserved byte
extended_sig db 0x29 ; Next three fields are available
serial dd 0x688B221B ; Volume serial number
label db "NATE " ; Volume label
filesystem db "FAT16 " ; Volume filesystem type
; Main bootloader code
main:
mov ax, 0x07C0 ; Segment we're loaded at
mov ds, ax
add ax, 0x0020 ; 32-paragraph bootloader
mov ss, ax
mov sp, 0x1000 ; 4K stack
mov byte [boot_drive_num], dl ; Save boot drive number
mov ah, 0x08 ; Read disk geometry
int 0x13 ; BIOS disk interrupt
mov dl, dh
mov dh, 0x00
inc dl
mov word [heads], dx ; The true number of heads
mov ch, 0x00
and ch, 0x3F
mov word [sectors_track], cx ; The true number of sectors per track
.load_fat:
mov si, msg_load
call print_str ; Print message
mov ax, 0x3000
mov es, ax ; Load FAT into this segment
mov bx, 0x0000
mov ax, word [reserved] ; First sector of FAT 1
call calc_chs_ls ; Convert to CHS address
mov ax, word [sectors_fat] ; Read the entire FAT
mov ah, 0x02 ; Read disk sectors
int 0x13 ; BIOS disk interrupt
jnc .load_root ; If no error, load the root directory
jmp reboot ; Otherwise, reboot
.load_root:
mov si, msg_load
call print_str ; Print message
mov ax, 0x3800
mov es, ax ; Load root directory into this segment
call calc_root_start ; First sector of root directory
call calc_chs_ls ; Convert to CHS address
mov ah, 0x02 ; Read disk sectors
mov al, 0x20 ; Root directory is 32 sectors (512/512 = 1)
int 0x13 ; BIOS disk interrupt
jnc .search_init ; If no error, begin searching
call reset_disk ; Otherwise, reset the disk
mov ah, 0x02 ; Read disk sectors
mov al, 0x20 ; Root directory is 32 sectors (512/512 = 1)
int 0x13 ; BIOS disk interrupt
jc reboot ; If error, reboot
.search_init:
mov si, msg_search_root
call print_str ; Print message
mov ax, 0x07C0
mov ds, ax ; The segment we are loaded at
mov ax, 0x3800
mov es, ax ; The segment the root directory is loaded at
mov di, 0x0000 ; Offset 0
mov cx, word [root_entries] ; Number of entries to look through
.check_entry:
push cx ; Save this to stack
mov cx, 0x000B ; Compare the first 11 bytes
mov si, kern_filename ; This should be the filename
push di ; Save our location
repe cmpsb ; Compare!
pop di ; Restore our location
pop cx ; Restore the remaining entries
je .found_entry ; If the filenames are the same, we found the entry!
add di, 0x0020 ; Otherwise, move to next entry
loop .check_entry ; And repeat
jmp reboot_fatal ; If we've gone through everything, it's missing
.found_entry:
mov ax, word [es:di+0x1A]
mov word [cluster], ax ; The starting cluster number
.load_cluster:
mov si, msg_load_cluster
call print_str ; Print message
mov ax, word [cluster] ; Our cluster number
sub ax, 0x0002 ; Clusters begin at #2
mul byte [sectors_cluster] ; Multiply by number of sectors
mov dx, ax ; Save in DX
call calc_root_start ; Start of root directory
add ax, 0x20 ; Root directory is 32 sectors
add ax, dx ; Add to the number of sectors
call calc_chs_ls ; Convert this Logical sector to CHS
mov ax, 0x2000
mov es, ax ; Load the kernel into this segment
mov bx, word [buffer_pointer] ; At this offset
mov ah, 0x02 ; Read disk sectors
mov al, byte [sectors_cluster] ; 1 cluster
int 0x13 ; BIOS disk interrupt
jnc .next_cluster ; If no error, set up for the next cluster
call reset_disk ; Otherwise, reset the disk
mov ah, 0x02 ; Read disk sectors
mov al, byte [sectors_cluster] ; 1 cluster
int 0x13 ; Try again
jc reboot ; If failed again, reboot
.next_cluster:
mov ax, 0x3000
mov ds, ax ; Segment where the FAT is loaded
mov si, word [cluster] ; Our cluster number
shl si, 0x1 ; There are two bytes per entry in FAT16
mov ax, word [ds:si] ; DS:SI is pointing to the FAT entry
mov word [cluster], ax ; The entry contains our next cluster
cmp ax, 0xFFF8 ; Is this the end of the file?
mov ax, 0x0200
mul word [sectors_cluster]
add word [buffer_pointer], ax ; Advance pointer by one cluster
jb .load_cluster ; If not, load next cluster
.jump:
mov si, msg_ready
call print_str ; Otherwise, we are ready to jump!
mov ah, 0x00 ; Wait and read from keyboard
int 0x16 ; BIOS keyboard interrupt
mov dl, byte [boot_drive_num] ; Provide the drive number to the kernel
jmp 0x2000:0x0000 ; Jump!
; Calculation routines
calc_root_start: ; Calculate the first sector of the root directory
push dx ; Push register states to stack
mov ax, word [sectors_fat] ; Start with the number of sectors per FAT
mov dh, 0x00
mov dl, byte [fats]
mul dx ; Multiply by the number of FATs
add ax, word [reserved] ; Add the number of reserved sectors
pop dx ; Restore register states
ret ; Return to caller
calc_chs_ls: ; Setup Cylinder-Head-Sector from LBA (AX)
mov dx, 0x0000
div word [sectors_track]
mov cl, dl
inc cl ; Sector number
mov dx, 0x0000
div word [heads]
mov dh, dl ; The remainder is the head number
mov ch, al ; The quotient is the cylinder number
mov dl, byte [boot_drive_num] ; Drive number
ret ; Return to caller
; Other routines
print_str: ; Print string in SI
pusha ; Push register states to stack
mov ax, 0x07C0
mov ds, ax ; Segment in which we are loaded
mov ah, 0x0E ; Teletype output
mov bh, 0x00 ; Page 0
.char:
lodsb ; Load next character
cmp al, 0x00 ; Is it a NULL character?
je .end ; If so, we are done
int 0x10 ; Otherwise, BIOS VGA interrupt
jmp .char ; Repeat
.end:
mov ah, 0x03 ; Get cursor position
int 0x10 ; BIOS VGA interrupt
mov ah, 0x02 ; Set cursor position
inc dh ; One row down
mov dl, 0x00 ; Far left
int 0x10 ; BIOS VGA interrupt
popa ; Restore register states
ret ; Return to caller
reset_disk: ; Reset the disk
push ax ; Push register states to stack
mov si, msg_retrying
call print_str ; Print message
mov ah, 0x00 ; Reset disk
mov dl, byte [boot_drive_num]
int 0x13 ; BIOS disk interrupt
jc reboot_fatal ; If there was an error, reboot
pop ax ; Otherwise, restore register states
ret ; Return to caller
reboot_fatal: ; Display FATAL
mov si, msg_fatal
call print_str ; Print message
reboot: ; Prompt user to press a key and reboot
mov si, msg_reboot
call print_str ; Print message
mov si, msg_ready
call print_str ; Print message
mov ah, 0x00 ; Wait and read from keyboard
int 0x16 ; BIOS keyboard interrupt
int 0x19 ; Reboot
; Data
data:
cluster dw 0x0000
buffer_pointer dw 0x0000
boot_drive_num db 0x00
msg_retrying db "RE", 0x00
msg_fatal db "FATL", 0x00
msg_reboot db "X", 0x00
msg_search_root db "Srch", 0x00
msg_load_cluster db "Clstr", 0x00
msg_ready db "GO", 0x00
msg_load db "Press a key", 0x00
kern_filename db "SYS BIN"
times 510-($-$$) db 0x00 ; Pad remainder of bootsector with zeroes
boot_sig dw 0xAA55 ; Boot signature
在此先感谢您的帮助。
cluster
中的单词如
0x0003
在
.load_cluster
下, 但随后为
0x0000
在
.next_cluster
下几条指令后。
最佳答案
您的 mov ax, word [ds:si]
有一个不需要的 ds
段覆盖。
这也与您的变量问题有关,内存访问使用 ds
作为默认段。所以在 mov ax, 0x3000
之后\mov ds, ax
您不再访问原始变量。
您必须重置 ds
到 7C0h,因为你的加载器使用默认的 org 0
.您的 print_str
函数会重置 ds
像那样。但是 mov si, word [cluster]
以及 .next_cluster
中 FAT 字访问之间的所有内容直到 .jump
使用错误 ds
.要更正此问题,请更改您的代码,例如:
mov si, word [cluster]
shl si, 0x1
push ds
mov ax, 0x3000
mov ds, ax
mov ax, word [si]
pop ds
mov word [cluster], ax
另一个错误:
jb
就在
.jump
之前使用进位标志。但是,
cmp
中没有保留该标志。如你所愿,因为
add
当然(和
mul
可能)会覆盖进位标志。
mov ax, word [sectors_fat]
\mov ah, 0x02
第二次写入覆盖 ax
的上半部分所以这只适用于最多 255 个扇区的 FAT。int 13h
最多可以读取 255 个扇区。称呼。这对于不支持轨道交叉读取请求的 ROM-BIOS 来说可能是错误的。这就是为什么大多数加载程序一次加载一个扇区的原因。inc dl
\mov word [heads], dx
你应该使用 inc dx
.and ch, 0x3F
\mov word [sectors_track], cx
你打算使用 and cl, 3Fh
. mul dx
\add ax, word [reserved]
您应该添加 adc dx, 0
.int 13h
)。还有 LBA 接口(interface)(int 13h
扩展)。仅当 CHS 几何形状未知或适用于可访问扇区的范围太小时才需要。int 13h ah=08h
检索 CHS 几何。并非所有磁盘或 ROM-BIOS 都支持此调用。 (尤其是软盘可能不支持它,但那些也使用 FAT12 作为您不支持的文件系统。)关于assembly - FAT16 Bootloader 仅加载文件的第一个簇,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63144980/
我正在用 C 实现 FAT 文件系统。我遵循 microsoft 发布的规范 ( http://read.pudn.com/downloads77/ebook/294884/FAT32%20Spec%
我正在尝试从具有 armv6 和 armv7 架构的库中删除重复对象,即, $ lipo -info libx.a Architectures in the fat file: libx.a are:
我正在学习 FAT 文件系统以及如何计算 FAT 大小。现在,我有这个问题: 假设磁盘大小为 32 MB,块大小为 1 KB。计算FAT16的大小。 现在,我知道要计算它,我们将每个条目的位数乘以块数
我正在使用 Chan's FAT library这似乎提供了一个标准的 FAT 文件系统 API。 API 似乎没有直接提供列出给定目录中的所有文件。 列出可以访问标准 FAT API 的目录中所有文
我有一个数据库实现,每条记录一个文件,我有大约 10000 条记录。我正在尝试优化访问文件的性能,但我有点怀疑。 将文件拆分到文件夹中是否比将所有文件保存在单个文件夹中更好,以便快速访问文件?例如:文
我需要用 C 创建我自己的文件系统实现。我正计划创建一个类似于 FAT 系统的系统。我们得到一个大小为 10MB 的文件,它充当我们自己的“磁盘”。我知道 FAT 表存储簇号,根目录存储我们创建的每个
我正在尝试使用自定义引导加载程序开发一个小型操作系统。我在 OSDEV 方面有一点经验,但没有那么多......我的问题是第一阶段引导加载程序没有从磁盘加载秒数。这是 boot.asm 文件: org
最近在处理我的代码时,我注意到一些内存使用量显着增加,我在我的代码中看不到很多原因。所以我想知道是否有任何程序、技术或其他类型的工具可以扫描我的代码(Delphi)并为我估计哪些过程、函数和函数将是最
我知道这个问题已经被提出过多次,但我的目标与我在网上搜索到的内容略有不同。具体来说,我已经能够为 iPhone 构建静态库,但我能够构建的最终 fat 文件仅包含 arm 和 i386 架构(并且我不
我已经在几个上下文中阅读过“胖指针”这个术语,但我不确定它的确切含义以及它何时在 Rust 中使用。指针似乎是普通指针的两倍,但我不明白为什么。它似乎也与特征对象有关。 最佳答案 术语“胖指针”用于指
因此,我正在翻译示例代码,该示例代码说明如何使用Gradle从GroovyDSL到KotlinDSL创建胖子(我正在使用Gradle 5.3.1)。 我得到了GroovyDSL代码here: jar
我的 CPU 是小端字节序,文档告诉我它符合 FAT 规范的字节顺序。那么为什么我得到了 BS_jmpBoot 的有效地址(第一个扇区的字节 0-3),却没有得到 BPB_BytesPerSec 的有
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 6 年前。 Improve
我正在寻找一种方法来纯粹外部化 Spring boot 应用程序中的一些配置设置。例如:当双击 fat-JAR 文件时,它会从中加载配置,例如 myConfig.config,该文件与 fat-JAR
当涉及到使用 FAT 的文件系统时,这里出现了一个关于随机访问的直截了当的问题。 我看到了不同种类的图片/动画对 FAT 的不同解释,展示了不同的东西。我不明白如何在不通过文件一次的情况下进行随机访问
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 6 年前。 Improve
我正在编写一个嵌入式系统,其中我正在创建一个 USB 大容量存储设备驱动程序,该驱动程序使用 8MB RAM block 作为 FAT 文件系统。 尽管当时允许操作系统将我的 RAM 区域清零并格式化
这个问题在这里已经有了答案: ECMAScript 6 arrow function that returns an object (6 个答案) 关闭 5 年前。 是否可以将下面的代码写在一行中(
我正在尝试使用这些说明在 Windows 上安装无脂 crm http://guides.fatfreecrm.com/Setup-Microsoft-Windows.html 我正在安装mysql2
我已经在多个上下文中读到术语“胖指针”,但我不确定它的确切含义以及它在 Rust 中的使用时间。指针好像是普通指针的两倍大,但我不明白为什么。它似乎也与特征对象有关。 最佳答案 术语“胖指针”用于指代
我是一名优秀的程序员,十分优秀!