User:Johnburger/Demo/User/LDT
The LDT cannot be hard-coded at assembly time: there are lots of them, and they need to be built directly in memory by the Executive. But the User code needs to know the values of the different segment Selectors, so a common definition is useful.
You'll also see that the Stack sizes are defined here. Multiple stacks? Yes. A requirement of Protected Mode programming is that User mode programs cannot affect the system - and if a rogue program nearly runs out of stack, the system won't have enough room to perform its critical functions, like servicing interrupts.
So every time the system needs to do a Supervisor mode operation, it switches to its own stack, as defined in the current TSS. In fact, up to four Stacks can be defined: one for each Privilege Level Ring. This Demonstrator only uses Rings 0 and 3 though.
Finally, the source has an assemble-time sanity check in it, to confirm a system-wide inviolate: I need both the Global and all Local Descriptor Tables to have an Alias to themselves, and I need them all to be at the same Selector index: DT.Alias
. That way I can access them in other system code easily.
Demo/User/LDT.inc
;
; User/LDT.inc
;
; This defines the LDT that the User program needs.
SEGMENT User.LDT START=0 ALIGN=16 NOBITS
USE32
User.Stack3.Size EQU 0010h ; Doesn't need much at all!
User.Stack0.Size EQU 0200h ; Needs a bit more...
User.LDT:
User.LDT.Alloc RESB LDT.Alloc_size
User.LDT.Alias RESB x86.Desc_size
User.LDT.Stack0 RESB x86.Desc_size
User.LDT.Stack3 RESB x86.Desc_size
User.LDT.Data RESB x86.Desc_size
User.LDT.Code RESB x86.Desc_size
%if (User.LDT.Alias-User.LDT) != DT.Alias
%error "Invalid User LDT alias"
%endif