simeonz wrote:
db 00100000b, should be db 00010000b or db 00000000b. You are setting the long mode flag for the TSS, but it needs to be always cleared (even for 64-bit TSS)
OK, that would probably do it. There may be other issues as well, but that alone would be a showstopper.
I will add something that occurred to me earlier: the OP would do well to look at the macro and structure-definition features of their assembler (I am guessing it is NASM, but I am not sure) as a way of simplifying these declarations, both for avoiding repetition (by using the default initializations, if it allows them) and for making the setting process more meaningful by giving names to the fields and so forth.
You could, for example, have a struct definition like this NASM version:
Code:
struc GDT_Entry
.limit_0_15 resw 1
.base_0_15 resw 1
.base_16_23 resb 1
.access resb 1
.flags_limit_16_19 resb 1
.base_24_31 resb 1
endstruc
Which would at least let you then do this:
Code:
Pr_Shift equ 7
DPL_Shift equ 5
ST_Shift equ 4
Ex_Shift equ 3
DC_Shift equ 2
RW_Shift equ 1
Ac_Shift equ 0
G_Shift equ 7
DB_Shift equ 6
L_Shift equ 5
istruc GDT_Entry
at .limit_0_15, dw 0xFFFF
at .base_0_15, dw 0x0000
at .base_16_23, db 0x00
at .access, db (1 << Pr_Shift) & (0 << DPL_Shift) & (1 << ST_Shift) & (1 << Ex-Shift) & (0 << DC_Shift) & (1 << RW_Shift) & (0 << Ac_Shift)
at .flags_limit_16_19, db 0x0F & (1 << G_Shift) & (1 << DB_Shift) & (0 << L_Shift)
at .base_24_31, db 0x00
iend
And then have a macro that takes the actual values you want by name, rather than the byte and bit values, and automagically combine them into the fields for you:
Code:
%macro Make_GDT_Entry 0-10 0, 1, 1, 0, 1, 0, 1, 1, 0, 0x00000000, 0x00FFFFFF
istruc GDT_Entry
at .limit_0_15, dw (%9 & 0x000FFFF)
at .base_0_15, dw (%10 & 0x0000FFFF)
at .base_16_23, db ((%9 & 0x00FF0000) >> 16)
at .access, db 0x80 & (%0 << DPL_Shift) & (%1 << ST_Shift) & ((%2 & %0) << Ex-Shift) & ((%3 & %0) << DC_Shift) & ((%4 & %0) << RW_Shift) & ((%5 & %0) << Ac_Shift)
at .flags_limit_16_19, db ((%10 & 0x00FF0000) >> 16) & (%6 << G_Shift) & (%7 << DB_Shift) & (%8 << L_Shift)
at .base_24_31, db ((%9 & 0xFF000000) >> 24)
iend
%endmacro
Which, if used with just the defaults,
Code:
GDT:
NULL_Descriptor: dq 0
; 32-bit code segment descriptor
Code32:
Make_GDT_Entry
would give you the descriptor you were using. For a System segment, you could use,
Code:
; 32-bit kernel segment descriptor
Kernel32:
Make_GEDT_Entry 0
which would be the same, except it would leave S, X, DC, RW, and Ac cleared.
(Note that this isn't tested code, so I may have some mistakes in it.)
You could, of course, make more specialized macros at your discretion. You would naturally need to adjust these to fit you assembler.