Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 我写了一个引导加载程序,但它总是跳转到我写的失败部分,而不加载我的第2阶段_Assembly_Nasm_X86 16_Bootloader - Fatal编程技术网

Assembly 我写了一个引导加载程序,但它总是跳转到我写的失败部分,而不加载我的第2阶段

Assembly 我写了一个引导加载程序,但它总是跳转到我写的失败部分,而不加载我的第2阶段,assembly,nasm,x86-16,bootloader,Assembly,Nasm,X86 16,Bootloader,我编写了一个引导加载程序,它应该在FAT12格式的img文件上加载我的KRNLDR.SYS。但它不起作用 我用来创建它的命令: nasm -fbin -o boot.bin boot.asm dd if=/dev/zero of=test.img bs=512 count=2880 sudo losetup /dev/loop0 test.img sudo mkdosfs -F 12 /dev/loop0 现在,我的系统识别并安装设备,我将KRNLDR.SYS放在上面 然后我执行: sudo

我编写了一个引导加载程序,它应该在FAT12格式的img文件上加载我的KRNLDR.SYS。但它不起作用

我用来创建它的命令:

nasm -fbin -o boot.bin boot.asm
dd if=/dev/zero of=test.img bs=512 count=2880
sudo losetup /dev/loop0 test.img
sudo mkdosfs -F 12 /dev/loop0
现在,我的系统识别并安装设备,我将KRNLDR.SYS放在上面

然后我执行:

sudo dd if=boot.bin of=/dev/loop0 bs=512 count=1 conv=notrunc
sudo umount /dev/loop0
sudo losetup -d /dev/loop0
现在该文件看起来像FAT12软盘,带有引导扇区和文件KRNLDR.SYS

现在我在QEMU中执行它:

qemu-system-i386 -device format=raw,file=test.img 
以及输出:

Operating System not found
Press any key to reboot
如果我的引导加载程序找不到文件KRNLDR.SYS,这是引导加载程序打印到屏幕上的输出

我的代码:

org 0x0
bits 16

    jmp     word loader

bsOEMName:                  db "TestOS  "
bpbBytesPerSector:          dw 512
bpbSectorsPerCluster:       db 1
bpbReservedSectors:         dw 1
bpbNumberOfFATs:            db 2
bpbNumberOfRootEntries:     dw 224
bpbTotalSectors:            dw 2880
bpbMedia:                   db 0xf0
bpbSectorsPerFAT:           dw 9
bpbSectorsPerTrack:         dw 18
bpbNumberOfHeads:           dw 2
bpbHiddenSectors:           dd 0
bpbTotalSectorsBig:         dd 0
bsDriveNumber:              db 0
bsReserved:                 db 0
bsExtendedBootSignature:    db 0x29
bsVolumeID:                 dd 0x12345678
bsVolumeLabel:              db "TestOS     "
bsFileSystem:               db "FAT12   "

;-------------------------------------------------------------------------------
; SI = Zero terminated string to print
;-------------------------------------------------------------------------------

printMsg:
    push    ax

.printStart:
    lodsb
    or      al, al
    jz      .printEnd

    mov     ah, 0x0e
    int     0x10
    jmp     .printStart

.printEnd:
    pop     ax

    ret

;-------------------------------------------------------------------------------
; AX = Starting sector
; CX = Number of sectors to read
; ES:BX = Buffer
;-------------------------------------------------------------------------------

readSectors:
    mov     di, 0x0005

.readLoop:
    push    ax
    push    bx
    push    cx

    call    lbaToChs

    mov     ah, 0x02
    mov     al, 0x01
    mov     ch, byte [track]
    mov     cl, byte [sector]
    mov     dh, byte [head]
    mov     dl, byte [bsDriveNumber]
    int     0x13
    jnc     .success

    dec     di
    pop     cx
    pop     bx
    pop     ax
    jnz     .readLoop

.success:
    pop     cx
    pop     bx
    pop     ax

    inc     ax
    add     bx, word [bpbBytesPerSector]
    loop    readSectors

    ret

track:      db      0
head:       db      0
sector:     db      0

;-------------------------------------------------------------------------------
; AX = Logical sector
;-------------------------------------------------------------------------------

lbaToChs:
    xor     dx, dx
    div     word [bpbSectorsPerTrack]
    inc     dl
    mov     byte [sector], dl

    xor     dx, dx
    div     word [bpbNumberOfHeads]
    mov     byte [head], dl
    mov     byte [track], al

    ret

;-------------------------------------------------------------------------------
; AX = Cluster number
;-------------------------------------------------------------------------------

clusterToLba:
    sub     ax, 0x0002
    xor     cx, cx
    mov     cl, byte [bpbSectorsPerCluster]
    mul     cx

    ret

;-------------------------------------------------------------------------------

