I'm creating a bootloader and trying to jump into 32-bit code segment in order to finish protected mode activation. But I have a problem with General Protection Segmentation Fault and I was struggling with it for a while but I couldn't find a solution, unfortunately.
I use Bochs as the emulator and I'm attaching a screenshot of an exception. As you can see the CPU is already in protected mode.
This is the part of the bootloader inside the bootsector:
Code: Select all
[bits 16]
; set registers
cli
xor bx, bx
mov ax, 0x50
mov es, ax
sti
mov ah, 0x2
mov al, 0x1 ; how many sectors to read
mov ch, 0x0 ; cylinder number
mov cl, 0x2 ; read from sector 2
mov dh, 0x0 ; head 0
; drive number is already set by BIOS
int 0x13 ; stage2 will be loaded at 0x0050:0x0000 == 0x500 (physical addr)
jmp 0x50:0x0 ; jump to stage2 at (0x50*0x10+0) == 0x500
jmp $
times 510 - ($ - $$) db 0
; now the machine code is exactly 512 bytes in size
dw 0xaa55 ; 0xaa55 tells the CPU that this is the 1st stage of a bootloader
Code: Select all
[bits 16]
[org 0x500]
cli ; clear interrupts while switching from real to protected mode
lgdt [gdt_descriptor] ; load address of the gdt_descriptor into gdtr
mov eax, cr0
or al, 0x1 ; set first bit of cr0
mov cr0, eax ; make a switch to protected mode
; jump to 32-bit code segment
jmp 0x8:pmode_entry ; I think that the problem is HERE
align 0x8 ; GDT should be aligned to an 8-byte boundary for performance reasons
gdt_start: ; Basic flat model
gdt_null:
dq 0x0 ; null-descriptor
gdt_code:
dw 0xffff ; limit (bits 0-15)
dw 0x0 ; base address (bits 0-15)
db 0x0 ; base address (bits 16-23)
db 10011010b ; P(15), DPL(14,13), S, Type(11-8)
db 11001111b ; G, D/B, L, AVL, limit (bits 16-19)
db 0x0 ; base address (bits 24-32)
gdt_data:
dw 0xffff
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_end: ; This label is used for calculating limit of the GDT
gdt_descriptor:
dw gdt_end - gdt_start - 0x1 ; From Intel Manual Vol. 3:
; "Because segment descriptors are always 8 bytes long,
; the GDT limit should always be one less than an integral multiple of eight"
dd gdt_start ; GDT base address
[bits 32]
; Setting data segment registers to the proper index of GDT.
; Data segment index in GDT is exactly 0x10
pmode_entry:
mov ax, 0x10
mov ds, ax
mov es, ax
mov ss, ax
mov fs, ax
mov gs, ax
Code: Select all
%include "stage1.asm"
%include "protected_mode.asm"
times 1024 - ($-$$) db 0 ; alignment