557 lines
12 KiB
NASM
557 lines
12 KiB
NASM
MaxProcess equ 7
|
||
|
||
;MULTITASKER
|
||
|
||
;Procedure "pubbliche":
|
||
|
||
;1) StartMultiTasking (no input, no output)
|
||
;2) LoadProgram
|
||
; Input: CS:SI --> nome del file che contiene il programma
|
||
; Output: ES:DI --> indirizzo a partire dal quale Š stato memorizzato il codice
|
||
;3) RunProcess (da chiamare subito dopo LoadProgram per iniziare l'esecuzione
|
||
; del processo)
|
||
;4) KillProcess
|
||
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
StartMultiTasking:
|
||
mov word ptr cs:[CurrentProg],0
|
||
mov al,1
|
||
mov byte ptr cs:[ProcessList],al
|
||
|
||
pushf
|
||
cli
|
||
call InstallTimerInt
|
||
popf
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
EndMultiTasking:
|
||
push ax
|
||
push es
|
||
|
||
xor ax,ax
|
||
mov es,ax
|
||
mov ax,word ptr cs:[oldint]
|
||
mov es:[(1ch*4)],ax
|
||
|
||
mov ax,word ptr cs:[oldint+2]
|
||
mov es:[(1ch*4+2)],ax
|
||
|
||
pop es
|
||
pop ax
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
GetProcessInfo:
|
||
;No input
|
||
;Output: SI --> [CurrentProg] (processo corrente)
|
||
; CX --> [VisibleProcess]
|
||
|
||
mov si,word ptr cs:[CurrentProg]
|
||
mov cx,word ptr cs:[VisibleProcess]
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
SetVisibleProcess:
|
||
;input SI --> numero del processo da rendere visibile
|
||
push ax
|
||
|
||
mov al,byte ptr cs:[ProcessList+si]
|
||
test al,al
|
||
jz SetVisibleProcess_End
|
||
|
||
mov word ptr cs:[VisibleProcess],si
|
||
|
||
SetVisibleProcess_End:
|
||
pop ax
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
GetNextProcess:
|
||
;output SI --> processo attivo successivo al processo corrente
|
||
;esempio sono attivi i processi 0 e 1, ed Š visibile il processo 1.
|
||
;In questo caso, GetNextProcess restituir… 0.
|
||
|
||
push ax
|
||
|
||
mov si,word ptr cs:[CurrentProg]
|
||
|
||
GetNextProcess_ScanList:
|
||
inc si
|
||
GetNextProcess_ScanList2:
|
||
mov al,byte ptr cs:[ProcessList+si]
|
||
cmp si,(MaxProcess)
|
||
je GetNextProcess_RestartScan
|
||
test al,al
|
||
jz GetNextProcess_ScanList
|
||
|
||
pop ax
|
||
|
||
ret
|
||
|
||
GetNextProcess_RestartScan:
|
||
xor si,si
|
||
jmp GetNextProcess_ScanList2
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
LoadProgram:
|
||
;input DS:SI nome del file che contiene il programma
|
||
;output ES:DI indirizzo a partire dal quale Š stato memorizzato il codice
|
||
; DX=Memoria allocata per il programma (in Kbytes)
|
||
|
||
cli
|
||
|
||
push ax
|
||
|
||
call Fat12_OpenFile ;apre il file
|
||
jc LoadProgram_Error
|
||
call Fat12_GetFileSize ;ottiene la grandezza del file
|
||
|
||
mov dx,ax
|
||
|
||
mov cl,10
|
||
shr dx,cl ;DX=DX/1024
|
||
add dx,2 ;Calcola la memoria da allocare (alloca 2kb in pi—
|
||
;necessari per lo stack)
|
||
|
||
push dx
|
||
|
||
call MemAlloc
|
||
|
||
mov dx,ax
|
||
xor di,di
|
||
push es
|
||
push di
|
||
|
||
; xor di,di
|
||
call Fat12_ReadFile ;legge il file
|
||
call Fat12_CloseFile ;chiude il file
|
||
|
||
pop di
|
||
pop es
|
||
pop dx
|
||
|
||
pop ax
|
||
sti
|
||
|
||
ret
|
||
|
||
LoadProgram_Error:
|
||
sti
|
||
xor dx,dx
|
||
pop ax
|
||
ret
|
||
|
||
;RealDS dw 0
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
LoadComProgram:
|
||
;input DS:SI nome del file
|
||
; DS:BX parametri
|
||
;output ES:DI indirizzo a partire dal quale Š memorizzato il codice
|
||
; (per default DI=100h)
|
||
; DX memoria allocata per il programma (in kbytes)
|
||
|
||
;Da aggiungere: costruzione del PSP (program segment prefix)
|
||
|
||
cli
|
||
|
||
push ax
|
||
|
||
call Fat12_OpenFile
|
||
jc LoadComProgram_Error
|
||
|
||
mov dx,64 ;per avere completa compatibilit… con il formato "com"
|
||
;del dos, alloco 64 Kb di memoria
|
||
|
||
push dx
|
||
|
||
call MemAlloc ;alloca 64 kb di memoria
|
||
|
||
call Fat12_GetFileSize
|
||
mov dx,ax
|
||
|
||
push bx
|
||
push cx
|
||
|
||
mov di,80h
|
||
mov cx,80h
|
||
|
||
LoadComProgram_LoadParameters:
|
||
mov al,byte ptr ds:[bx]
|
||
mov byte ptr es:[di],al
|
||
inc bx
|
||
inc di
|
||
loop LoadComProgram_LoadParameters
|
||
|
||
pop cx
|
||
pop bx
|
||
|
||
|
||
mov di,100h ;offset iniziale 100h
|
||
push es
|
||
push di
|
||
|
||
call Fat12_ReadFile ;memorizza il file a partire da ES:[100h]
|
||
call Fat12_CloseFile
|
||
|
||
pop di
|
||
pop es
|
||
pop dx
|
||
|
||
pop ax
|
||
|
||
ret
|
||
|
||
LoadComProgram_Error:
|
||
xor dx,dx
|
||
pop ax
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
RunProcess:
|
||
;Fa in modo che un processo, gi… caricato in memoria, sia eseguito.
|
||
;input ES:DI=segment:offset di partenza del processo.
|
||
; DX=memoria allocata per il programma
|
||
; BL=0 --> rende visibile il processo (normale)
|
||
; BL=1 --> non rende visibile il processo
|
||
;La procedura setta P_Ds, P_Es, P_Ss del processo uguali a ES.
|
||
;P_Sp del processo = 0fffah
|
||
;Gli altri registri = 0
|
||
;Flags = indefiniti
|
||
;
|
||
;Carica nello stack del processo i flags, il segmento e l'offset del processo
|
||
;cos<6F> l'interrupt del timer sa dove tornare con IRET.
|
||
;Rende visibile il processo caricato.
|
||
|
||
;Questa procedura Š un po' incasinata...
|
||
|
||
push ax
|
||
push si
|
||
pushf
|
||
|
||
pushf
|
||
cli
|
||
|
||
;Cerca un posto libero nella "ProcessList"
|
||
mov si,0ffffh
|
||
RunProcess_Loop1:
|
||
inc si
|
||
cmp si,(MaxProcess)
|
||
jae RunProcess_Error1
|
||
mov al,byte ptr cs:[ProcessList+si]
|
||
test al,al
|
||
jnz RunProcess_Loop1
|
||
|
||
;Ora in SI ho il numero del primo processo libero...
|
||
|
||
mov al,1
|
||
mov byte ptr cs:[ProcessList+si],al ;"occupa" il posto nella ProcessList
|
||
|
||
test bl,bl
|
||
jnz RunProcess_DontSetVisible ;Nuova opzione: se BL=1 allora il
|
||
;processo non viene reso visibile
|
||
;(utile per processi come i driver)
|
||
|
||
mov ah,02h ;rende visibile il processo
|
||
int 24h
|
||
|
||
RunProcess_DontSetVisible:
|
||
add si,si
|
||
|
||
jmp RunProcess_2
|
||
|
||
RunProcess_Error1:
|
||
popf
|
||
popf
|
||
pop si
|
||
pop ax
|
||
ret
|
||
|
||
RunProcess_2:
|
||
|
||
push si
|
||
mov ax,es
|
||
|
||
add si,si ;Salva in ProcessMemory la memoria occupata
|
||
mov word ptr cs:[ProcessMemory+si],ax ;dal programma
|
||
|
||
mov ax,dx
|
||
|
||
mov word ptr cs:[ProcessMemory+si+2],ax
|
||
pop si
|
||
|
||
push cx
|
||
mov cl,10
|
||
shl dx,cl ;DX=DX*1024
|
||
sub dx,6 ;Calcola la posizione iniziale di SP
|
||
pop cx
|
||
|
||
mov word ptr cs:[P_Sp+si],dx ;Salva SP iniziale (importante!)
|
||
|
||
mov ax,es
|
||
mov word ptr cs:[P_Ss+si],ax ;setta i valori dei segment registers
|
||
mov word ptr cs:[P_Ds+si],ax
|
||
mov word ptr cs:[P_Es+si],ax
|
||
xor ax,ax
|
||
mov word ptr cs:[P_Ax+si],ax ;setta a 0 gli altri registri
|
||
mov word ptr cs:[P_Bx+si],ax
|
||
mov word ptr cs:[P_Cx+si],ax
|
||
mov word ptr cs:[P_Dx+si],ax
|
||
mov word ptr cs:[P_Bp+si],ax
|
||
mov word ptr cs:[P_Si+si],ax
|
||
mov word ptr cs:[P_Di+si],ax
|
||
|
||
pop ax ;salva nello stack del processo i flags,
|
||
or ax,0000001000000000b ;abilita l'interrupt flag
|
||
|
||
push si
|
||
mov si,dx
|
||
|
||
mov word ptr es:[si+4],ax
|
||
mov ax,es
|
||
mov word ptr es:[si+2],ax
|
||
mov word ptr es:[si],di
|
||
|
||
pop si
|
||
|
||
popf
|
||
pop si
|
||
pop ax
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
KillProcess:
|
||
;Elimina dalla lista di esecuzione il processo puntato da cs:[CurrentProg]
|
||
;Input BL = 0 --> Libera la memoria occupata dal programma
|
||
; BL = 1 --> Non libera la memoria (Terminate and stay resident)
|
||
|
||
cli ;meglio disabilitare gli interrupt...
|
||
|
||
mov ah,04h ;"ClearScreen": cancella lo schermo del processo
|
||
int 24h ;da terminare
|
||
|
||
mov si,word ptr cs:[CurrentProg]
|
||
|
||
mov al,0
|
||
mov byte ptr cs:[ProcessList+si],al
|
||
|
||
cmp si,word ptr cs:[VisibleProcess]
|
||
jne KillProcess_2 ;se il processo non Š visibile, lo termina
|
||
;direttamente
|
||
|
||
;se invece il processo Š visibile, allora ne deve cercare un altro
|
||
;da rendere visibile
|
||
|
||
push si
|
||
|
||
KillProcess_NextVisibleProcess:
|
||
;cerca il prossimo processo visibile
|
||
dec si
|
||
cmp si,0ffffh
|
||
je KillProcess_1
|
||
mov al,byte ptr cs:[ProcessList+si]
|
||
test al,al
|
||
jz KillProcess_NextVisibleProcess
|
||
|
||
mov ah,02h
|
||
int 24h ;Attenzione, il driver video dev'essere presente!
|
||
|
||
pop si
|
||
|
||
;controlla se c'Š un solo processo disponibile: in questo caso, infatti,
|
||
;non viene terminato. Se viene terminato l'ultimo processo disponibile,
|
||
;il sistema va in crash...
|
||
|
||
jmp KillProcess_2
|
||
|
||
KillProcess_1:
|
||
mov si,(MaxProcess)
|
||
jmp KillProcess_NextVisibleProcess
|
||
|
||
|
||
KillProcess_2:
|
||
;controlla se BL=0...se non Š zero, allora la memoria del processo
|
||
;non viene liberata (Terminate and Stay Resident).
|
||
test bl,bl
|
||
jnz KillProcess_3
|
||
|
||
add si,si ;SI=SI*4
|
||
add si,si
|
||
|
||
mov ax,word ptr cs:[ProcessMemory+si]
|
||
mov es,ax
|
||
mov dx,word ptr cs:[ProcessMemory+si+2]
|
||
|
||
call MemFree ;libera la memoria occupata dal programma
|
||
|
||
KillProcess_3:
|
||
sti
|
||
|
||
KillProcess_End:
|
||
jmp KillProcess_End ;jmp infinito finchŠ non si verifica un
|
||
;timer interrupt (che toglie definitivamente
|
||
;l'esecuzione al processo).
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
InstallTimerInt:
|
||
push ax
|
||
push es
|
||
push di
|
||
xor ax,ax
|
||
mov es,ax
|
||
mov di,(1ch*4)
|
||
mov ax,word ptr es:[di]
|
||
mov word ptr cs:[oldint],ax
|
||
mov ax,offset TimerInt
|
||
mov word ptr es:[di],ax
|
||
|
||
add di,2
|
||
mov ax,word ptr es:[di]
|
||
mov word ptr cs:[oldint+2],ax
|
||
mov ax,cs
|
||
mov word ptr es:[di],ax
|
||
pop di
|
||
pop es
|
||
pop ax
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
TimerInt:
|
||
|
||
;salva tutti i registri tranne CS e IP, perchŠ tanto CS e IP sono gi…
|
||
;salvati nello stack del programma chiamante.
|
||
|
||
mov word ptr cs:[temp_si],si
|
||
mov si,word ptr cs:[currentprog]
|
||
add si,si
|
||
|
||
mov word ptr cs:[p_ax+si],ax
|
||
mov word ptr cs:[p_bx+si],bx
|
||
mov word ptr cs:[p_cx+si],cx
|
||
mov word ptr cs:[p_dx+si],dx
|
||
mov word ptr cs:[p_di+si],di
|
||
mov ax,ds
|
||
mov word ptr cs:[p_ds+si],ax
|
||
mov ax,es
|
||
mov word ptr cs:[p_es+si],ax
|
||
mov ax,ss
|
||
mov word ptr cs:[p_ss+si],ax
|
||
mov word ptr cs:[p_sp+si],sp
|
||
mov word ptr cs:[p_bp+si],bp
|
||
mov di,si
|
||
mov ax,word ptr cs:[temp_si]
|
||
mov word ptr cs:[p_si+di],ax
|
||
|
||
|
||
;Ora cerca nella ProcessList il prossimo processo da attivare
|
||
shr si,1 ;lavoro in byte
|
||
; xor cx,cx
|
||
goon_1:
|
||
inc si
|
||
goon_12:
|
||
; inc cx
|
||
; cmp cx,(MaxProcess+1)
|
||
; je TimerInt_EndSystem
|
||
mov al,byte ptr cs:[ProcessList+si]
|
||
cmp si,(MaxProcess)
|
||
jb TimerInt_TestAl
|
||
|
||
xor si,si
|
||
jmp goon_12
|
||
|
||
TimerInt_TestAl:
|
||
test al,al
|
||
jz goon_1
|
||
|
||
|
||
;Ora in SI ho il numero del processo da eseguire
|
||
|
||
goon_2:
|
||
mov word ptr cs:[CurrentProg],si
|
||
|
||
add si,si ;lavoro in word
|
||
|
||
mov bx,word ptr cs:[p_bx+si]
|
||
mov cx,word ptr cs:[p_cx+si]
|
||
mov dx,word ptr cs:[p_dx+si]
|
||
mov di,word ptr cs:[p_di+si]
|
||
mov ax,word ptr cs:[p_ds+si]
|
||
mov ds,ax
|
||
mov ax,word ptr cs:[p_es+si]
|
||
mov es,ax
|
||
mov ax,word ptr cs:[p_ss+si]
|
||
mov ss,ax
|
||
mov sp,word ptr cs:[p_sp+si]
|
||
mov bp,word ptr cs:[p_bp+si]
|
||
mov ax,word ptr cs:[p_ax+si]
|
||
mov si,word ptr cs:[p_si+si]
|
||
|
||
TimerInt_End:
|
||
|
||
push ax
|
||
mov al,20h
|
||
out 20h,al
|
||
pop ax
|
||
|
||
iret
|
||
|
||
TimerInt_EndSystem:
|
||
call EndSystem
|
||
|
||
temp_si dw 0
|
||
|
||
;---------------------------------
|
||
|
||
p_ax dw MaxProcess dup 0
|
||
p_bx dw MaxProcess dup 0
|
||
p_cx dw MaxProcess dup 0
|
||
p_dx dw MaxProcess dup 0
|
||
p_si dw MaxProcess dup 0
|
||
p_di dw MaxProcess dup 0
|
||
p_ds dw MaxProcess dup 0
|
||
p_es dw MaxProcess dup 0
|
||
p_ss dw MaxProcess dup 0
|
||
p_sp dw MaxProcess dup 0
|
||
p_bp dw MaxProcess dup 0
|
||
|
||
CurrentProg dw 0 ;indica il processo che Š attivo
|
||
VisibleProcess dw 0 ;indica il processo che Š visibile
|
||
|
||
ProcessList db MaxProcess dup 0
|
||
|
||
ProcessMemory dd MaxProcess dup 0 ;indica la memoria occupata da ogni
|
||
;programma. La prima word indica il segmento (e si presuppone
|
||
;che l'offset sia 0), la seconda word indica la quantit…
|
||
;di memoria occupata in kbytes.
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
GoToNextProcess:
|
||
;Questa procedura serve al sistema operativo...ad esempio nel driver della
|
||
;tastiera: se un processo NON visibile ha chiesto un tasto e lo sta attendendo,
|
||
;finchŠ non Š visibile spreca solo risorse, quindi il driver della tastiera
|
||
;chiama questa funzione per passare al processo successivo.
|
||
cli
|
||
int 1ch
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
oldint dd ?
|
||
longadr dd ?
|