nxos/PROCESSI.ASM
2014-01-27 10:02:18 +01:00

557 lines
12 KiB
NASM
Raw Permalink Blame History

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 ?