Im currently learning to build my own bootloader. I was able to setup a gdt and get into protected mode. But when i tried to move 0x18 (third segment in gdt) into ds most of my registers are destroyed and eip gets something random
Code that causes error: (im already in protected 32-bit mode)
mov eax, 0x18
mov ds, eax <--- After this instruction registers are destroyed
mov eax, [0x0000]
My gdt entries:
; 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 before the instruction:
─── 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 after instruction:
─── 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
as you see most of the registers are destroyed, eip is somewhere else it should be and there is not really code at that location. Some instruction before i move 0x10 in ds and it works without any problems. Is this a bug of qemu? I do not want to try this on my real pc, cause who know what happens? Anyone have an idea?
The reason the registers are trashed is because your system triple faulted and entered back into real mode. CS:IP afterwards is 0xf000:e05b which is in the BIOS ROM. GDB doesn't properly deal with real mode and is displaying the instructions at 0x0000:0xe05b because it doesn't understand that the segment register 0xf000 also makes up part of the address and disassembled the instructions from the wrong memory location. That memory appears to have been filled with zeroes. BOCHS is a better debugger when debugging this kind of problem early on in OS development. BOCHs has an info gdt
command that will show you the currently loaded GDT. If an entry is corrupt you'd more easily be able to see it.
As it appears you have managed to set CS selector register (before the triple fault) I assume part of your GDT is valid. My first observation is that your gdt_video
descriptor in the GDT is laid out incorrectly. You have:
; 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
It should have been:
; GDT video segment
gdt_video:
dw 0xFFFF
dw 0x00
db 0x00
db 10010010b
db 11001111b
db 0x00
You may have other issues, but based on the information given this is the only thing I can observe being incorrect.
gdt_video
descriptor. You've made it a flat 4GB data descriptor just like the gdt_data
descriptor. Both descriptors as you have shown here are identical. You could have loaded DS selector with 0x10.You don't show all your code but I noticed that before the triple fault the debugger said:
ss 0x000007e0 ds 0x00000010 es 0x000009e0 fs 0x00000000
I hope that you intend to set SS (and ESP), ES, FS, and GS at some point. SS:ESP should be set before you use any instructions that interact with the stack (ie: push
, pop
, call
, ret
etc.)
User contributions licensed under CC BY-SA 3.0