OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Apr 23, 2024 6:20 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: GDT Not Working!
PostPosted: Mon Mar 21, 2011 10:20 am 
Offline

Joined: Thu Dec 23, 2010 12:34 pm
Posts: 9
I have decided to write an OS. So far I have set up the screen and booted from GRUB. But as soon as it sets up the GDT it stops being able to display anything on the screen. Here is the code for the GDT and my linker script:

link.ld:
Code:
ENTRY(start)
SECTIONS
{
  .text 0x100000 :
  {
    code = .; _code = .; __code = .;
    *(.text)
    . = ALIGN(4096);
  }

  .data :
  {
     data = .; _data = .; __data = .;
     *(.data)
     *(.rodata)
     . = ALIGN(4096);
  }

  .bss :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
    . = ALIGN(4096);
  }

  end = .; _end = .; __end = .;
}


gdt.s:
Code:
section .data

gdt:
null:
dq 0

code:
dw 0xFFFF
dw 0

db 0
db 10011010b
db 01001111b
db 0

data:
dw 0xFFFF
dw 0

db 0
db 10010010b
db 01001111b
db 0

gdt_end

gdt_desc:
dq gdt_end - gdt
dd gdt


section .text
global gdt_setup

gdt_setup:

xor ax,ax
mov ds,ax

lgdt [gdt_desc]

mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax

jmp 0x08:flush
flush:
ret


I don't know what is wrong with it. Does anybody know how to fix it?


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Mon Mar 21, 2011 12:42 pm 
Offline
Member
Member

Joined: Sun Oct 17, 2010 2:21 pm
Posts: 221
Location: United Kingdom
It looks to me as if you are loading protected mode segment selectors before switching to protected mode (by updating cr0).


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Mon Mar 21, 2011 1:02 pm 
Offline

Joined: Thu Dec 23, 2010 12:34 pm
Posts: 9
Casm wrote:
It looks to me as if you are loading protected mode segment selectors before switching to protected mode (by updating cr0).

So before I run the lgdt instruction I have to do this?:
Code:
mov eax, cr0
or eax, 1
mov cr0, eax


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Mon Mar 21, 2011 1:06 pm 
Offline

Joined: Thu Dec 23, 2010 12:34 pm
Posts: 9
That didn't seem to work. I don't know if I'm doing it in the right place.


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Mon Mar 21, 2011 1:15 pm 
Offline

Joined: Thu Dec 23, 2010 12:34 pm
Posts: 9
I've changed the code around a bit and it now looks like this:
Code:
bits 32

section .data

gdt:
null:
dq 0

code:
dw 0xFFFF
dw 0

db 0
db 10011010b
db 01001111b
db 0

data:
dw 0xFFFF
dw 0

db 0
db 10010010b
db 01001111b
db 0

gdt_end

gdt_desc:
dq gdt_end - gdt
dd gdt


section .text
global gdt_setup

gdt_setup:

cli

xor ax,ax
mov ds,ax

lgdt [gdt_desc]

mov eax, cr0
or eax, 1
mov cr0, eax

jmp 0x08:.flush
.flush:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
ret


And in case it is useful here is main.c:
Code:
#include <system.h>
#include <screen.h>

extern void gdt_setup();

void setup();

void main()
{
  setup();
 
  puts("The GDT has been set up!");
}

void setup()
{
  gdt_setup();
  clear(0, 0x0F);
}


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Mon Mar 21, 2011 5:39 pm 
Offline
Member
Member
User avatar

Joined: Wed Oct 27, 2010 4:53 pm
Posts: 1150
Location: Scotland
Quote:
db 01001111b

Try changing the two occurrances of this to 11001111b

I'm can't remember what bit-7 of it does, but that's the value I use.

_________________
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Tue Mar 22, 2011 11:58 am 
Offline

Joined: Thu Dec 23, 2010 12:34 pm
Posts: 9
DavidCooper wrote:
Quote:
db 01001111b

Try changing the two occurrances of this to 11001111b

