I did some changes and my kernel is going now into real mode. Maybe this will be usefull to someone in future.
format elf executable at 1024*1024
entry _kernel
MB_4KBPAGE_ALIGN = 1 shl 0
MB_MEMORY_INFO = 1 shl 1
MB_HEADER_MAGIC = 0x1BADB002
MB_HEADER_FLAGS = MB_4KBPAGE_ALIGN or MB_MEMORY_INFO
MB_CHECKSUM = -MB_HEADER_MAGIC-MB_HEADER_FLAGS
SEGMENT_RING0 = 10010000b
SEGMENT_RW = 0010b
SEGMENT_RE = 1010b
SEGMENT_4KB = 1000b
SEGMENT_USE32 = 0100b
macro GDT_ITEM number,limit,base,access,granularity
{
Gdt_item#number:
.limit_low dw limit and 0xFFFF
.base_low dw base and 0xFFFF
.base_middle db (base shr 16) and 0xFF
.access db access
.gran db ((limit shr 16) and 0x0F) or ((granularity) shl 4)
.base_high db (base shr 24) and 0xFF
}
segment
multiboot_header:
.magic dd MB_HEADER_MAGIC
.flags dd MB_HEADER_FLAGS
.checksum dd MB_CHECKSUM
_kernel:
mov esp, kStack
; Load new GDT and set segment registers.
lgdt [Gdt]
mov ax, GDT_RING0_DATA
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Flush CS.
jmp GDT_RING0_CODE : .pmode_flush
.pmode_flush:
; Load real mode IDT.
lidt [rmIdtr]
; Copying real mode code to under 1MB.
mov edi, 0x7C000
mov esi, RealModeCode
mov ecx, length.RealModeCode
rep movsb
; Jumping to segment with 64kb limit. Base is set to .rmode_flush.
jmp GDT_RMODE_CODE : 0
.rmode_flush:
org 0
use16
mov ax, GDT_RMODE_DATA
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Cleaning PE bit in cr0.
mov eax, cr0
and al, not 1
mov cr0, eax
; Jumping to 0x7C000.
jmp 0x7C00 : 0
org $ + _kernel.rmode_flush
use32
RealModeCode:
org 0
use16
; Setting segment registers.
mov ax, cs
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
sti
mov ax,0x4F02
mov bx,0x4112
int 10h
cli
hlt
length.RealModeCode = $
org $ + RealModeCode
use32
rmIdtr:
.size dw 1023
.addr dd 0
Gdt:
.size dw Gdt_size
.addr dd Gdt_array
Gdt_array:
GDT_ITEM 0, 0, 0, 0, 0
GDT_RING0_CODE = $ - Gdt_array
GDT_ITEM 1, 0xFFFFF, 0, SEGMENT_RING0 or SEGMENT_RE, SEGMENT_4KB or SEGMENT_USE32
GDT_RING0_DATA = $ - Gdt_array
GDT_ITEM 2, 0xFFFFF, 0, SEGMENT_RING0 or SEGMENT_RW, SEGMENT_4KB or SEGMENT_USE32
GDT_RMODE_CODE = $ - Gdt_array
GDT_ITEM 3, 0xFFFF, _kernel.rmode_flush, SEGMENT_RING0 or SEGMENT_RE, 0
GDT_RMODE_DATA = $ - Gdt_array
GDT_ITEM 4, 0xFFFF, _kernel.rmode_flush, SEGMENT_RING0 or SEGMENT_RW, 0
Gdt_size = $ - Gdt_array - 1
segment
rb 1024
kStack: