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