I'm can't remember what bit-7 of it does, but that's the value I use.

That bit is the granularity. 0 means byte granularity and 1 means page granularity. My limit uses byte granularity.


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Tue Mar 22, 2011 4:45 pm 
Offline
Member
Member
User avatar

Joined: Wed Oct 27, 2010 4:53 pm
Posts: 1150
Location: Scotland
jfl wrote:
DavidCooper wrote:
Quote:
db 01001111b

Try changing the two occurrances of this to 11001111b

I'm can't remember what bit-7 of it does, but that's the value I use.

That bit is the granularity. 0 means byte granularity and 1 means page granularity. My limit uses byte granularity.

Yes, I've checked that - you're limiting yourself to a 1MB range instead of 4GB, but while that's unusual it shouldn't stop you accessing the screen.

Code:
jmp 0x08:.flush
.flush:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
ret

You haven't shown how you're trying to print to the screen, but to narrow down where the problem is, why not try adding a bit of code just before the ret in the bit above to print to the screen from there. I work directly in machine code directly using decimals, so I'd put 120 in al, 12 in ah, 0,128,11,0 in edi and post ax to the screen with 102,171 (thereby printing a red capital X to the top left corner of the screen). In assembler that would be something like:-

Code:
mov al,0x78
mov ah,0x0C
mov edi,000B8000h // check that value - I'm not great with hex
stosw // check that too - I'm trying to represent the instruction that sends
          // ax to the address in edi


My own code to jump switch from real mode to 32-bit protected mode is as follows, but I'm only giving it to you so you can see if your own code is doing something radically different in case it helps: 250 (disable interrupts), 51 192 (ax=0), 142 208 (ss=0), 188 0 124 (sp = address where boot sector is loaded in, so stack will run downwards from there), 176 209 230 100 (send 209 to port 100), 176 223 230 96 (and 223 to port 96 - A20 now on to open up whole memory range of machine), 190 196 124 (si = address of lgdt pointer to GDT - see below), 15 1 20 (load GDT), 15 32 192 (mov eax, cr0), 12 1 (or ah, 1), 15 34 192 (mov cr0, eax - switch to protected mode made), 102 234 172 125 0 0 8 0 (jump to next byte to load cs).

The thing I called the lgdt pointer is a block of 8 bytes, the first two of which in my case are 39, 0 (which is 5 times 8 minus 1 because I have five entries in my GDT - as you only have three entries you should make these 23, 0 instead), then the two-byte address of the start of your GDT, then four zero bytes (though I can't remember if segment values are part of that - my GDT's in the bottom 64KB of memory so they would be zero anyway).

_________________
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Tue Mar 22, 2011 10:14 pm 
Offline
Member
Member
User avatar

Joined: Sat Jul 17, 2010 12:45 am
Posts: 487
Here's a help from my side with modification to your code:
Code:
bits 32

section .data

gdt:
null:
dq 0

code:
dw 0xFFFF
dw 0

db 0
db 10011010b
db 01001111b
db 0

data:
dw 0xFFFF
dw 0

db 0
db 10010010b
db 01001111b
db 0

gdt_end

gdt_desc:
dq gdt_end - gdt    ; Replace this with: dw gdt_end - gdt - 1
dd gdt


section .text
global gdt_setup

gdt_setup:

cli

xor ax,ax
mov ds,ax

lgdt [gdt_desc]

mov eax, cr0
or eax, 1
mov cr0, eax

jmp 0x08:.flush
.flush:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
ret


Good to help!
Please look at the Intel's manual for more info about GDTR register.

_________________
Programming is not about using a language to solve a problem, it's about using logic to find a solution !


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Wed Mar 23, 2011 9:39 am 
Offline

Joined: Thu Dec 23, 2010 12:34 pm
Posts: 9
DavidCooper wrote:
jfl wrote:
DavidCooper wrote:
Try changing the two occurrances of this to 11001111b

I'm can't remember what bit-7 of it does, but that's the value I use.

That bit is the granularity. 0 means byte granularity and 1 means page granularity. My limit uses byte granularity.

