Assembly QEMU寄存器和eip在ds中移动0x18后被销毁

Assembly QEMU寄存器和eip在ds中移动0x18后被销毁,assembly,x86,qemu,bootloader,protected-mode,Assembly,X86,Qemu,Bootloader,Protected Mode,我现在正在学习构建自己的引导加载程序。我能够设置gdt并进入保护模式。但当我试图将0x18(gdt中的第三段)移动到ds中时,我的大多数寄存器都被破坏,eip得到了一些随机信息 导致错误的代码:(im已处于受保护的32位模式) 指令前的gdb: ─── Output/messages ───────────────────────────────────────────────────────────────────────────────────── ─── Assembly ────────

我现在正在学习构建自己的引导加载程序。我能够设置gdt并进入保护模式。但当我试图将0x18(gdt中的第三段)移动到ds中时,我的大多数寄存器都被破坏,eip得到了一些随机信息

导致错误的代码:(im已处于受保护的32位模式)

指令前的gdb:

─── Output/messages ─────────────────────────────────────────────────────────────────────────────────────
─── Assembly ────────────────────────────────────────────────────────────────────────────────────────────
0x00007cf4 ? mov    ds,eax
0x00007cf6 ? mov    eax,ds:0x0
0x00007cfb ? hlt    
0x00007cfc ? or     BYTE PTR [eax+0x65],0x6c
0x00007d00 ? ins    BYTE PTR es:[edi],dx
0x00007d01 ? outs   dx,DWORD PTR ds:[esi]
0x00007d02 ? and    BYTE PTR [edi+0x6f],dl
─── Expressions ─────────────────────────────────────────────────────────────────────────────────────────
─── History ─────────────────────────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────────────────────────
─── Registers ───────────────────────────────────────────────────────────────────────────────────────────
   eax 0x00000018       ecx 0x00000002       edx 0x00000080       ebx 0x00000000       esp 0x00002000   
   ebp 0x00000000       esi 0x00000000       edi 0x00000000       eip 0x00007cf4    eflags [ PF ]       
    cs 0x00000008        ss 0x000007e0        ds 0x00000010        es 0x000009e0        fs 0x00000000   
─── Output/messages ─────────────────────────────────────────────────────────────────────────────────────
─── Assembly ────────────────────────────────────────────────────────────────────────────────────────────
0x0000e05b ? add    BYTE PTR [eax],al
0x0000e05d ? add    BYTE PTR [eax],al
0x0000e05f ? add    BYTE PTR [eax],al
0x0000e061 ? add    BYTE PTR [eax],al
0x0000e063 ? add    BYTE PTR [eax],al
0x0000e065 ? add    BYTE PTR [eax],al
0x0000e067 ? add    BYTE PTR [eax],al
─── Expressions ─────────────────────────────────────────────────────────────────────────────────────────
─── History ─────────────────────────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────────────────────────
─── Registers ───────────────────────────────────────────────────────────────────────────────────────────
   eax 0x00000000       ecx 0x00000000       edx 0x00000663       ebx 0x00000000       esp 0x00000000   
   ebp 0x00000000       esi 0x00000000       edi 0x00000000       eip 0x0000e05b    eflags [ ]          
    cs 0x0000f000        ss 0x00000000        ds 0x00000000        es 0x00000000        fs 0x00000000   
    gs 0x00000000   
指示后的gdb:

─── Output/messages ─────────────────────────────────────────────────────────────────────────────────────
─── Assembly ────────────────────────────────────────────────────────────────────────────────────────────
0x00007cf4 ? mov    ds,eax
0x00007cf6 ? mov    eax,ds:0x0
0x00007cfb ? hlt    
0x00007cfc ? or     BYTE PTR [eax+0x65],0x6c
0x00007d00 ? ins    BYTE PTR es:[edi],dx
0x00007d01 ? outs   dx,DWORD PTR ds:[esi]
0x00007d02 ? and    BYTE PTR [edi+0x6f],dl
─── Expressions ─────────────────────────────────────────────────────────────────────────────────────────
─── History ─────────────────────────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────────────────────────
─── Registers ───────────────────────────────────────────────────────────────────────────────────────────
   eax 0x00000018       ecx 0x00000002       edx 0x00000080       ebx 0x00000000       esp 0x00002000   
   ebp 0x00000000       esi 0x00000000       edi 0x00000000       eip 0x00007cf4    eflags [ PF ]       
    cs 0x00000008        ss 0x000007e0        ds 0x00000010        es 0x000009e0        fs 0x00000000   
