From OSDev Wiki
Jump to: navigation, search

For each Task we want to set up, the Main Executive Task will perform the following steps:

  1. Prepare the LDT (Demo/Exec/User/LDT)
    1. Allocate memory for an LDT, and put a descriptor for it in the GDT
    2. Allocate memory for a Ring0 Stack, and put a descriptor for it in the LDT
    3. Allocate memory for a Ring3 Stack, and put a descriptor for it in the LDT
    4. Allocate memory for a Data Segment, and put a descriptor for it in the LDT
    5. Put a descriptor for the Code Segment in the LDT (share code among all tasks!)
  2. Prepare the TSS (Demo/Exec/User/TSS)
    1. Allocate memory for a TSS, fill it in, and put a descriptor for it in the GDT

Note that the last step will make the new TSS runnable: a new Program has been created!

Each new Task needs to be assigned a different area of the screen to modify. This information is easiest passed into the Task by altering its starting registers. We could modify the Task's Data Segment instead - that is left as an exercise for the reader!

Once all the Tasks have been created, there's nothing for the Main Task to do. It might as well simply HLT - but an Interrupt will take it out of HLT, so JMP back and do it all again! Or, we could simply remove the Main Task's TSS from the run queue. (Run queue? Run queue!? What's that?)

Of course, this is also a perfect location to insert some test code: MOV ESP,1 anybody?


; Exec/User/
; Now that everything is set up, we can start to generate User-mode Programs.
; Each Program is essentially the same: code that bounces a ball around its
; defined area of the screen. To fully demonstrate the features of Protected
; Mode, the following is used:
; 1) The Code runs in User Mode (Ring 3);
; 2) Every Program has its own LDT;
; 3) The CPU's Task Switching mechanism using TSSs is used;
; 4) Every Program has its own Stacks and Data, but shares the same Code.
; Once all the Tasks have been set up, the Executive merely waits for
; <Ctrl><Alt><Del> to be pressed - and then resets the computer... At least it
; would: that's been left as an exercise for the reader. At the moment, you can
; use the trusty Power button!
%push Exec.Start ; Let's not leave these %defines just lying around...
%define         %$Pos           EBP - 4
%define         %$LDT           EBP - 8
%include        "Exec/User/" ; Creates one LDT for a User-mode Program
%include        "Exec/User/" ; Creates one TSS for a User-mode Program
                ENTER           8, 0
                XOR             EDX,EDX         ; Zero high part of EDX
;               MOV             DL, 0           ; Start full left
                MOV             DH, 1           ; Start one row low
                MOV             [%$Pos],EDX     ; Store away new position
                ; Create a new User LDT
                CALL            Exec.User.LDT
                TEST            EAX,EAX
                JZ              .Finished
                ; Create a TSS to run that User Task
                CALL            Exec.User.TSS
                TEST            EAX,EAX
                JZ              .Finished
                MOV             EDX,[%$Pos]              ; Current position
                ADD             DL,Window.Width          ; Next Window
                CMP             DL,VGA.Cols-Window.Width ; Too far?
                JBE             .Loop                    ; Not yet...
                MOV             DL,0            ; Start at left again
                ADD             DH,Window.Height          ; Next row
                CMP             DH,VGA.Rows-Window.Height ; Too far?
                JBE             .Loop                     ; Not yet...
; Wait for <Ctrl><Alt><Del>
                JMP             .Finished
Personal tools