installing own GDT using gdt_flush() why jmp 0x08:flush2

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
redDot
Member
Member
Posts: 29
Joined: Sat Jan 26, 2008 2:48 am

installing own GDT using gdt_flush() why jmp 0x08:flush2

Post by redDot »

hello friends,
i have been following the OS tutorial by bran and have been currently studying the topic GDT. What i am finding difficult to understand is the use of the instruction jmp 0x08:flush2 to load the cs with the appropriate value. i understand that 0x08 is the location for the kernel code in the GDT created to be installed, but i don't understand how the jmp statement is loading the code segment with the base address of the kernel code.

the code is,
global _gdt_flush
extern _gp
_gdt_flush:
lgdt [_gp]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2
flush2:
ret

thank you for your time. any help and suggestion will be extremely appreciated.
cyr1x
Member
Member
Posts: 207
Joined: Tue Aug 21, 2007 1:41 am
Location: Germany

Post by cyr1x »

The lgdt instruction loads a pointer to a GDT
Now lets say our GDT looks like this

Code: Select all

; null-descriptor
dq 0
;kernel-code-segment (this is offset 0x8)
dw 0xFFFF		;limit
dw 0x0000		;base low
db 0x00			;base middle
db 0x9A			;access
db 0xCF			;gran
db 0x00			;base high
;kernel-data-segment (this is offset 0x10)
dw 0xFFFF
dw 0x0000
db 0x00
db 0x92
db 0xCF
db 0x00	
Now, when you do a far jmp like

Code: Select all

 jmp 0x08:somelocation 
it loads the GDT-Entry from the gdt-pointer with the offset 0x08 and loads the base, limit, etc.. of the entry
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

First, use the "code" tag, it makes code easier to read.

Code: Select all

global _gdt_flush
extern _gp
_gdt_flush:
lgdt [_gp]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2
flush2:
ret
What happens here is the GDT is loaded into the CPU GDTR (see the intel manuals for information about htis) and then the segments are loaded with 0x10 - which is typically the kernel data segment. Then,

Code: Select all

jmp 0x08:flush2
is written to load CS from the GDT. You can't manually modify CS, and the only way the CPU will load it's attributes (limit, flags, etc...) is by performing this action to reset the code segment.
Post Reply