flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Going back from protected to real mode.

Author
Thread Post new topic Reply to topic
Trolek



Joined: 19 Dec 2005
Posts: 2
Location: Poland
Trolek 12 Aug 2006, 16:27
Hello.

Few days ago I started to switch my kernel from protected to real mode. Everything was loaded via GRUB. Then I was loading GDT and updating segment registers for ring0 4gb code. In text step I was trying to do far jump to 64kb segment. On that point qemu and Bochs were just hanging. In Bochs log i saw that error was occured by that far jump. I dont know why it is happening and what do to make it works. Ill be glad if someone help me with that.

Here is shorted kernel code:

Code:
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
        
        lgdt [Gdt]
        
        mov ax, GDT_RING0_DATA
        mov ds, ax
        mov es, ax
        mov fs, ax
        mov gs, ax
        mov ss, ax
        
        jmp GDT_RING0_CODE : .pmode_flush
        
.pmode_flush:
        ; And here we got error :/

        jmp GDT_RMODE_CODE : .rmode_flush

.rmode_flush:

        mov ax, GDT_RMODE_DATA
        mov ds,ax
        mov es,ax
        mov fs,ax
        mov gs,ax
        mov ss,ax
        
        hlt
        
Gdt:
        .size dw Gdt_size
        .addr dd Gdt_array
        
Gdt_array:
        GDT_ITEM 0, 0, 0, 0, 0
        GDT_RING0_CODE = 8
        GDT_ITEM 1, 0xFFFFF, 0, SEGMENT_RING0 or SEGMENT_RE, SEGMENT_4KB or SEGMENT_USE32
        GDT_RING0_DATA = 16
        GDT_ITEM 2, 0xFFFFF, 0, SEGMENT_RING0 or SEGMENT_RW, SEGMENT_4KB or SEGMENT_USE32
        
        GDT_RMODE_CODE = 24
        GDT_ITEM 3, 0xFFFF, 0, SEGMENT_RING0 or SEGMENT_RE, 0
        GDT_RMODE_DATA = 32
        GDT_ITEM 4, 0xFFFF, 0, SEGMENT_RING0 or SEGMENT_RW, 0
Gdt_size = $ - Gdt_array - 1
        
segment
        rb 1024
        kStack:    
[/code]
Post 12 Aug 2006, 16:27
View user's profile Send private message Reply with quote
0x4e71



Joined: 25 Feb 2004
Posts: 50
0x4e71 13 Aug 2006, 17:23
if you want to go back to real mode you also have to update cr0.
Post 13 Aug 2006, 17:23
View user's profile Send private message Reply with quote
Trolek



Joined: 19 Dec 2005
Posts: 2
Location: Poland
Trolek 15 Aug 2006, 11:15
I did some changes and my kernel is going now into real mode. Maybe this will be usefull to someone in future.

Code:
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:    
Post 15 Aug 2006, 11:15
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.