我正在编写一个内核,并且遇到了一个我不理解且无法修复的错误。我正在为它开发一个文件系统,因为我想快速实现持久存储。从磁盘读取似乎不一致。从磁盘的第一次读取以 22 字节偏移量读取。我已经解决了它mov edi, InfoSector-22
。第二次读取工作正常,但第三次读取全部为 0。之前,当我在引导加载程序中预读取文件系统信息扇区时,文件描述符的读取导致 4 字节偏移。为什么会这样?
FS
[ BITS 32 ]
[ org 0x1500]
; Stuff for the filesystem
LoadingSectors:
mov edi, DescriptorSectorPos
mov esi, DescriptorsStart
jmp startup
ATA1Port equ 0x1F0
ATAinit:
pusha
mov dx, ATA1Port+7
in al, dx
cmp al, 0xff
je .noDisk
mov dx, ATA1Port+6
mov al, 0xE0
out dx, al
inc dx
mov cx, 5
rep in al, dx
mov dx, ATA1Port+5
mov al, 0
out dx, al
dec dx
out dx, al
dec dx
out dx, al
dec dx
out dx, al
dec dx
out dx, al
mov dx, ATA1Port+7
mov al, 0xEC
out dx, al
in al, dx
cmp al, 0
jne .diskFound
test al, 0
jnz .packetedATA
.noDisk:
cli
hlt
.packetedATA:
jmp .noDisk
.diskFound:
in al, dx
test al, 7
jnz .diskFound
mov dx, ATA1Port+4
in al, dx
cmp al, 0
jne .packetedATA
mov dx, ATA1Port+7
cmp al, 0
jne .packetedATA
call IOWait
mov dx, ATA1Port
mov ax, 0x10
mov es, ax
mov di, 0x7c00
mov ecx, 253
rep insw
mov dx, ATA1Port+7
in al, dx
popa
ret
ATAWriteSector: ; esi - source location, al - sector location.
pusha
push ax
mov dx, ATA1Port+2
mov al, 1
out dx, al
inc dx
pop ax
out dx, al
inc dx
mov al, 0
out dx, al
inc dx
out dx, al
mov dx, ATA1Port+7
mov al, 30h
out dx, al
call IOWait
mov dx, ATA1Port
mov ecx, 256
rep outsw
popa
ret
ATAWriteSectors: ; esi - source location, cx - # of sectors to write, ax - starting sector location.
pusha
.loop:
cmp cx, 0
je .end
call ATAWriteSector
add edi, 200h
dec cx
jmp .loop
.end:
popa
ret
ATAReadSector: ; edi - buffer location, ax - sector location.
pusha
push ax
mov dx, ATA1Port+2
mov al, 1
out dx, al
inc dx
pop ax
out dx, al
inc dx
mov al, 0
out dx, al
inc dx
out dx, al
mov dx, ATA1Port+7
mov al, 20h
out dx, al
call IOWait
mov ecx, 256
mov dx, ATA1Port
rep insw
test al, 0x21
jz .fail
popa
ret
.fail:
mov dx, ATA1Port+1
in al, dx
mov edi, VIDMEM
shr al, 4
mov dl, al
push dx
mov ax, startup.HEXTABLE
add ax, dx
mov dl, [eax]
mov ah, 0x70
mov al, dl
mov [edi], ax
add edi, 2
pop dx
shl dl, 4
mov al, [esi]
sub al, dl
mov dl, al
mov ax, startup.HEXTABLE
add ax, dx
mov dl, [eax]
mov ah, 0x70
mov al, dl
mov [edi], ax
hlt
ATAReadSectors: ; edi - buffer location, cx - # of sectors to read, ax - starting sector location.
pusha
.loop:
cmp cx, 0
je .end
call ATAReadSector
add edi, 200h
dec cx
inc ax
jmp .loop
.end:
popa
ret
times 2*512-($-$$) db 0
LoadFile: ; esi - location of file name to search for, edi - buffer for file.
pusha
push edi
mov edi, DescriptorSectorPos+3
xor ecx, ecx
.loop:
cmp byte [esi], 0
je .end
mov al, [edi]
cmp [esi], al
je .correct
sub esi, ecx
sub edi, ecx
add esi, 46
xor ecx, ecx
jmp .loop
.correct:
inc esi
inc edi
inc ecx
jmp .loop
.end:
sub edi, ecx
sub edi, 2
xor ecx, ecx
mov al, [edi]
inc edi
mov cl, [edi]
pop edi
call ATAReadSectors
popa
ret
IOWait:
pusha
mov dx, ATA1Port+7
.loop:
in al, dx
test al, 0
jnz ATAinit.noDisk
test al, 3
jz IOWait.loop
popa
ret
startup:
InfoSector equ 0x2A00
VIDMEM equ 0xB8000
DescriptorsStart equ 0x2C00
DataStart equ 0x2E00
call ATAinit
mov edi, InfoSector-22
mov ax, 11
call ATAReadSector
mov edi, DescriptorsStart
mov ax, 12
call ATAReadSector
mov edi, InfoSector
cmp dword [edi], 0xEADFAAFF
jne .fail
call .success1
add edi, 4
mov ax, [edi]
mov [.SectorCount], ax
add edi, 2
xor eax, eax
mov ax, [edi]
add ax, DescriptorsStart
mov edi, eax
mov al, [edi]
cmp al, 1
jne .fail
call .success2
mov esi, .kernelfile
mov edi, DataStart
call LoadFile
cmp dword [edi], 0
je .fail
call .success3
jmp DataStart
.success1:
pusha
mov al, '1'
mov ah, 0x2F
mov [VIDMEM+2], ax
popa
ret
.success2:
pusha
mov al, '2'
mov ah, 0x2F
mov [VIDMEM+4], ax
popa
ret
.success3:
pusha
mov al, '3'
mov ah, 0x2F
mov [VIDMEM+6], ax
popa
ret
.fail:
mov esi, edi
mov al, 'F'
mov ah, 0x4C
mov edi, VIDMEM
mov [edi], ax
xor ecx, ecx
xor edx, edx
xor eax, eax
add edi, 4
.fail.loop:
add edi, 2
inc cx
mov al, [esi]
shr al, 4
mov dl, al
push dx
mov ax, .HEXTABLE
add ax, dx
mov dl, [eax]
mov ah, 0x70
mov al, dl
mov [edi], ax
add edi, 2
pop dx
shl dl, 4
mov al, [esi]
sub al, dl
mov dl, al
mov ax, .HEXTABLE
add ax, dx
mov dl, [eax]
mov ah, 0x70
mov al, dl
mov [edi], ax
inc esi
cmp cx, 512
jne .fail.loop
.halt:
hlt
jmp .halt
.SectorCount: dw 0x0000
.HEXTABLE: db '0123456789ABCDEF'
.kernelfile: db 'Kernel.bin', 0
times 10*512-($-$$) db 0
InfoSectorPos:
dd 0xEADFAAFF
dw 0x0006
dw 0x0000
times 512-($-InfoSectorPos) db 0
DescriptorSectorPos:
.kernel.bin:
db 0x01
db 0x13
db 0x10
db 'Kernel.bin'
times 43-($-.kernel.bin) db 0
.VideoFunctions.lbin:
db 0x02
db 0x1C
db 0x10
db 'VideoFunctions.lbin'
times 43-($-.VideoFunctions.lbin) db 0
times 512-($-DescriptorSectorPos) db 0
DataPos:
%include "Filesystem/Kernel.bin.asm"
%include "Filesystem/VideoFunctions.lbin.asm"
PS 如果您需要完整的引导加载程序代码,我可以提供它,但它只在内存地址 0x1500 处加载磁盘的 10 个扇区,将堆栈指针设置为 0x1500 并切换到 32 位 PM。