GDT gone with the wind

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
TexHawk

GDT gone with the wind

Post by TexHawk »

I keep getting these memory exceptions and I have traced the problem to the first instance that I attempt to use a selector from the GDT after jumping into protected mode.  I am trying to do all of this in the bootsector so I figured that the following code could load the GDT address.

lgdt[ds:gdtr]

where gdtr is:

gdtr
     dw gdt_end-gdt-1    ;where gdt and gdt_end mark the beginning and end of gdt
     dd gdt

I have checked the syntax of the GDT and the selectors have been built properly but I'm getting the feeling that I'm not correctly passing the actual base address of the GDT.  Thanks for anyone who can shed some light on this.
Xenos

RE:GDT gone with the wind

Post by Xenos »

The '-1' in the gdt limit makes me wonder: I don't have a '-1' there and it works.
How does your 'jmp' into pmode look like? I would expect a far jump (which needs a selector, of course).
Adek336

RE:GDT gone with the wind

Post by Adek336 »

unless your bootsector is loaded at 0000:0000 it wont work. the base adress is CS << 4 + GDT not just GDT. As we dont know CS on linking, we have to use a runtime patch:

. . .

   xor eax, eax
   mov ax, cs
   shr eax, 4

   add dword [GDTR+2], eax

. . .
  



GDTR:
  dw gdt_end - gdt_start - 1 ;the ¨-1¨ is correct
  dd gdt_start

Cheers,
Adrian
Dr. 128 Bit

RE:GDT gone with the wind

Post by Dr. 128 Bit »

Note that the gdt address in the gdtr must be an _ABSOLUTE_ address, so if you have your segment starting at 0x7C00 (for example) and you have an origin (ORG) statement set to 0x0000, your gdt address will be relative to your DS segment.

For example (relative addresses on the left):
DS = 0x7C00
ORG = 0x0000

0x00000000 gdtr:
0x00000000  dw gdt_end - gdt - 1
0x00000002  dd gdt ; The processor think that the GDT is at address 0x06, but its absolute address is 0x7C06

0x00000006 gdt:
              ...

absolute address = segment base + relative address
  
TexHawk

RE:GDT gone with the wind

Post by TexHawk »

Well I do use an org=0x0000 statement and now understand how the addressing works but I don't think I'm getting the big picture.  

Adek said to use the following code

xor eax,eax
mov ax,cs
add dword [GDTR+2], eax

             ;and I assumed load the gdtr with...

lgdtr[eax]   ;This might be a poor assumption


GDTR:
     dw gdt_end-gdt-1
     dd gdt

However when I do this I'm still triple faulting at this instruction:


jmp CODE_SEL:pmode


where CODE_SEL is an index into my GDT.  Adek and Dr. 128 Bit seem to be saying the same thing but I *think* that I'm doing it but still I seem to be missing something.  Thanks for the help guys.
Xenos

RE:GDT gone with the wind

Post by Xenos »

Try the following: Make a short jump to your far jump after loading the GDT. I don't know why, but this works with my OS.

jmp near nearlabel

nearlabel:
jmp far CODE_SEL:pmode
Adek336

RE:GDT gone with the wind

Post by Adek336 »

you are not loading your gdt correctly. instead try:

push cs
pop ds
lgdt [ds:gdtr]


Cheers,
Adrian
Adek336

RE:GDT gone with the wind

Post by Adek336 »

damn there´s another error. look: GDTR.base is equal to the linear adress of your code segment + offset of your gdt. Linear adress is CS << 4, and offset is gdt.

..
xor eax, eax
mov ax, cs
shr ax, 4           ; in eax there is the linear adress of the code segment

add eax, gdt       ; we add the gdt´s offset
mov dword [gdtr + 2], eax
...

we can now load the gdt. we have to point to the GDTR, for example DS relative:
push cs
pop ds         ; we have to get a correct value inside

lgdt [ds:gdtr] ; the GDTR is at offset gdtr DS relative

If it doesn´t work, try this at the beginning of your code:

[ORG 0] ; this is what dr128bit said
JMP 0x7C0:start
start:
...

now we know what segment and offset we are (some bioses put them in 0:0x7c00 some in 0x7c0:0 so we can´t risk it)

cheers,
Adrian
mikeleany

RE:GDT gone with the wind

Post by mikeleany »

It looks like Dr. 128Bit was said the same thing as Adek was TRYING to say, but I think Adek got confused himself when writing his code. Just go back to your original code. With it, if you have org=0x0000, then set up your GDTR like this:

GDTR:
  dw gdt_end - gdt - 1
  dd gdt + 0x7c00

But of course, you would have to make sure that DS was the same as CS (0x07c0)
But what I would recommend is to use org=0x0000 and begin your code with a far jump to 0x0000:0x7c00, and make sure all your seg selectors are at 0x0000. Then you could just use your original code.
mikeleany

RE:GDT gone with the wind - correction

Post by mikeleany »

Correction: if you begin your code with far jump to 0x0000:0x7c00 (as I suggested at the end), use org as 0x7c00 NOT 0x0000.
Post Reply