QEMU 寄存器和 eip 在 ds 中移动 0x18 后被销毁
QEMU registers and eip are destroyed after moving 0x18 in ds
我目前正在学习构建自己的引导加载程序。我能够设置 gdt 并进入保护模式。但是当我试图将 0x18(gdt 中的第三段)移动到 ds 时,我的大部分寄存器都被破坏了,eip 得到了一些随机的东西
导致错误的代码:(我已经处于受保护的 32 位模式)
mov eax, 0x18
mov ds, eax <--- After this instruction registers are destroyed
mov eax, [0x0000]
我的 gdt 条目:
; GDT null segment
8 gdt_null:
9 dq 0
10
11 ; GDT code segment (4GB)
12 gdt_code:
13 dw 0xFFFF
14 dw 0x00
15 db 0x00
16 db 10011010b
17 db 11001111b
18 db 0x00
19
20 ; GDT data segment (4GB)
21 gdt_data:
22 dw 0xFFFF
23 dw 0x00
24 db 0x00
25 db 10010010b
26 db 11001111b
27 db 0x00
28
29 ; GDT video segment
30 gdt_video:
31 dw 0xFFFF
32 dw 0x00
33 dw 0x00
34 dw 10010010b
35 db 11001111b
36 db 0x00
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
gdb 指令后:
─── 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的错误吗?我不想在我的真实电脑上尝试这个,因为谁知道会发生什么?有人有想法吗?
寄存器被破坏的原因是因为您的系统三重故障并进入实模式。 CS:IP之后是0xf000:e05b,在BIOS ROM中。 GDB 没有正确处理实模式,而是在 0x0000:0xe05b 处显示指令,因为它不理解段寄存器 0xf000 也构成地址的一部分,并从错误的内存位置反汇编指令。那个记忆似乎已经被零填满了。在 OS 开发早期调试此类问题时,BOCHS 是一个更好的调试器。 BOCHs 有一个 info gdt
命令可以显示当前加载的 GDT。如果条目已损坏,您将更容易看到它。
看来您已经设法设置了 CS 选择器寄存器(在三重故障之前)我假设您的 GDT 的一部分是有效的。我的第一个观察是 GDT 中的 gdt_video
描述符布局不正确。你有:
; 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 video segment
gdt_video:
dw 0xFFFF
dw 0x00
db 0x00
db 10010010b
db 11001111b
db 0x00
您可能还有其他问题,但根据所提供的信息,这是我能观察到的唯一不正确的地方。
其他观察结果
- 不清楚您创建
gdt_video
描述符的原因。就像 gdt_data
描述符一样,您已将其设为一个扁平的 4GB 数据描述符。您在此处显示的两个描述符都是相同的。您可以使用 0x10. 加载 DS 选择器
你没有显示你所有的代码,但我注意到在三重错误之前调试器说:
ss 0x000007e0 ds 0x00000010 es 0x000009e0 fs 0x00000000
我希望你打算设置SS(和ESP),ES, FS 和 GS 在某些时候。 SS:ESP 应在使用任何与堆栈交互的指令之前设置(即:push
、pop
、call
、ret
等)
我目前正在学习构建自己的引导加载程序。我能够设置 gdt 并进入保护模式。但是当我试图将 0x18(gdt 中的第三段)移动到 ds 时,我的大部分寄存器都被破坏了,eip 得到了一些随机的东西
导致错误的代码:(我已经处于受保护的 32 位模式)
mov eax, 0x18
mov ds, eax <--- After this instruction registers are destroyed
mov eax, [0x0000]
我的 gdt 条目:
; GDT null segment
8 gdt_null:
9 dq 0
10
11 ; GDT code segment (4GB)
12 gdt_code:
13 dw 0xFFFF
14 dw 0x00
15 db 0x00
16 db 10011010b
17 db 11001111b
18 db 0x00
19
20 ; GDT data segment (4GB)
21 gdt_data:
22 dw 0xFFFF
23 dw 0x00
24 db 0x00
25 db 10010010b
26 db 11001111b
27 db 0x00
28
29 ; GDT video segment
30 gdt_video:
31 dw 0xFFFF
32 dw 0x00
33 dw 0x00
34 dw 10010010b
35 db 11001111b
36 db 0x00
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
gdb 指令后:
─── 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的错误吗?我不想在我的真实电脑上尝试这个,因为谁知道会发生什么?有人有想法吗?
寄存器被破坏的原因是因为您的系统三重故障并进入实模式。 CS:IP之后是0xf000:e05b,在BIOS ROM中。 GDB 没有正确处理实模式,而是在 0x0000:0xe05b 处显示指令,因为它不理解段寄存器 0xf000 也构成地址的一部分,并从错误的内存位置反汇编指令。那个记忆似乎已经被零填满了。在 OS 开发早期调试此类问题时,BOCHS 是一个更好的调试器。 BOCHs 有一个 info gdt
命令可以显示当前加载的 GDT。如果条目已损坏,您将更容易看到它。
看来您已经设法设置了 CS 选择器寄存器(在三重故障之前)我假设您的 GDT 的一部分是有效的。我的第一个观察是 GDT 中的 gdt_video
描述符布局不正确。你有:
; 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 video segment
gdt_video:
dw 0xFFFF
dw 0x00
db 0x00
db 10010010b
db 11001111b
db 0x00
您可能还有其他问题,但根据所提供的信息,这是我能观察到的唯一不正确的地方。
其他观察结果
- 不清楚您创建
gdt_video
描述符的原因。就像gdt_data
描述符一样,您已将其设为一个扁平的 4GB 数据描述符。您在此处显示的两个描述符都是相同的。您可以使用 0x10. 加载 DS 选择器
你没有显示你所有的代码,但我注意到在三重错误之前调试器说:
ss 0x000007e0 ds 0x00000010 es 0x000009e0 fs 0x00000000
我希望你打算设置SS(和ESP),ES, FS 和 GS 在某些时候。 SS:ESP 应在使用任何与堆栈交互的指令之前设置(即:
push
、pop
、call
、ret
等)