loader:
    cli

    mov     ax, 0x07c0
    mov     es, ax
    mov     gs, ax
    mov     fs, ax
    mov     ds, ax

    mov     ax, 0x0000
    mov     ss, ax
    mov     sp, 0xffff

    sti

    mov     byte [bsDriveNumber], dl

    xor     dx, dx
    xor     cx, cx
    mov     ax, 0x0020
    mul     word [bpbNumberOfRootEntries]
    div     word [bpbBytesPerSector]
    xchg    cx, ax ; Number of sectors of the root directory

    mov     al, byte [bpbNumberOfFATs]
    mul     word [bpbSectorsPerFAT]
    add     ax, word [bpbReservedSectors] ; Starting sector of the root directory

    mov     bx, 0x0200
    call    readSectors

    mov     cx, word [bpbNumberOfRootEntries]
    mov     di, 0x0200

searchRoot:
    push    cx
    mov     cx, 0x000b
    mov     si, stage2

    push    di
    rep cmpsb
    pop     di

    je      loadFat
    pop     cx
    add     di, 0x0020
    loop    searchRoot

    jmp     failure

loadFat:
    mov     dx, [di + 26] ; Starting address of entry
    xor     ax, ax
    mov     al, byte [bpbNumberOfFATs]
    mul     word [bpbSectorsPerFAT] ; Number of sectors used by the FATs

    mov     word [cluster], dx
    mov     cx, ax
    mov     ax, word [bpbReservedSectors]

    mov     bx, 0x0200
    call    readSectors

    mov     ax, 0x0050
    mov     es, ax
    mov     bx, 0x0000
    push    bx

loadFile:
    mov     ax, word [cluster]
    pop     bx
    call    clusterToLba
    xor     cx, cx
    mov     cl, byte [bpbSectorsPerCluster]
    call    readSectors
    push    bx

    mov     ax, word [cluster]

    mov     cx, ax
    mov     dx, ax
    shr     dx, 1
    add     cx, dx

    mov     bx, 0x0200
    add     bx, cx
    mov     dx, [bx]

    test    ax, 1
    jnz     oddCluster

evenCluster:
    and     dx, 0b0000111111111111
    jmp     next

oddCluster:
    shr     dx, 4

next:
    mov     word [cluster], dx
    cmp     dx, 0x0ff0
    jb      loadFile

    jmp     0x0050:0 ; Far jmp to KRNLDR.SYS

failure:
    mov     si, fail
    call    printMsg

    mov     si, anykey
    call    printMsg

    mov     ah, 0x00
    int     0x16 ; Await key press

    jmp     0xffff:0 ; Reboot with far jmp to BIOS

stage2:         db          "KRNLDR  SYS"
fail:           db          "Operating system not found", 0xd, 0xa, 0x0
anykey:         db          "Press any key to reboot", 0xd, 0xa, 0x0

cluster:        dw          0

times 510 - ($ - $$) db 0
dw 0xaa55
我能做什么? 谢谢你的帮助

loadFat:
    mov     dx, [di + 26] ; Starting address of entry
    xor     ax, ax
    mov     al, byte [bpbNumberOfFATs]
    mul     word [bpbSectorsPerFAT] ; Number of sectors used by the FATs

    mov     word [cluster], dx
这里的一个问题是带有一个字操作数的
mul
将该字乘以
ax
,并将结果保留在寄存器对
dx:ax
中。因此,在初始化名为cluster的变量之前,用零覆盖
dx
。当将FAT条目索引转换为扇区号时,从零减去2将得到一个非常高的扇区号

这就引出了我发现的第二个问题。通常,[cluster]中的零应该减去2,结果乘以1(每个簇的扇区数量),然后加上“第一个数据扇区”,这将再次导致非常低的数字,这将导致故障,但可能有所不同。但是,clusterToLba实际上并没有转换为该集群数据的LBA起始扇区,因为它没有添加“第一个数据扇区”(即,第一个集群第一个扇区的LBA编号)。这需要由加载程序计算。它是根目录的起始扇区加上根目录扇区的数量

这里的一个问题是带有一个字操作数的
mul
将该字乘以
ax
,并将结果保留在寄存器对
dx:ax
中。因此,在初始化名为cluster的变量之前,用零覆盖
dx
。当将FAT条目索引转换为扇区号时,从零减去2将得到一个非常高的扇区号


这就引出了我发现的第二个问题。通常,[cluster]中的零应该减去2,结果乘以1(每个簇的扇区数量),然后加上“第一个数据扇区”,这将再次导致非常低的数字,这将导致故障,但可能有所不同。但是,clusterToLba实际上并没有转换为该集群数据的LBA起始扇区,因为它没有添加“第一个数据扇区”(即,第一个集群第一个扇区的LBA编号)。这需要由加载程序计算。它是根目录的起始扇区加上根目录扇区的数量。

您是否考虑过使用类似BOCHs的工具,通过其调试器逐步检查代码?BOCHs有一个内置的调试器,在实模式下运行良好。你可以观察你的代码,看看它是如何失败的。我只是设置了它。现在我正在调试,您是否考虑过使用类似BOCHs的工具,通过其调试器逐步完成代码?BOCHs有一个内置的调试器,在实模式下运行良好。你可以观察你的代码,看看它是如何失败的。我只是设置了它。现在我正在调试