Give me PMode, or give me death
Posted: Sat Nov 24, 2007 7:42 pm
I am using a bootloader to load my kernel from a floppy to 0x0100:0x0000, but I am having difficulties when switching to PMode (actually, I think it happens when making the far jump, to be more precise)...
The kernel code:
Bochs says:
If I execute this code instead of my bootloader (with the addition of 0AA55h as the boot signature, the 512b size adjustment and the ORG 7C00h directive), it works just fine and prints the blue P out on the screen.
I'm guessing that I haven't set up the GDT properly... How to make sure?
I tried adjusting the location of the GDT (since I am using ORG 0x0), but I still get a triple fault in Bochs:
What next? Am I loading the GDT correctly? (am I pointing to it's location at all?)
The kernel code:
Code: Select all
[BITS 16]
[ORG 0x0]
jmp start
;print
print:
push ax
.prn:
lodsb
or al,al
jz .end
mov ah,0eh
int 10h
jmp .prn
.end:
pop ax
ret
start:
cli
mov ax, 0x0100
mov ss, ax ;stack segment
mov sp, 0xFFFF ;stack pointer
push cs
pop ax
mov dx,ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
sti
;start
begin:
startmeup:
mov si,starting
call print
cli ; Disable interrupts... again...
xor ax, ax
mov ds, ax ; Set DS-register to 0 - used by lgdt
lgdt [gdt_desc] ; Load the GDT descriptor
xor ax,ax
mov ds,ax
;pmode in a can
mov eax, cr0 ; Copy the contents of CR0 into EAX
or eax, 1 ; Set bit 0
mov cr0, eax ; Copy the contents of EAX into CR0
jmp 0x08:clear_pipe ; Jump to code segment, offset clear_pipe
;old school Pmode tutorial for the sake of testing...
[BITS 32]
clear_pipe:
mov ax, 10h ; Save data segment identifyer
mov ds, ax ; Move a valid data segment into the data segment register
mov ss, ax ; Move a valid data segment into the stack segment register
mov esp, 090000h ; Move the stack pointer to 090000h
;write something
mov byte [ds:0B8000h], 'P' ; Move the ASCII-code of 'P' into first video memory
mov byte [ds:0B8001h], 1Bh ; Assign a color code
cli ; stop interrupts
hlt ; halt the CPU
starting db 'Booting...',13,10,0
gdt: ; Address for the GDT
gdt_null: ; Null Segment
dd 0
dd 0
gdt_code: ; Code segment, read/execute, nonconforming
dw 0FFFFh
dw 0
db 0
db 10011010b
db 11001111b
db 0
gdt_data: ; Data segment, read/write, expand down
dw 0FFFFh
dw 0
db 0
db 10010010b
db 11001111b
db 0
gdt_end:
gdt_desc: ; GDT descriptor
dw gdt_end - gdt - 1 ; Limit (size)
dd gdt ; Address of the GDT
Bochs says:
Code: Select all
00060434533i[BIOS ] Booting from 0000:7C00
00067385591e[CPU0 ] jump_protected: call gate.p == 0
00067385591e[CPU0 ] fetch_raw_descriptor: GDT: index (f007)1e00 > limit (53f0)
00067385591i[CPU0 ] protected mode
00067385591i[CPU0 ] CS.d_b = 16 bit
00067385591i[CPU0 ] SS.d_b = 16 bit
00067385591i[CPU0 ] EFER = 0x00000000
00067385591i[CPU0 ] | RAX=0000000000000011 RBX=0000000000000007
00067385591i[CPU0 ] | RCX=0000000000000017 RDX=0000000000000100
00067385591i[CPU0 ] | RSP=000000000000ffff RBP=0000000000000000
00067385591i[CPU0 ] | RSI=00000000ffff0107 RDI=0000000000080005
00067385591i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00067385591i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00067385591i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00067385591i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00067385591i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00067385591i[CPU0 ] | SEG selector base limit G D
00067385591i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00067385591i[CPU0 ] | CS:0100( 0004| 0| 0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] | DS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00067385591i[CPU0 ] | SS:0100( 0005| 0| 0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] | ES:0100( 0005| 0| 0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] | FS:0100( 0005| 0| 0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] | GS:0100( 0005| 0| 0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] | MSR_FS_BASE:0000000000001000
00067385591i[CPU0 ] | MSR_GS_BASE:0000000000001000
00067385591i[CPU0 ] | RIP=0000000000000084 (0000000000000084)
00067385591i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00067385591i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00067385591i[CPU0 ] >> jmp far 0008:0089 : EA89000800
00067385591e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown
status is 00h, resetting
00067385591i[SYS ] bx_pc_system_c::Reset(SOFTWARE) called
00067385591i[APIC0] local apic in CPU 0 initializing
00067385591e[CPU0 ] CPU_LOOP bx_guard.interrupt_requested=1
Next at t=67385591
<bochs:2> dump_cpu
eax:0x00000000, ebx:0x00000000, ecx:0x00000000, edx:0x00000f20
ebp:0x00000000, esp:0x00000000, esi:0x00000000, edi:0x00000000
eip:0x0000fff0, eflags:0x00000002, inhibit_mask:0
cs:s=0xf000, dl=0x0000ffff, dh=0xff009bff, valid=1
ss:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
ds:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
es:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
fs:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
gs:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
tr:s=0x0000, dl=0x0000ffff, dh=0x00008300, valid=1
gdtr:base=0x00000000, limit=0xffff
idtr:base=0x00000000, limit=0xffff
dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
dr3:0x00000000, dr6:0xffff0ff0, dr7:0x00000400
cr0:0x00000010, cr1:0x00000000, cr2:0x00000000
cr3:0x00000000, cr4:0x00000000
done
I'm guessing that I haven't set up the GDT properly... How to make sure?
I tried adjusting the location of the GDT (since I am using ORG 0x0), but I still get a triple fault in Bochs:
Code: Select all
gdt_desc: ; GDT descriptor
dw gdt_end - gdt - 1 ; Limit (size)
dd gdt + 0x1000 ; Address of the GDT + 0x1000