Assembly 以wierd偏移量读取ATA PIO磁盘
我正在编写一个内核,遇到了一个我不理解的错误,无法修复。我正在为它开发一个文件系统,因为我想快速实现pesistent存储。从磁盘读取的数据似乎不一致。磁盘的第一次读取以22字节的偏移量读取。我用Assembly 以wierd偏移量读取ATA PIO磁盘,assembly,x86,nasm,osdev,disk-io,Assembly,X86,Nasm,Osdev,Disk Io,我正在编写一个内核,遇到了一个我不理解的错误,无法修复。我正在为它开发一个文件系统,因为我想快速实现pesistent存储。从磁盘读取的数据似乎不一致。磁盘的第一次读取以22字节的偏移量读取。我用movedi和InfoSector-22解决了这个问题。第二次读取工作正常,但第三次读取全部0。 以前,当我在引导加载程序中预读文件系统信息扇区时,读取文件描述符会导致4字节的偏移量。为什么会发生这种情况 FS [ BITS 32 ] [ org 0x1500] ; Stuff for the f
movedi和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"
另外,如果您需要完整的引导加载程序代码,我可以提供,但它只在内存地址0x1500处加载磁盘的10个扇区,将堆栈指针设置为0x1500并切换到32位PM。您是否验证了映像本身是否正确?PS:可能与您当前的问题无关,但请避免使用16位内容,尤其是push-ax
和mov-ax,startup.HEXTABLE;mov dl,[eax]
(仅设置低16位,然后使用完整的32位寄存器进行寻址)。您好,我在开始时使用了您的代码,代码为全零LBA,对我来说效果很好。我可以在EDI中指定的地址将硬盘的第一个扇区放入RAM中。我使用QEMU和GDB对dump memory memory.bin 0x0000 0xffff
进行测试。我从硬盘上加载了引导扇区3次,效果很好。我用IRQ代替了投票。如果您愿意,我可以提供我的代码。您是否验证了图像本身是否正确?PS:可能与您当前的问题无关,但请避免使用16位内容,尤其是push-ax
和mov-ax,startup.HEXTABLE;mov dl,[eax]
(仅设置低16位,然后使用完整的32位寄存器进行寻址)。您好,我在开始时使用了您的代码,代码为全零LBA,对我来说效果很好。我可以在EDI中指定的地址将硬盘的第一个扇区放入RAM中。我使用QEMU和GDB对dump memory memory.bin 0x0000 0xffff
进行测试。我从硬盘上加载了引导扇区3次,效果很好。我用IRQ代替了投票。如果你愿意,我可以提供我的代码。