Setting up new GDT

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
Crazed123

Setting up new GDT

Post by Crazed123 »

I'm setting up a post-GRUB GDT for my kernel, and want to write a function to load the GDT and set the segment registers like the one at http://www.osdever.net/bkerndev/index.php?the_id=90 . How could I do this in Pascal? The compiler is set up to allow inline assembler (even whole routines of it) in Intel format.
AR

Re:Setting up new GDT

Post by AR »

If your GDT is set up in the same way then you should be able to implement the code exactly the same, I don't know whether Pascal takes line labels but it should, it should work fine as is. (Provided the GDT is NULL, Code, Data)
Crazed123

Re:Setting up new GDT

Post by Crazed123 »

I've set mine up as NULL,DATA,CODE, but I know how to switch the numbers. The problem lies in jumping to a new code segment. I've got a way to label a line, but for some damn reason it refuses to accept the jmp instruction.
AR

Re:Setting up new GDT

Post by AR »

If it won't take it then you can create an ASM file and call that from the Pascal code, you will probably need to look through the language guides for inline assembly to see how to implement it properly using the inline assembler.
Crazed123

Re:Setting up new GDT

Post by Crazed123 »

I've looked through the docs. They don't help much. And I tried a seperate asm file to be compiled with nasm, but then had trouble linking my RTL and it both into my final program.
Kim

Re:Setting up new GDT

Post by Kim »

Your lucky i just started an os in freepascal and got new GDT working :)

Code: Select all

procedure kload_gdt(); assembler; [public, alias: 'kload_gdt'];
asm
   //jmp GDT_KERNEL_CODE_SEL:@loadedcs
   //Freepascal will not compile this!
   //But Intel manual says you can use a far ret.
   //RETF executes a far return: after popping IP/EIP, it then pops CS, and then increments the
   //stack pointer by the optional argument if present.
   //Force dword sized push, because retf pops dwords and else the stack will be rong.
   push dword GDT_KERNEL_CODE_SEL
   push dword offset @loadedcs
   lgdt gdtr
   retf
@loadedcs:
   mov ax, GDT_KERNEL_DATA_SEL
   mov ss, ax
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax
end ['EAX'];
Crazed123

Re:Setting up new GDT

Post by Crazed123 »

Thank you so much! ;D

*Crazed bows before master*

Just one more question. In my linker script I have a KERNEL_END variable defined that I use to find the end of kernel memory, including the kernel stack. I want to use this constant in my Pascal code and I've written it as:

Code: Select all

var
 KERNEL_END: longword; external name 'KERNEL_END';
This reference resolves, but the variable always evaluates to zero. In my linker script I write on the very last line before the closing curly-brace of the SECTIONS section:

Code: Select all

KERNEL_END = .;
What's wrong here?
AR (Away)

Re:Setting up new GDT

Post by AR (Away) »

The linker resolves linkscript variables as pointers, KERNEL_END is resolved as a variable located at that point.

In C the way around is:

Code: Select all

extern int KERNEL_END;
printf("Kernel End is at %x", &KERNEL_END); //Notice "Get Reference" symbol
It's cleaner to do this in the linkscript though:

Code: Select all

.data
{
     ...
     KERNEL_DATA = .;
     LONG(KernelEndPoint);
}
...
KernelEndPoint = .;
This creates a variable and stores the kernel end in it.
Crazed123

Re:Setting up new GDT

Post by Crazed123 »

What's the KERNEL_DATA variable for?
AR (Away)

Re:Setting up new GDT

Post by AR (Away) »

Sorry, that was a misspelling, it was ment to be KERNEL_END.
Post Reply