GDT gone with the wind
GDT gone with the wind
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.
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.
RE:GDT gone with the wind
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).
How does your 'jmp' into pmode look like? I would expect a far jump (which needs a selector, of course).
RE:GDT gone with the wind
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
. . .
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
RE:GDT gone with the wind
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
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
RE:GDT gone with the wind
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.
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.
RE:GDT gone with the wind
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
jmp near nearlabel
nearlabel:
jmp far CODE_SEL:pmode
RE:GDT gone with the wind
you are not loading your gdt correctly. instead try:
push cs
pop ds
lgdt [ds:gdtr]
Cheers,
Adrian
push cs
pop ds
lgdt [ds:gdtr]
Cheers,
Adrian
RE:GDT gone with the wind
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
..
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
RE:GDT gone with the wind
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.
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.
RE:GDT gone with the wind - correction
Correction: if you begin your code with far jump to 0x0000:0x7c00 (as I suggested at the end), use org as 0x7c00 NOT 0x0000.