─── Output/messages ─────────────────────────────────────────────────────────────────────────────────────
─── Assembly ────────────────────────────────────────────────────────────────────────────────────────────
0x0000e05b ? add    BYTE PTR [eax],al
0x0000e05d ? add    BYTE PTR [eax],al
0x0000e05f ? add    BYTE PTR [eax],al
0x0000e061 ? add    BYTE PTR [eax],al
0x0000e063 ? add    BYTE PTR [eax],al
0x0000e065 ? add    BYTE PTR [eax],al
0x0000e067 ? add    BYTE PTR [eax],al
─── Expressions ─────────────────────────────────────────────────────────────────────────────────────────
─── History ─────────────────────────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────────────────────────
─── Registers ───────────────────────────────────────────────────────────────────────────────────────────
   eax 0x00000000       ecx 0x00000000       edx 0x00000663       ebx 0x00000000       esp 0x00000000   
   ebp 0x00000000       esi 0x00000000       edi 0x00000000       eip 0x0000e05b    eflags [ ]          
    cs 0x0000f000        ss 0x00000000        ds 0x00000000        es 0x00000000        fs 0x00000000   
    gs 0x00000000   

正如您所看到的,大多数寄存器都被销毁了,eip位于它应该位于的其他位置,并且在该位置没有真正的代码。在ds中移动0x10之前执行一些指令,它可以正常工作。这是qemu的bug吗?我不想在我真正的电脑上尝试,因为谁知道会发生什么?有人知道吗?

寄存器被破坏的原因是系统出现三重故障并重新进入实模式。CS:IP是BIOS ROM中的0xf000:e05b。GDB不能正确处理实模式,并在0x0000:0xe05b显示指令,因为它不理解段寄存器0xf000也构成了地址的一部分,并从错误的内存位置反汇编了指令。该内存似乎已被零填充。在OS开发的早期调试此类问题时,BOCHS是一个更好的调试器。BOCHs有一个
info-gdt
命令,将显示当前加载的gdt。如果条目已损坏,您将更容易看到它

看起来您已经成功地设置了CS选择器寄存器(在三重故障之前),我假设您的GDT的一部分是有效的。我的第一个观察结果是,gdt中的
gdt\u视频
描述符布局不正确。你有:

; GDT video segment
gdt_video:
    dw 0xFFFF
    dw 0x00
    dw 0x00             ; <------ This needs to be a byte
    dw 10010010b        ; <------ This needs to be a byte
    db 11001111b
    db 0x00
您可能还有其他问题,但根据提供的信息,这是我唯一能观察到的错误


其他意见
  • 不清楚您为什么创建了
    gdt\u视频
    描述符。您已经使它成为一个扁平的4GB数据描述符,就像
    gdt\u数据
    描述符一样。这里显示的两个描述符是相同的。您本可以使用0x10加载DS选择器
  • 您没有显示所有代码,但我注意到在出现三重错误之前,调试器说:

    我希望您打算在某个时候设置SS(和ESP)、ES、FS和GS。SS:在使用与堆栈交互的任何指令(即:
    push
    pop
    call
    ret
    等)之前,应设置ESP


这不是一个问题。无论如何,您可能设置了错误的GDT(例如错误的限制),并且您得到了一个异常,该异常的处理程序也被破坏。我建议您使用bochs,因为它可以提供更好的调试。我希望使用视频片段与视频缓冲区进行交互,并将基数设置为0xB8000。但它不起作用,因为我不小心写了'dw'而不是你提到的'db'。所以我想,如果我复制第二段的字节结构,它应该可以工作,因为这两段应该是相同的,并且与第二段的操作已经可以工作了。但是我没有再看到这个错误。你解决了这个错误,非常感谢。
; GDT video segment
gdt_video:
    dw 0xFFFF
    dw 0x00
    db 0x00
    db 10010010b
    db 11001111b
    db 0x00
ss 0x000007e0        ds 0x00000010        es 0x000009e0        fs 0x00000000