46 多进程并行执行(上)
参考
https://blog.51cto.com/13475106/category6.html及狄泰软件相关课程







主要代码:
kmain.c
#include "kernel.h"
#include "screen.h"
#include "global.h"
void (* const InitInterrupt)() = NULL;
void (* const EnableTimer)() = NULL;
void (* const SendEOI)(uint port) = NULL;
volatile Task* gCTaskAddr = NULL;
Task p = {0};
Task t = {0};
TSS gTSS = {0};
void InitTask(Task* pt, void(*entry)())
{
pt->rv.cs = LDT_CODE32_SELECTOR;
pt->rv.gs = LDT_VIDEO_SELECTOR;
pt->rv.ds = LDT_DATA32_SELECTOR;
pt->rv.es = LDT_DATA32_SELECTOR;
pt->rv.fs = LDT_DATA32_SELECTOR;
pt->rv.ss = LDT_DATA32_SELECTOR;
pt->rv.esp = (uint)pt->stack + sizeof(pt->stack);
pt->rv.eip = (uint)entry;
pt->rv.eflags = 0x3202;
gTSS.ss0 = GDT_DATA32_FLAT_SELECTOR;
gTSS.esp0 = (uint)&pt->rv + sizeof(pt->rv);
gTSS.iomb = sizeof(TSS);
SetDescValue(pt->ldt + LDT_VIDEO_INDEX, 0xB8000, 0x07FFF, DA_DRWA + DA_32 + DA_DPL3);
SetDescValue(pt->ldt + LDT_CODE32_INDEX, 0x00, 0xFFFFF, DA_C + DA_32 + DA_DPL3);
SetDescValue(pt->ldt + LDT_DATA32_INDEX, 0x00, 0xFFFFF, DA_DRW + DA_32 + DA_DPL3);
pt->ldtSelector = GDT_TASK_LDT_SELECTOR;
pt->tssSelector = GDT_TASK_TSS_SELECTOR;
SetDescValue(&gGdtInfo.entry[GDT_TASK_LDT_INDEX], (uint)&pt->ldt, sizeof(pt->ldt)-1, DA_LDT + DA_DPL0);
SetDescValue(&gGdtInfo.entry[GDT_TASK_TSS_INDEX], (uint)&gTSS, sizeof(gTSS)-1, DA_386TSS + DA_DPL0);
}
void Delay(int n)
{
while( n > 0 )
{
int i = 0;
int j = 0;
for(i=0; i<1000; i++)
{
for(j=0; j<1000; j++)
{
asm volatile ("nop\n");
}
}
n--;
}
}
void TaskA()
{
int i = 0;
SetPrintPos(0, 12);
PrintString("Task A: ");
while(1)
{
SetPrintPos(8, 12);
PrintChar('A' + i);
i = (i + 1) % 26;
Delay(1);
}
}
void TaskB()
{
int i = 0;
SetPrintPos(0, 13);
PrintString("Task B: ");
while(1)
{
SetPrintPos(8, 13);
PrintChar('0' + i);
i = (i + 1) % 10;
Delay(1);
}
}
void ChangeTask()
{
gCTaskAddr = (gCTaskAddr == &p) ? &t : &p;
gTSS.ss0 = GDT_DATA32_FLAT_SELECTOR;
gTSS.esp0 = (uint)&gCTaskAddr->rv.gs + sizeof(RegValue);
SetDescValue(&gGdtInfo.entry[GDT_TASK_LDT_INDEX], (uint)&gCTaskAddr->ldt, sizeof(gCTaskAddr->ldt)-1, DA_LDT + DA_DPL0);
LoadTask(gCTaskAddr);
}
void TimerHandlerEntry();
void TimerHandler()
{
static uint i = 0;
i = (i + 1) % 5;
if( i == 0 )
{
ChangeTask();
}
SendEOI(MASTER_EOI_PORT);
}
void KMain()
{
int n = PrintString("D.T.OS\n");
uint temp = 0;
PrintString("GDT Entry: ");
PrintIntHex((uint)gGdtInfo.entry);
PrintChar('\n');
PrintString("GDT Size: ");
PrintIntDec((uint)gGdtInfo.size);
PrintChar('\n');
PrintString("IDT Entry: ");
PrintIntHex((uint)gIdtInfo.entry);
PrintChar('\n');
PrintString("IDT Size: ");
PrintIntDec((uint)gIdtInfo.size);
PrintChar('\n');
InitTask(&t, TaskB);
InitTask(&p, TaskA);
SetIntHandler(gIdtInfo.entry + 0x20, (uint)TimerHandlerEntry);
InitInterrupt();
EnableTimer();
gCTaskAddr = &p;
RunTask(gCTaskAddr);
}
loader.asm
%include "blfunc.asm"
%include "common.asm"
org BaseOfLoader
interface:
BaseOfStack equ BaseOfLoader
BaseOfTarget equ BaseOfKernel
Target db "KERNEL "
TarLen equ ($-Target)
[section .gdt]
; GDT definition
; Base, Limit, Attribute
GDT_ENTRY : Descriptor 0, 0, 0
CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_C + DA_32 + DA_DPL0
VIDEO_DESC : Descriptor 0xB8000, 0x07FFF, DA_DRWA + DA_32 + DA_DPL0
CODE32_FLAT_DESC : Descriptor 0, 0xFFFFF, DA_C + DA_32 + DA_DPL0
DATA32_FLAT_DESC : Descriptor 0, 0xFFFFF, DA_DRW + DA_32 + DA_DPL0
TASK_LDT_DESC : Descriptor 0, 0, 0
TASK_TSS_DESC : Descriptor 0, 0, 0
; GDT end
GdtLen equ $ - GDT_ENTRY
GdtPtr:
dw GdtLen - 1
dd 0
; GDT Selector
Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL0
VideoSelector equ (0x0002 << 3) + SA_TIG + SA_RPL0
Code32FlatSelector equ (0x0003 << 3) + SA_TIG + SA_RPL0
Data32FlatSelector equ (0x0004 << 3) + SA_TIG + SA_RPL0
; end of [section .gdt]
[section .idt]
align 32
[bits 32]
IDT_ENTRY:
; IDT definition
; Selector, Offset, DCount, Attribute
%rep 256
Gate Code32Selector, DefaultHandler, 0, DA_386IGate + DA_DPL0
%endrep
IdtLen equ $ - IDT_ENTRY
IdtPtr:
dw IdtLen - 1
dd 0
; end of [section .idt]
[section .s16]
[bits 16]
BLMain:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, SPInitValue
; initialize GDT for 32 bits code segment
mov esi, CODE32_SEGMENT
mov edi, CODE32_DESC
call InitDescItem
; initialize GDT pointer struct
mov eax, 0
mov ax, ds
shl eax, 4
add eax, GDT_ENTRY
mov dword [GdtPtr + 2], eax
; initialize IDT pointer struct
mov eax, 0
mov ax, ds
shl eax, 4
add eax, IDT_ENTRY
mov dword [IdtPtr + 2], eax
call LoadTarget
cmp dx, 0
jz output
call StoreGlobal
; 1. load GDT
lgdt [GdtPtr]
; 2. close interrupt
; load IDT
; set IOPL to 3
cli
lidt [IdtPtr]
pushf
pop eax
or eax, 0x3000
push eax
popf
; 3. open A20
in al, 0x92
or al, 00000010b
out 0x92, al
; 4. enter protect mode
mov eax, cr0
or eax, 0x01
mov cr0, eax
; 5. jump to 32 bits code
jmp dword Code32Selector : 0
output:
mov bp, ErrStr
mov cx, ErrLen
call Print
jmp $
; esi --> code segment label
; edi --> descriptor label
InitDescItem:
push eax
mov eax, 0
mov ax, cs
shl eax, 4
add eax, esi
mov word [edi + 2], ax
shr eax, 16
mov byte [edi + 4], al
mov byte [edi + 7], ah
pop eax
ret
;
;
StoreGlobal:
mov dword [RunTaskEntry], RunTask
mov dword [LoadTaskEntry], LoadTask
mov dword [InitInterruptEntry], InitInterrupt
mov dword [EnableTimerEntry], EnableTimer
mov dword [SendEOIEntry], SendEOI
mov eax, dword [GdtPtr + 2]
mov dword [GdtEntry], eax
mov dword [GdtSize], GdtLen / 8
mov eax, dword [IdtPtr + 2]
mov dword [IdtEntry], eax
mov dword [IdtSize], IdtLen / 8
ret
[section .sfunc]
[bits 32]
;
;
Delay:
%rep 5
nop
%endrep
ret
;
;
Init8259A:
push ax
; master
; ICW1
mov al, 00010001B
out MASTER_ICW1_PORT, al
call Delay
; ICW2
mov al, 0x20
out MASTER_ICW2_PORT, al
call Delay
; ICW3
mov al, 00000100B
out MASTER_ICW3_PORT, al
call Delay
; ICW4
mov al, 00010001B
out MASTER_ICW4_PORT, al
call Delay
; slave
; ICW1
mov al, 00010001B
out SLAVE_ICW1_PORT, al
call Delay
; ICW2
mov al, 0x28
out SLAVE_ICW2_PORT, al
call Delay
; ICW3
mov al, 00000010B
out SLAVE_ICW3_PORT, al
call Delay
; ICW4
mov al, 00000001B
out SLAVE_ICW4_PORT, al
call Delay
pop ax
ret
; al --> IMR register value
; dx --> 8259A port
WriteIMR:
out dx, al
call Delay
ret
; dx --> 8259A
; return:
; ax --> IMR register value
ReadIMR:
in ax, dx
call Delay
ret
;
; dx --> 8259A port
WriteEOI:
push ax
mov al, 0x20
out dx, al
call Delay
pop ax
ret
[section .gfunc]
[bits 32]
;
; parameter ===> Task* pt
RunTask:
push ebp
mov ebp, esp
mov esp, [ebp + 8]
lldt word [esp + 200]
ltr word [esp + 202]
pop gs
pop fs
pop es
pop ds
popad
add esp, 4
iret
; void LoadTask(Task* pt);
;
LoadTask:
push ebp
mov ebp, esp
mov eax, [ebp + 8]
lldt word [eax + 200]
leave
ret
;
;
InitInterrupt:
push ebp
mov ebp, esp
push ax
push dx
call Init8259A
sti
mov ax, 0xFF
mov dx, MASTER_IMR_PORT
call WriteIMR
mov ax, 0xFF
mov dx, SLAVE_IMR_PORT
call WriteIMR
pop dx
pop ax
leave
ret
;
;
EnableTimer:
push ebp
mov ebp, esp
push ax
push dx
mov dx, MASTER_IMR_PORT
call ReadIMR
and ax, 0xFE
call WriteIMR
pop dx
pop ax
leave
ret
; void SendEOI(uint port);
; port ==> 8259A port
SendEOI:
push ebp
mov ebp, esp
mov edx, [ebp + 8]
mov al, 0x20
out dx, al
call Delay
leave
ret
[section .s32]
[bits 32]
CODE32_SEGMENT:
mov ax, VideoSelector
mov gs, ax
mov ax, Data32FlatSelector
mov ds, ax
mov es, ax
mov fs, ax
mov ax, Data32FlatSelector
mov ss, ax
mov esp, BaseOfLoader
jmp dword Code32FlatSelector : BaseOfKernel
;
;
DefaultHandlerFunc:
iret
DefaultHandler equ DefaultHandlerFunc - $$
Code32SegLen equ $ - CODE32_SEGMENT
ErrStr db "No KERNEL"
ErrLen equ ($-ErrStr)
Buffer db 0
更多代码见相关课程
posted on 2021-05-10 10:44 lh03061238 阅读(80) 评论(0) 收藏 举报
浙公网安备 33010602011771号