Alright, I tried to read up on these topics once again so correct me if I'm wrong in my understanding.
In real mode, linear addresses are computed by the segment:offset pair corresponding to the data you want to get. There are separate segment registers for code (%ss) and data (%ds), with the additional extra segments. The address is then the result of the value in the segment register multiplied by 16 (shifted left by 4), plus the offset.
In protected mode segmentation works by referencing a global (or local) descriptor table. This table has 64-bit entries, which contain information about a segment. A special 48-bit register, the GDT register, contains the size of this table, as well as the base address from where the structure begins. The segment selectors now contain an offset into the GDT register, so if the code segment is the second entry into the GDT, it would contain the value of 8, because the descriptor starts at the eighth byte.
I can't see why my segmentation would be broken as I checked that my GDT entries are correct and ensured that at least most of my code complies with the examples given in numerous places... But it actually
is broken and I really can't understand why and it's driving me crazy.
From my latest code edit I get a new type of error:
jump_protected: gate type 0 unsupported
Code: Select all
.section .data
gdt: .quad 0
.byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00
.byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
gdtr: .word 23
.long gdt
.code16
.section .text
.globl boot1
boot1:
cli
/* re-set the stack and segments */
xorw %ax, %ax
movw %ax, %es
movw %ax, %ds
movw $0x7C00, %ax
movw %ax, %ss
movw $0x7CDF, %sp
sti
/* enable A20 line */
movw $0x2401, %ax
int $0x15
/* load the kernel */
/* set up for protected mode */
cli
movl $2, %edi
movw gdt, %eax
orw $0x0100, %eax
movl %eax, gdtr(, %edi, 2)
/* enter protected mode */
lgdt gdtr
movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0
ljmp $0x08, $protected_mode
.code32
protected_mode:
/* update segments */
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %gs
movw %ax, %fs
movw %ax, %ss
movl $0x0001000, %esp
//call kmain
/* NOTREACHED */
halt:
hlt
jmp halt
What's the difference between CS, CS.base and the far jump address?
CS has two meanings depending on real/protected mode (like I wrote above, if it's even correct). CS.base specifies the starting address of the segment in protected mode (are you refering to .base in the CS entry in GDT?). The far jump modifies the code segment when jumping to an address. So when I perform a far jump to protected mode, basically CS gets the value of 8 in order to offset the correct entry in the GDT.