Assembly 复制并执行

Assembly 复制并执行,assembly,x86,bootloader,Assembly,X86,Bootloader,我正在为我的定制内核编写一个简单的引导程序。它的逻辑非常简单: 引导加载程序由BIOS加载 将自身复制到0x8000 将内核从磁盘加载到0x9000 跳转到0x8000并将内核复制到0x0并设置GDT 跳转到0x0 这是我的引导程序: .set DEST, 0x8000 start: movw $0x3, %ax int $0x10 movw msg, %bp movw $0xa, %cx call print_msg //copy the end o

我正在为我的定制内核编写一个简单的引导程序。它的逻辑非常简单:

  • 引导加载程序由BIOS加载
  • 将自身复制到0x8000
  • 将内核从磁盘加载到0x9000
  • 跳转到0x8000并将内核复制到0x0并设置GDT
  • 跳转到0x0
  • 这是我的引导程序:

    .set    DEST, 0x8000
    
    start:
    movw    $0x3, %ax
    int     $0x10
    
    movw    msg, %bp
    movw    $0xa, %cx
    call    print_msg
    
    //copy the end of bootloader to new place
    selfCopy:
    cld
    xor     %ax, %ax
    movw    %ax, %ds
    movl    move_kernel, %esi
    movw    %ax, %es
    movl    DEST, %edi
    movl    (move_kernel_end-move_kernel), %ecx
    rep movsb
    
    //load kernel to 0x9000
    load_kernel:
    xor     %dx, %dx
    xor     %ah, %ah
    int     $0x10
    jc      reboot
    
    xor     %ax, %ax
    movw    %ax, %ds
    movb    $0x42, %ah
    movw    DAP, %si
    int     $0x13
    jc      reboot
    
    jmp     DEST
    
    DAP:
    .byte   0x10
    .byte   0x0
    .word   2048
    //offset
    .word   9000
    .word   0x0
    .long   1
    
    move_kernel:
    xor     %ax, %ax
    movw    %ax, %ds
    movl    $0x9000, %esi
    movw    %ax, %es
    movl    $0x0, %edi
    movl    (move_kernel_end-move_kernel), %ecx
    rep movsb
    lgdt    gdtr
    jmp     $0x0
    move_kernel_end:
    
    print_msg:
    //print message    
    movw    $0x0007, %bx
    movw    $0x1301, %ax
    int     $0x10
    ret
    msg:
    .string "Booting..."
    error_msg:
    .string "Error..."
    
    gdt:
    .quad   0x0
    
    .byte   0x0
    .byte   0b11001111
    .byte   0b11111010
    .byte   0x0
    .word   0x0
    .word   0xffff
    
    .byte   0x0
    .byte   0b11001111
    .byte   0b11110010
    .byte   0x0
    .word   0x0
    .word   0xffff
    gdtr:
    .long   gdt
    .word   $23
    
    reboot:
    movw    error_msg, %bp
    movw    $0x8, %cx
    call    print_msg
    jmp     .
    
    .fill   510-(. - start), 1, 0
    .byte   0x55
    .byte   0xaa
    
    所以,如果我把
    jmp.
    放在
    jmpdest
    之前,它就不会进入无限循环。那么,我的引导程序有什么问题

    谢谢

    顺便说一句,对不起,我的英语不好

    修改代码:

    .set    DEST, 0x8000
    
    start:
    movw    $0x3, %ax
    int     $0x10
    
    pushw   msg
    pushw   $0xa
    call    print_msg
    
    //copy the end of bootloader to new place
    selfCopy:
    cld
    xor     %ax, %ax
    movw    %ax, %ds
    movl    move_kernel, %esi
    movw    %ax, %es
    movl    DEST, %edi
    movl    (move_kernel_end-move_kernel), %ecx
    rep     movsb
    
    //load kernel to 0x9000
    load_kernel:
    xor     %dx, %dx
    xor     %ah, %ah
    int     $0x13
    jc      reboot
    
    xor     %ax, %ax
    movw    %ax, %ds
    movb    $0x42, %ah
    movw    DAP, %si
    int     $0x13
    jc      reboot
    jmp     DEST
    
    DAP:
    .byte   0x10
    .byte   0x0
    .word   2048
    //offset
    .word   9000
    .word   0x0
    .long   1
    
    move_kernel:
    cli
    xor     %ax, %ax
    movw    %ax, %ds
    movl    $0x9000, %esi
    movw    %ax, %es
    movl    $0x0, %edi
    movl    (move_kernel_end-move_kernel), %ecx
    rep movsb
    lgdt    gdtr
    jmp     .
    sti
    jmp     $0x0
    move_kernel_end:
    
    print_msg:
    //print message
    popw    %ax
    popw    %cx
    popw    %bp
    pushl   %eax
    movb    $0x07, %bl
    movb    $0x13, %ah
    movb    $0x1, %al
    int     $0x10
    ret
    
    msg:
    .string "Booting..."
    
    gdt:
    .quad   0x0
    
    .byte   0x0
    .byte   0b11001111
    .byte   0b11111010
    .byte   0x0
    .word   0x0
    .word   0xffff
    
    .byte   0x0
    .byte   0b11001111
    .byte   0b11110010
    .byte   0x0
    .word   0x0
    .word   0xffff
    gdtr:
    .long   gdt
    .word   23
    
    reboot:
    pushw   $0xdead
    pushw   $0x8
    call    print_msg
    
    .fill   510-(. - start), 1, 0
    .byte   0x55
    .byte   0xaa
    

    在您的
    load\u内核:
    标签下面,您打算执行
    int$0x10
    还是
    int$0x13
    ?我看不到在哪里显式加载了
    %es
    0:0
    似乎是将内核复制到的一个奇怪的位置-至少没有
    cli
    !您没有向我们显示您的ld命令行或链接器脚本。初始消息有效吗?感谢您的更正!我已经修改了代码(将其添加到问题中),所以我遇到了下一个问题:它在
    int%0x13
    (在
    内核加载期间)崩溃。我通过异或%ax、%ax movw%ax、%es设置了
    %es
    ,因此
    %es
    ==0。在这个阶段,我根本不使用链接器(bootloader是yasm-f bin的原始二进制文件)。另外,我的软盘映像不正确,只有514字节。这个问题会发生吗?它是如何崩溃的?如果设置了CF,您可以检查AH的状态。顺便说一句,0x0真的不是内核的好地方。Bochs:
    [GDBST]用ac0停止
    GDB:
    info寄存器eax eflags
    eflags 0x0[]
    eax 0x2fe 766为什么
    0x0
    不是个好地方(我不会使用BIOS中断)?啊!使用Yasm!酷!这可能意味着您的原点是0,而不是0x7C00,因此
    %ds
    %es
    应该是0x7C0而不是0。中断会发生-每18秒,每次按键和释放,也许其他时间-无论你是否使用它们。。。除非你把它们关掉,我看不到。我不知道Bochs,所以我不明白它在告诉你什么,抱歉。