2

我有一个引导扇区,用于从软盘映像加载一个名为 BOOT.BIN 的文件。但是我不知道如何从文件中读取多个扇区。FAT 12 位于 0x10000。BOOT.BIN 文件将放在 0x40000。编码:

foundfile:
        mov word ax,[es:di+0x0f]
        push ax ;save file cluster
        ;now to parse the fat
        mov dx,second_boot_segment
        mov es,dx
        xor bx,bx
        
        read_file_sector:
            pop ax ;retrieve file cluster
            mov byte dl,[drive_num]
            mov cx,ax
            add cx,31
            push ax ;save cluster number
            mov al,1
            call readdisk
            pop ax ;retrieve cluster number
            
        find_clusters:
            push es
            push bx
            mov cx,fat_segment
            mov es,cx
            xor bx,bx
            xor dx,dx
            mov cx,3
            mul cx
            shr ax,1
            ;ax is now (clusternum*3)/2
            test ax,1
            
            jz short evennum
            
            oddnum:
                shr ax,4
                jmp short find_clusters_continued
                
            evennum:
                and ax,0x0fff
                
            find_clusters_continued:
                cmp ax,0x0ff0
                jae short finishedread ;read all of file
                
                mov word ax,[es:bx]
                
                pop bx
                pop es
                
                push ax
                
                add bx,512 ;next sector
                jmp short read_file_sector
                
        finishedread:
            jmp second_boot_segment:0000
            jmp fatalerror

==================================================== =======================readdisk等功能:

readdisk: ;input: es:bx for where disk data is stored, al for sectors, cx for lba, drive_num for drive output: carry flag on error, ah is return type, al is the number of sectors read
        push dx ;save dx
        call lbatochs
        mov byte dl,[drive_num]
        mov ah,2
        int 13h
        jc short resetdisk
        mov byte dl,[drive_num]
        pop dx ;restore dx
        ret
        
        resetdisk:
            push ax
            mov ah,0
            int 13h
            jc short fatalerror
            pop ax
            jmp short readdisk

    fatalerror:
        mov ax,0x0003 ;ah = 0 al = 3
        int 10h
        
        mov si,boot_error
        mov ax,0xb800
        mov es,ax
        xor bx,bx
        cld
        
        printloop:
            lodsb
            or al,al ;is the last character read
            jz short infloop
            mov ah,0x0f ;color
            mov word [es:bx],ax ;write to vram
            add bl,2 ;as long a the text is less than 256 bytes this works
            jmp short printloop
    
    lbatochs: ;input: cx for lba, output: cx for cylinder and sector, and dh for head
        push ax ;save for later
        push bx ;save bx
        
        ;find temp variable
        xor dx,dx
        mov ax,cx ;ax now has lba
        push ax ;save lba
        mov word bx,[sects_per_track] ;sectors per track
        div bx ;ax is now temp
        
        ;cylinder
        push ax ;save temp
        xor dx,dx
        mov word bx,[num_heads] ;number of heads
        div bx ;ax is now cylinder
        mov cx,ax ;cx stores cylinder
        pop ax ;retrieve temp
        ;cx is now cylinder
        
        ;head
        push dx ;heads already in dx
        
        ;sector
        pop dx ;pop dx to get stack value underneath it
        pop ax ;retrieve lba
        push dx ;push dx back on
        push cx ;save cylinder
        xor dx,dx
        mov word bx,[sects_per_track]
        div bx
        inc dx ;dx now has sectors
        mov bx,dx ;now bx has sectors
        pop cx
        pop dx
        
        ;put params together
        mov ch,cl ;cylinder in ch
        mov cl,bl ;sector in cl
        mov dh,dl ;head in dh
        mov dl,0 ;erase dl
        
        pop bx ;load old bx
        pop ax ;load old ax
        ret
``` This read disk code likely is not causing the issues as I have loaded many other sectors with this.
4

3 回答 3

1

int 13hwithah=02应该采用 中的部分数al,请参阅http://www.ctyme.com/intr/rb-0607.htm。目前您mov al, 1在调用之前执行此操作readdisk,并且该值是通过调用保留的lbatochs,因此您读取了 1 个扇区。

如果您想要 42 个扇区,请将其更改为mov al, 42. readdisk或者以其他方式重构。

于 2021-08-31T17:14:13.037 回答
1
  readfat:
       mov byte dl,[es:bx]

这个指令毫无意义!在那个地方(还)没有什么有用的东西可以阅读。


但是我不知道如何从文件中读取多个扇区。

原因是您的代码忘记实际循环回readfat标签。一旦你加载了下一个簇号,你需要跳回到循环的顶部,而不是立即跳到BOOT.BIN二进制文件。

请注意,仅插入缺失的jmp! 因为必要add bx, 512的被pop bx指令破坏了,所有的扇区将相互叠加

因为

这个读取磁盘代码可能不会导致问题,因为我已经用它加载了许多其他扇区。

我没有调查你的那部分代码。看看下一次重写是否适合你:

foundfile:
        mov  ax, [es:di+0x0F]  ; dirFirstCluster
        mov  bx, 0x4000
        mov  es, bx
        xor  bx, bx
READSECTOR:
        push es                ; (1)
        push bx                ; (2)
        push ax                ; (3)
        add  ax, 31
        mov  cx, ax
        mov  al, 1
        call readdisk
        pop  ax                ; (3)
        mov  dx, 3
        mul  dx
        shr  ax, 1
        jnc  short evenclus
oddclus:
        shr  ax, 4
evenclus:
        and  ax, 0x0FFF
        cmp  ax, 0x0FF8
        jae  finishedread

        mov  bx, 0x1000        ; FAT
        mov  es, bx
        mov  bx, ax
        mov  ax, [es:bx]       ; Following cluster number
        pop  bx                ; (2)
        pop  es                ; (1)
        ADD  BX, 512       <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        JMP  READSECTOR    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

finishedread:
        jmp  0x4000:0000
        jmp  fatalerror
于 2021-09-01T01:00:24.747 回答
0

我已经想出了如何自己编写循环。

如果您想查看它,这是代码:

foundfile:
    mov word ax,[es:di+0x0f]
    push ax ;save file cluster
    ;now to parse the fat
    mov dx,second_boot_segment
    mov es,dx ;second_boot_segment
    xor bx,bx ;offset for es
    xor di,di ;offset for es when reading the fat
    
    read_file_sector:
        pop cx ;get file cluster and put in cx
        add cx,31
        push ax ;save cluster again
        mov byte al,[sects_per_cluster] ;cluster size
        call readdisk
        pop ax ;retrieve cluster
        push es
        
    find_cluster:
        mov cx,3
        xor dx,dx
        mul cx ;multiply cluster number by 3
        shr ax,1 ;divide cluster number by 2
        mov cx,fat_segment
        mov es,cx
        mov di,ax
        mov word ax,[es:di]

        jnc short evenclus
        
        oddclus:
            shr ax,4
            jmp short continue_findcluster
            
        evenclus:
            and ax,0x0fff
            
        continue_findcluster:
            cmp ax,0x0ff0
            jae finishedread
            
            add bx,512
            pop es
            push ax ;save cluster for loop
            jmp short read_file_sector
        
    finishedread:
        jmp second_boot_segment:0000
        jmp fatalerror
于 2021-09-01T19:32:47.013 回答