I attach a resume of my code of the things I supose are important for this, if you need the real code, say me.
Also for the ones that dosent whant to take a look here is a resume of the resume .
Code: Select all
jump start2
.
jump_to_tss:
jmp far [bx]
ret
%define MAX_TASK 3
gdt_label: times ((5+MAX_TASK)*DESCR_SEG_size) db 0
gdtr_label: times DESCR_GDTR_size db 0
idt_label: times (0x22 * DESCR_INT_size) db 0
idtr_label: times DESCR_IDTR_size db 0
.
scancode db "@"
.
taskList: times MAX_TASK*DESCR_TSS_size db 0
total_task dw MAX_TASK
cur_task dw 0
task_sel times MAX_TASK dw 0
%define STACK_SIZE 1024
task_stack times STACK_SIZE db 0
.
setup_GDT:
.
; /* 0x28 -- TSS for main() */
mov ax, ds
mov bx, ds
shl ax, 4
shr bx, 12
add ax, taskList
adc bx, 0
invk setup_GDT_entry, (gdt_label +5*DESCR_SEG_size), ax, bx, DESCR_TSS_size, 0, byte ACS_TSS, byte 0
mov word[task_sel], 0x28
; /* 0x30 -- TSS for task() */
.
; /* 0x38 -- TSS for task() */
.
invk setup_GDT_entry, (gdt_label + 7*DESCR_SEG_size), ax, bx, DESCR_TSS_size, 0, byte ACS_TSS, byte 0
mov word[task_sel], 0x38
.
ret
; void setup_PMode()
setup_pmode:
; /* disable interrupts so that IRQs don't cause exceptions */
; /* disable NMIs as well */
call setup_GDT
call setup_IDT
; /* save IRQ masks */
; /* setup PIC */
; setup_PIC (0x20, 0x28);
; /* set new IRQ masks */
; /* saving real mode segment addresses */
; /* WOW!!! This switches us to PMode just setting up CR0.PM bit to 1 */
; /* loading segment registers with PMode selectors */
invk update_cs, 0x8
mov ax, 0x10
mov ds, ax
mov es, ax
mov ax, 0x18
mov ss, ax
; /* if we don't load fs and gs with valid selectors, task switching may fail. */
invk load_fs, 0x10
invk load_gs, 0x10
; /* due to the same reason, let's clear ldtr */
invk load_ldt, gdt_label ;(selector zero)
......
xor cx, cx
mov bx, taskList
xor edx, edx
mov dx, task_stack
.again:
mov eax, 0
mov [bx+DESCR_TSS.trace], ax
mov word[bx + DESCR_TSS.io_map_addr], DESCR_TSS_size
or cx, cx
jz .check
mov [bx+DESCR_TSS.ldtr], eax
mov [bx+ DESCR_TSS.fs], eax
mov [bx+ DESCR_TSS.gs], eax
mov eax, ds
mov [bx + DESCR_TSS.ds], eax
mov [bx + DESCR_TSS.es], eax
mov [bx + DESCR_TSS.ss], eax
mov eax, cs
mov [bx + DESCR_TSS.cs], eax
mov dword[bx+DESCR_TSS.eflags], 0x202
mov [bx+DESCR_TSS.esp], edx
add edx, STACK_SIZE
.check
add bx, DESCR_TSS_size
inc cx
cmp cx, 3
jb .again
mov dword[taskList+1*DESCR_TSS_size+DESCR_TSS.eip], task1
mov dword[taskList+2*DESCR_TSS_size+DESCR_TSS.eip], task2
; /* load the TR register */
mov ax, [task_sel]
invk load_ltr, ax
sti
ret
......
scheduler:
; ret ; If I uncomment this ret, the message "X Task 0" is printed and handled OK
mov si, [cur_task]
inc si
cmp si, MAX_TASK
jb .cont
xor si, si
.cont
mov [cur_task], si
shl si, 1
mov bx, [task_sel+si]
invk jump_to_tss
ret
; void timer_handler()
timer_handler:
mov ebx, [ticks]
add ebx, 1
mov [ticks], ebx
mov ax, 0x20
mov fs, ax
mov bl, [fs:80*40+8*2]
inc bl
mov [fs:80*40+8*2], bl
mov al, EOI
out PORT_8259M, al
invk scheduler
ret
; void kbd_handler()
kbd_handler:
in al, PORT_KBD_A
mov [scancode], al
mov al, EOI
out PORT_8259M, al
ret
mt0 db " Task 0", 0
mt1 db " Task 1", 0
mt2 db " Task 2", 0
task1:
.again
mov al, [scancode]
mov [mt1], al
mov di, 80 * 8
mov si, mt1
invk write_msg
jmp .again
ret
task2:
.again
mov al, [scancode]
mov [mt2], al
mov di, 80 * 8
mov si, mt2
invk write_msg
jmp .again
ret
...
start2:
....
call setup_pmode
; db 0xea, 0,0, 0x28, 0
;jmp 0x30:0 ; If I uncomment this, it is called ok :)
;jmp 0x38:0 ; If I uncomment this, task bussy "jump_protected: JUMP to busy 386 TSS unsupported." msg by Bochs
.again
mov al, [scancode]
mov [mt0], al
mov di, 80 * 6
mov si, mt0
push ax
invk write_msg
pop ax
cmp al, 0x81
je .end
; jmp 0x30:0 ; If I uncomment this, is only executed one time??? and task 0 is continued...
; jmp 0x38:0 ; If I uncomment this, task bussy "jump_protected: JUMP to busy 386 TSS unsupported."
jmp .again
.end
......
Code: Select all
Out Of PM
exception Number 000D At address 0FBA:00080002 ERROR B810
I also have added a error for the exception... (dont know if is correct...)??