Yes, I've checked that - you're limiting yourself to a 1MB range instead of 4GB, but while that's unusual it shouldn't stop you accessing the screen.

Code:
jmp 0x08:.flush
.flush:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
ret

You haven't shown how you're trying to print to the screen, but to narrow down where the problem is, why not try adding a bit of code just before the ret in the bit above to print to the screen from there. I work directly in machine code directly using decimals, so I'd put 120 in al, 12 in ah, 0,128,11,0 in edi and post ax to the screen with 102,171 (thereby printing a red capital X to the top left corner of the screen). In assembler that would be something like:-

Code:
mov al,0x78
mov ah,0x0C
mov edi,000B8000h // check that value - I'm not great with hex
stosw // check that too - I'm trying to represent the instruction that sends
          // ax to the address in edi


My own code to jump switch from real mode to 32-bit protected mode is as follows, but I'm only giving it to you so you can see if your own code is doing something radically different in case it helps: 250 (disable interrupts), 51 192 (ax=0), 142 208 (ss=0), 188 0 124 (sp = address where boot sector is loaded in, so stack will run downwards from there), 176 209 230 100 (send 209 to port 100), 176 223 230 96 (and 223 to port 96 - A20 now on to open up whole memory range of machine), 190 196 124 (si = address of lgdt pointer to GDT - see below), 15 1 20 (load GDT), 15 32 192 (mov eax, cr0), 12 1 (or ah, 1), 15 34 192 (mov cr0, eax - switch to protected mode made), 102 234 172 125 0 0 8 0 (jump to next byte to load cs).

The thing I called the lgdt pointer is a block of 8 bytes, the first two of which in my case are 39, 0 (which is 5 times 8 minus 1 because I have five entries in my GDT - as you only have three entries you should make these 23, 0 instead), then the two-byte address of the start of your GDT, then four zero bytes (though I can't remember if segment values are part of that - my GDT's in the bottom 64KB of memory so they would be zero anyway).

I used this just before the ret statement and it didn't work:
Code:
mov [0xb8000],dword 15 << 7 | 0x78


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Wed Mar 23, 2011 9:46 am 
Offline

Joined: Thu Dec 23, 2010 12:34 pm
Posts: 9
Chandra wrote:
Here's a help from my side with modification to your code:
Code:
bits 32

section .data

gdt:
null:
dq 0

code:
dw 0xFFFF
dw 0

db 0
db 10011010b
db 01001111b
db 0

data:
dw 0xFFFF
dw 0

db 0
db 10010010b
db 01001111b
db 0

gdt_end

gdt_desc:
dq gdt_end - gdt    ; Replace this with: dw gdt_end - gdt - 1
dd gdt


section .text
global gdt_setup

gdt_setup:

cli

xor ax,ax
mov ds,ax

lgdt [gdt_desc]

mov eax, cr0
or eax, 1
mov cr0, eax

jmp 0x08:.flush
.flush:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
ret


Good to help!
Please look at the Intel's manual for more info about GDTR register.

I tried the change you said and it still didn't work.

I have attached a screenshot. It should be cleared and display a message but that doesn't happen.

Here is my monitor code written in c:
screen.h:
Code:
#ifndef SCREEN_H
#define SCREEN_H

void clear(unsigned char background, unsigned char foreground);
void putch(const char c);
void puts(const char *s);

#endif

screen.c:
Code:
#include <screen.h>
#include <system.h>

unsigned short *vmem = (short *) 0xB8000;

short colours;

unsigned int x = 0, y = 0;

static void cursor()
{
  unsigned short tmp = y * 80 + x;
 
  outb(0x3D4, 14);
  outb(0x3D5, tmp >> 8);
  outb(0x3D4, 15);
  outb(0x3D5, tmp);
}

static void scroll()
{
  unsigned short space = (colours << 8) | 0x20;
  unsigned short tmp;
 
  if(y >= 25)
  {
    tmp = y - 24;
    memcpy((char *) vmem, (char *) vmem + tmp * 80, 160 * (25 - tmp));
   
    memsetw (vmem + (25 - tmp) * 80, space, 80);
  }
}

