Setup Kernel stack and reload register limit

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
ich_will

Setup Kernel stack and reload register limit

Post by ich_will »

First question: How can I setup the kernel stack with another offset than the 0x0? I try it like that:

GDT.asm

Code: Select all

[BITS 32]
[EXTERN __stack]

gdt:
NULL_SELECTOR equ $-gdt
        dd 0x00
        dd 0x00
REALMODE_DATA_SELECTOR equ $-gdt
        dw 0xFFFF       ; limit bit 7 - 0 and 15 - 8
        dw 0x0000       ; base 0  - 15
        db 0x00         ; base 16 - 23
        db 10010010b    ; access byte
        db 00000000b
        db 0x00
DATA_SELECTOR equ $-gdt
        dw 0xFFFF       ; limit bit 7 - 0 and 15 - 8
        dw 0x0000       ; base 0  - 15
        db 0x00         ; base 16 - 23
        db 10010010b    ; access byte
        db 11001111b
        db 0x00
CODE_SELECTOR equ $-gdt
        dw 0xFFFF       ; limit bit 7 - 0 and 15 - 8
        dw 0x0000       ; base 0  - 15
        db 0x00         ; base 16 - 23
        db 10011010b    ; access byte
        db 11001111b
        db 0x00
STACK_SELECTOR equ $-gdt
        dw 0x0000       ; limit bit 7 - 0 and 15 - 8
        dw 0xFBFF       ; base 0  - 15
        db 0x08         ; base 16 - 23
        db 10010010b    ; access byte
        db 11000001b
        db 0x00      ; base 24 - 31
gdt_end:
gdt_desc:
        dw gdt_end - gdt - 1
        dd gdt
_start.asm

Code: Select all

[BITS 32]
[GLOBAL start]
[GLOBAL __kernel_mem_size]
[EXTERN _code]
[EXTERN _bss]
[EXTERN _end]
[EXTERN _main]

start:
jmp start2

%include 'gdt.asm'

MULTIBOOT_MAGIC         equ 0x1BADB002
;MULTIBOOT_AOUT_KLUDGE   equ 1 << 16
MULTIBOOT_FLAGS         equ 0 ;MULTIBOOT_AOUT_KLUDGE
MULTIBOOT_CHECKSUM      equ -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS)

__kernel_mem_size dd 0

start2:
   cli
   mov ecx, eax            ; save the multiboot magic in ecx

        mov [__kernel_mem_size], dword _end

        lgdt [gdt_desc]

        jmp dword CODE_SELECTOR:reload_cs
    reload_cs:
        mov eax, STACK_SELECTOR
        mov ss, eax
   mov esp, 0xFFFF

        mov eax, DATA_SELECTOR
        mov ds, eax
        mov es, eax
        mov fs, eax
        mov gs, eax

   push ebx
   push ecx

        call _main

halt:
        cli
        hlt
        jmp halt

align 4
multiboot_header:
        magic           dd MULTIBOOT_MAGIC
        flags           dd MULTIBOOT_FLAGS
        checksum        dd MULTIBOOT_CHECKSUM

;        header_addr     dd multiboot_header
;        load_addr       dd _code
;        load_end_addr   dd _bss
;        bss_end_addr    dd _end
;        entry_addr      dd start
If I try to boot the kernel it now happens (no text is print out etc.)

Second question: How can I reload the limit of the cs, ds, es, fs and gs register so that it all has a limit of 0xFFFFFFFF after I've enabled paging?

Third question: How is it possible that code is executed at 0x100000 but the limit of cs is only 0xFFFFF.
It might be that I've not understood the meanings of the registers correctly.
pkd

Re:Setup Kernel stack and reload register limit

Post by pkd »

Hi.

With Question 2 & 3 you have set the Granularity bit
in both your code & data selectors what this does is multiply the limit by 4096, which give you access to the full 4 gigs

DATA_SELECTOR equ $-gdt
dw 0xFFFF ; limit bit 7 - 0 and 15 - 8
dw 0x0000 ; base 0 - 15
db 0x00 ; base 16 - 23
db 10010010b ; access byte
db 11001111b
^ <-- Granularity bit
db 0x00

Hope this helps
pkd.
ich_will

Re:Setup Kernel stack and reload register limit

Post by ich_will »

thank you for reposting.
I change the line mov esp, 0xFFFF:

reload_cs:
mov eax, STACK_SELECTOR
mov ss, eax
   mov esp, 0xFFFF <---------------
to mov esp, 0x9FBFF but it doesn't work to. But i dont know why. Do I have to set the esp register to a specific value or something like that?
Dreamsmith

Re:Setup Kernel stack and reload register limit

Post by Dreamsmith »

Okay, unless I'm misreading your code, you're setting the base of your stack segment to 0x8FBFF, with a limit of 0x10000 with granularity 4K for a total size of 0x10001000 bytes. So, your stack segment starts at memory address 0x8FBFF and extends to memory address 0x10090BFE inclusive. Since you're then setting your ESP to 0x9FBFF, your stack pointer starts out pointing at memory address 0x12F7FE. Is that actually what you want?

Are you sure you even want a seperate stack segment descriptor? Most people just load SS with their data segment descriptor. I suspect what you actually want to happen is what would happen if you changed "mov eax, STACK_SELECTOR" to "mov ax, DATA_SELECTOR". That's what you want to do if you want to use a flat memory model.

Otherwise, if you're sticking with a segmented memory model, keep in mind that ESP contains an offset into the stack segment, not a memory address. You might want to play with the "grows down" bit in the segment descriptor, too.
ich_will

Re:Setup Kernel stack and reload register limit

Post by ich_will »

thank you, I missunderstood everything. I will try to change my code.
Post Reply