I am facing a similar problem to other users, but after searching
Google Groups, I find no concrete solution to #task switches#/
So, here I am, with some basic code to guide all of us into making a
How-To for prosperity. There are many reasons why I'd like to see this
happen. Namely, to help others like me, making their first OS in ASM.
But, mostly because in all the OS Dev labs / websites Ive visited,
nothing is out there on this subject. It seems to be a closely guarded
secret, and that is not possible in today's Open Source society!!!
So, here is some PD code, wrote by myself, for us to work on at our
leisure, until we hack together something that works for the
community.
The code;
mov ebx, TSS_Main ; Task Main
mov WORD [ebx+TSS_IOBitBase], 0x68 ; I/O Permissions
mov WORD [ebx+TSS_TrapBit], 0
mov DWORD [ebx+TSS_LDT], 0x00
mov DWORD [ebx+TSS_GS], 0x10
mov DWORD [ebx+TSS_FS], 0x10
mov DWORD [ebx+TSS_ES], 0x10
mov DWORD [ebx+TSS_DS], 0x10
mov DWORD [ebx+TSS_SS], 0x18
mov DWORD [ebx+TSS_CS], 0x08
mov DWORD [ebx+TSS_ESP], 0xFFFF
mov DWORD [ebx+TSS_EFlags], 0x202
mov DWORD [ebx+TSS_SS0], 0x18
mov DWORD [ebx+TSS_ESP0], 0xFFFF
mov DWORD [ebx+TSS_EIP], inf
inc DWORD [CurrGDesc] ; 0x40 Data Segment for Tasks
mov eax, TSS_Main
mov ebx, sTSS
; mov dx, TS_Access
; mov cx, TS_Attrib
mov dx, 0x89
mov cx, 0x00
call Add_GD2
Basically, this all starts at the top of the code segment. Here, we
define a memory location of where the Task State Segment is located in
RAM, then move that memory address into EBX. Next, we use memory
offsets (given below) to 'fill in' with data.
Here are the memory offsets I've accepted as defuncto!
sTSS EQU 104
TSS_BackLink EQU 0 ;DW 0000h,0000h ; Task Selector of Interrupted
TASK
TSS_ESP0 EQU 4 ;DD 00000000h ; Top of Stack for Prot Level 0
TSS_SS0 EQU 8 ;DW 0000h,0000h ; Selector for Prot Level 0 Stack
TSS_ESP1 EQU 12 ;DD 00000000h ; Top of Stack for Prot Level 1
TSS_SS1 EQU 16 ;DW 0000h,0000h ; Selector for Prot Level 1 Stack
TSS_ESP2 EQU 20 ;DD 00000000h ; Top of Stack for Prot Level 2
TSS_SS2 EQU 24 ;DW 0000h,0000h ; Selector for Prot Level 2 Stack
TSS_CR3 EQU 28 ;DD 00000000h ; Physical Address of Page Directory
TSS_EIP EQU 32 ;DD 00000000h ; Extended Instruction Pointer
TSS_EFlags EQU 36 ;DD 00000000h ; Extended Flags
TSS_EAX EQU 40 ;DD 00000000h ; General Purpose Registers
TSS_ECX EQU 44 ;DD 00000000h ;
TSS_EDX EQU 48 ;DD 00000000h ;
TSS_EBX EQU 52 ;DD 00000000h ;
TSS_ESP EQU 56 ;DD 00000000h ; Top of Stack for Current Prot Level
TSS_EBP EQU 60 ;DD 00000000h ; Base Frame Pointer (64 bytes to
here)
TSS_ESI EQU 64 ;DD 00000000h ; Source Index Register
TSS_EDI EQU 68 ;DD 00000000h ; Destination Index Register
TSS_ES EQU 72 ;DW 0000h,0000h ; E Selector (Extra)
TSS_CS EQU 76 ;DW 0000h,0000h ; C Selector (Code)
TSS_SS EQU 80 ;DW 0000h,0000h ; S Selector (Stack Curr Prot Level)
TSS_DS EQU 84 ;DW 0000h,0000h ; D Selector (Data)
TSS_FS EQU 88 ;DW 0000h,0000h ; F Selector (Extra)
TSS_GS EQU 92 ;DW 0000h,0000h ; G Selector (Extra)
TSS_LDT EQU 96 ;DW 0000h,0000h ; LDT Selector ( ALWAYS 0) (100)
TSS_TrapBit EQU 100 ;DW 0000h ; 1 = DEBUG; 0 = NODEBUG
TSS_IOBitBase EQU 102 ;DW 1111111111111111b ; NULL I/O Permission Bit
Map
As you can see, the usual s(ize)TSS is 104 Bytes and each of these
EQUates, lists some data that is required for the task switch. So, I'd
like to know what the MINIMAL list of EQUates are required to be
filled in before task switching can occur.
The stage I am at right now is attempting to fill in all the EQUates ~
then load the GDT with the following command;
lgdt [Loader]
This command works just fine with my pre-existing GDT ~ but _not_ when
I call LGDT after establishing the code above into the GDT...strange,
hey?
So, my questions are thus;
i) How to perform a minimalistic task switch?
ii) Any automation tips?
iii) Try to keep all information relevant to task switches inside this
thread to create a How-To...for future generations...to come.
Peace out and love in,
Cat
I've furthered the code for this MT objective. Here is it below;
inc DWORD [CurrGDesc] ; 0x40 TSS Descriptor
mov eax, sTSS
mov ebx, 0x0089
mov edx, TSS_Main
call AddTSSDesc
mov ebx, TSS_Main ; Task Main
mov WORD [ebx+TSS_IOBitBase], 0xff ; I/O Permissions
mov WORD [ebx+TSS_TrapBit], 0
mov DWORD [ebx+TSS_LDT], 0x00
mov DWORD [ebx+TSS_GS], 0x10
mov DWORD [ebx+TSS_FS], 0x10
mov DWORD [ebx+TSS_ES], 0x10
mov DWORD [ebx+TSS_DS], 0x10
mov DWORD [ebx+TSS_SS], 0x18
mov DWORD [ebx+TSS_CS], 0x30
MOV DWORD [ebx+TSS_EFlags],00000202h ; Load the Flags
Register
mov DWORD [ebx+TSS_SS0], 0x18
mov DWORD edx, PLTaskStack
mov DWORD [ebx+TSS_SS], edx
mov DWORD [ebx+TSS_ESP0], edx
mov DWORD edx, inf
mov DWORD [ebx+TSS_EIP], edx
;cli
lgdt [Loader]
;sti
mov edi, GD_Table ; Get offset of Current Global
Table Descriptor
mov eax, 8 ; Multiple by 8 bytes...
mov ebx, [CurrGDesc] ; ...the Current Global
Descriptor Counter
mul ebx ; Put the sum in EAX
add edi, eax ; Add eax to edi to point to
descriptor in GDT.
sub edi, GD_Table ; Get Descriptor Address
mov [eax], edi ; Sort it in eax
ltr word [eax] ; Let's bring the bass back,
baby!
jmp 0x08:inf
mov edi, LTR_Message
mov ecx, LTR_Length
call Print
As you can see, I'm playing about with this code for fun and profit!
But, I have another problem...
The problem, or error/bug, is thus; When issuing LGDT [Loader+0x08]
the VMWare Player issues this error message [see photo below]
http://img.photobucket.com/albums/v723/catcalls/MT_1.png
This is the error I receive on MTasking the OS. Weird, hey? Never seen
anything like this, and only happens when I re-issue the LGDT
directive inside VMWare Player after establishing a TSS Descriptor!
Any help furthering the goal of this How-To?
Cat