void clear(unsigned char background, unsigned char foreground)
{
  colours = ((background << 4) | foreground) << 8;
  short space = colours | 0x20;
 
  memsetw(vmem, space, 1920);
 
  x = y = 0;
 
  cursor();
}

void putch(const char c)
{
   if(c == 0x7) /* write code to make a noise!!!!!!!*/;
   else if(c == 0x8)
   {
     if(x != 0 && y != 0)
     {
       if(x = 0)
       {
    y--;
    x = 80;
       }
       else x--;
     }
   }
   else if(c == 0x9) x = (x+8) & ~(8-1);
   else if(c == 0xD) x = 0;
   else if(c > 0x1F && c < 0x7F)
   {
     vmem[y * 80 + x] = colours | c;
     x++;
   }
   
   if (x >= 80)
   {
       x = 0;
       y++;
   }
   scroll();
   cursor();
}
void puts(const char *s)
{
  int i = 0;
  while (s[i])
  {
    putch(s[i++]);
  }
}


I use GRUB Legacy for booting.


Attachments:
snapshot1.png
snapshot1.png [ 40.25 KiB | Viewed 3340 times ]
Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Wed Mar 23, 2011 10:06 am 
Offline
Member
Member
User avatar

Joined: Sat Jul 17, 2010 12:45 am
Posts: 487
jfl wrote:
I tried the change you said and it still didn't work.

One thing I'm sure is that, you didn't check the Intel's manual, did you?

I just made a small modification so that you could figure out the rest. But you seem to be too noob for that.
Okay, this time some more modifications:
Code:
gdt_end

which should be actually declared as a label like this,
Code:
gdt_end:


Oh come on, should I make whole lots of changes?
Replace you entire descriptor table code with this:
Code:
gdt:                       ; Address for the GDT

gdt_null:                  ; Null Segment
        dd 0
        dd 0

gdt_code:                  ; Code segment, read/execute, nonconforming
        dw 0ffffh         ; Limit 4 GB
        dw 0         ; Base 0
        db 0
        db 10011010b
        db 11001111b
        db 0

gdt_data:                  ; Data segment, read/write, expand down
        dw 0ffffh         ; Limit 4 GB
        dw 0         ; Base 0
        db 0
        db 10010010b
        db 11001111b
        db 0


gdt_end:                   ; Mark as the end label, will be used to calculate the size of GDT



gdt_desc:                          ; The GDT descriptor
        dw gdt_end - gdt - 1       ; Limit (size)
        dd gdt                     ; Address of the GDT


Before anyone accuses me with the sin of spoon-feeding, I'm out of here.
Good to help again!

_________________
Programming is not about using a language to solve a problem, it's about using logic to find a solution !


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Wed Mar 23, 2011 10:15 am 
Offline
Member
Member
User avatar

Joined: Tue Feb 08, 2011 1:58 pm
Posts: 496
You have several mistakes in your code:
1. you do not specify "bit 16", so the code before the jump will be compiled for protected mode and you execute it in real mode.
2. if you call gdt_setup from real mode, the stack will contain a real mode return address. When you make a ret in protmode, it interpreted as linear address, and that's obviously won't work.

Code:
bit 16
gdt_setup:
...
jmp 0x08:.flush
bit 32
.flush:

and to get the correct return address, you should know it's called with a near or a far call. You should do something like
Code:
gdt_setup:
xor ebp, ebp
pop bp

and instead of a ret
Code:
jmp ebp

If it was a far call, the stack contains to words (each 16 bits): segment and offset, so you have to calculate seg<<4+offs, and jump there.


Top
 Profile  
 
 Post subject: Re: GDT Not Working!
PostPosted: Wed Mar 23, 2011 10:42 am 
Offline

Joined: Thu Dec 23, 2010 12:34 pm
Posts: 9
Thanks! It finally works!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: SemrushBot [Bot] and 114 guests


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 post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group