Assembly 以wierd偏移量读取ATA PIO磁盘

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

我正在编写一个内核,遇到了一个我不理解的错误,无法修复。我正在为它开发一个文件系统,因为我想快速实现pesistent存储。从磁盘读取的数据似乎不一致。磁盘的第一次读取以22字节的偏移量读取。我用
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代替了投票。如果你愿意,我可以提供我的代码。