home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 19
/
CD_ASCQ_19_010295.iso
/
dos
/
prg
/
noyau
/
principa.asm
< prev
next >
Wrap
Assembly Source File
|
1994-05-25
|
24KB
|
860 lines
;
; Principa.asm
;
; Processus principal & tous ses processus fils
;
; Noyau Multitache .
;
; ART OF CODE
.286
.MODEL SMALL,OS_DOS
INCLUDE dos.inc
INCLUDE types.inc
INCLUDE const.inc
INCLUDE etats.inc
INCLUDE descript.inc
INCLUDE semphor.inc
INCLUDE process.inc
INCLUDE gestlist.inc
INCLUDE donnees.inc
INCLUDE code.inc
INCLUDE tampon.inc
; définition des fonctions de gestion d'écran.
; fonctions assez vielles ( avril 92 ) et certainement mal programmées.
EXTERNDEF Trace_Cadre : NEAR ; Attention, procédure non réentrante
EXTERNDEF Clear_Screen : NEAR
EXTERNDEF Affiche_Chaine : NEAR
; déclaration des segments de pile de chaque processus
PilePrincipal SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
PUBLIC SP_PilePrincipal
SP_PilePrincipal LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET Principal ; point d'entrée
PilePrincipal ENDS
PileGestEcran SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_PileGestEcran LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET GestEcran ; point d'entrée
PileGestEcran ENDS
Pileprocess SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_Pileprocess LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET process ; point d'entrée
Pileprocess ENDS
Pileprocess2 SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_Pileprocess2 LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET process2 ; point d'entrée
Pileprocess2 ENDS
Pileprocess3 SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_Pileprocess3 LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET process3 ; point d'entrée
Pileprocess3 ENDS
PileProcess4 SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_PileProcess4 LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET Process4 ; point d'entrée
PileProcess4 ENDS
PileProcess5 SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_PileProcess5 LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET Process5 ; point d'entrée
PileProcess5 ENDS
PileProcess6 SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_PileProcess6 LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET Process6 ; point d'entrée
PileProcess6 ENDS
PileProducteur SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_PileProducteur LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET Producteur ; point d'entrée
PileProducteur ENDS
PileConsommateur SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_PileConsommateur LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET Consommateur ; point d'entrée
PileConsommateur ENDS
PileMonHorloge SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_PileMonHorloge LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET MonHorloge ; point d'entrée
PileMonHorloge ENDS
PileBalle SEGMENT WORD 'STACK' ; pile privée du processus
WORD (DimPile-NbRegs) DUP (?)
SP_PileBalle LABEL WORD ; sommet actuel de la pile privée
WORD (NbRegs - 2) DUP (?) ; valeur initiale des registres du µp
WORD ETAT_INITIAL ; valeur initiale du mot d'état
WORD OFFSET Balle ; point d'entrée
PileBalle ENDS
; Données concernant le Timer Système pour le processus d'affichage
; de l'horloge.
DonneesTimer SEGMENT AT 0040h
org 006Ch
TIMER_LOW WORD ?
TIMER_HIGH WORD ?
DonneesTimer ENDS
.DATA
; définition des Descripteurs de Processus
pGestEcran PROCESSUS <{,,,TypeProcessus,SUSPENDU,129},OFFSET SP_PileGestEcran,PileGestEcran,NIL>
pProcess PROCESSUS <{,,,TypeProcessus,SUSPENDU,131},OFFSET SP_Pileprocess,Pileprocess,NIL>
pProcess2 PROCESSUS <{,,,TypeProcessus,SUSPENDU,131},OFFSET SP_Pileprocess2,Pileprocess2,NIL>
pProcess3 PROCESSUS <{,,,TypeProcessus,SUSPENDU,136},OFFSET SP_Pileprocess3,Pileprocess3,NIL>
pProcess4 PROCESSUS <{,,,TypeProcessus,SUSPENDU,136},OFFSET SP_PileProcess4,PileProcess4,NIL>
pProcess5 PROCESSUS <{,,,TypeProcessus,SUSPENDU,136},OFFSET SP_PileProcess5,PileProcess5,NIL>
pProcess6 PROCESSUS <{,,,TypeProcessus,SUSPENDU,136},OFFSET SP_PileProcess6,PileProcess6,NIL>
pProducteur PROCESSUS <{,,,TypeProcessus,SUSPENDU,136},OFFSET SP_PileProducteur,PileProducteur,NIL>
pConsommateur PROCESSUS <{,,,TypeProcessus,SUSPENDU,136},OFFSET SP_PileConsommateur,PileConsommateur,NIL>
pMonHorloge PROCESSUS <{,,,TypeProcessus,SUSPENDU,1},OFFSET SP_PileMonHorloge,PileMonHorloge,NIL>
pBalle PROCESSUS <{,,,TypeProcessus,SUSPENDU,1},OFFSET SP_PileBalle,PileBalle,NIL>
; Déclaration des sémaphores
Synchro1 SEMAPHORE <> ; sémaphore de synchronisation
Synchro2 SEMAPHORE <> ; sémaphore de synchronisation
sPrincipal SEMAPHORE <> ; sémaphore de déblocage du processus principal
DosBios SEMAPHORE <> ; sémaphore d'exclusion mutuelle concernant le DOS
mutex SEMAPHORE <> ; sémaphore d'exclusion mutuelle concernant le Tampon
PlaceLibre SEMAPHORE <> ; sémaphore concernant le buffer circulaire
CarDisponible SEMAPHORE <> ; sémaphore concernant le buffer circulaire
PUBLIC sHorloge ; sémaphores commandant l'execution de ces deux processus
; ces sémaphores sont préinitialisés. Donc pas de problèmes de démarrage.
sHorloge SEMAPHORE <{OFFSET sHorloge,OFFSET sHorloge,,TypeSemaphore,OCCUPE,INFINI},0>
sBalle SEMAPHORE <{OFFSET sBalle,OFFSET sBalle,,TypeSemaphore,OCCUPE,INFINI},0>
; Déclaration des affichages
Chaine1 DB "NOYAU MULTITACHE PREEMPTIF Version 1.0",0
Chaine2 DB "Par the EQUALIZER from The ART OF CODE !!!",0
ChainePro1 DB "Processus N°1 ( priorité 131 ) synchro ... ",0
ChainePro2 DB "Processus N°2 ( priorité 131 ) synchro ... ",0
ChainePro3 DB "Processus N°3 ( priorité 136 )............ ",0
ChainePro4 DB "Processus N°4 ( priorité 136 )............ ",0
ChainePro5 DB "Processus N°5 ( priorité 136 )............ ",0
ChainePro6 DB "Processus N°6 ( priorité 136 )............ ",0
ChaineProducteur DB "Veuillez tapez votre phrase suivie de [entrée]:",0
; Déclaration du tampon d'echange entre le Producteur et le Consommateur
BufferClavier BYTE 32 DUP (?)
LeTampon TAMPON <OFFSET BufferClavier,OFFSET BufferClavier,OFFSET BufferClavier,OFFSET BufferClavier+32,OFFSET Ajoute,OFFSET Retire>
; Données concernant la petite balle qui rebondit
x WORD ? ; coordonnées de la balle
y WORD ?
x1 WORD ? ; coordonnées des limites du rectangle
y1 WORD ? ; dans lequel évolue la balle
x2 WORD ?
y2 WORD ?
devx WORD ? ; variables de direction de la balle : 1 = droite, -1 = gauche
devy WORD ? ; 1 = bas , -1 = haut
.CODE
; Attention ces deux procédures doivent s'executer en exclusion mutuelle
; prodédure d'ajout dans un buffer circulaire pointé par ds:si
; on ajoute l'octet AL
Ajoute PROC
push ax
push si
ASSUME DS:@data;es:Nothing
mov SI,(TAMPON PTR [si]).LaQueue
mov [si],al ; on place AL en queue
pop si
mov ax,(TAMPON PTR [si]).LaQueue
inc ax ; on incrémente Queue
cmp ax,(TAMPON PTR [si]).LaFin ; si on arrive à la fin, on retourne
jne Ajoute_Suite ; au début
mov ax,(TAMPON PTR [si]).Debut
Ajoute_Suite:
mov (TAMPON PTR [si]).LaQueue,ax
pop ax
RET
Ajoute ENDP
; Procédure de retrait d'une valeur du buffer circulaire dans AL
Retire PROC
push si
ASSUME DS:@data;es:Nothing
mov SI,(TAMPON PTR [si]).Tete ; on récupère le premier caractère ( FIFO )
mov al,[SI]
pop si
push ax
mov ax,(TAMPON PTR [si]).Tete ; on incrémente la tête
inc ax
cmp ax,(TAMPON PTR [si]).LaFin ; si arrivé à la fin, on saute au début.
jne Retire_Suite
mov ax,(TAMPON PTR [si]).Debut
Retire_Suite:
mov (TAMPON PTR [si]).Tete,ax
pop ax
RET ; et voila.
Retire ENDP
; procédure de suicide d'un processus
Suicide PROC NEAR
mov si,[EnCours] ; on tue le processus
mov (DESCRIPTEUR PTR [si]).Etat,TERMINE
call dispatcher
Suicide ENDP
; Procedure qui fait rebondir une petite balle
; processus sans prétention ni optimisation, juste pour montrer l'aspect
; multitache.
Balle PROC
mov ax,@data
mov ds,ax
mov ax,0B800h
mov es,ax
ASSUME DS:@data;es:Nothing
mov word ptr [x1],10 ; on sauvegarde les limites
mov word ptr [x2],69 ; du rectangle Hôte.
mov word ptr [y1],20
mov word ptr [y2],24
mov word ptr [x],11 ; coordonnées de départ
mov word ptr [y],21
mov word ptr [devx],1 ; directions de départ
mov word ptr [devy],1
mov di,2*11+160*21 ;di=(11,21)
BoucleBalle:
lea si,sBalle
Call p ; on bloque le processus
mov si,di ; on sauvegarde l'ancienne position de la balle
mov ax,[x] ; on effectue le déplacement de la balle
add ax,word ptr [devx]
cmp ax,word ptr [x2] ; débordement à gauche ?
jne suite_x2 ; non, on continue
sub ax,2 ; on change la direction
neg word ptr [devx]
jmp suite_x3 ; on continue
suite_x2:
cmp ax,word ptr [x1] ; débordement à droite
jne suite_x3
add ax,2 ; idem
neg word ptr [devx]
suite_x3:
mov word ptr [x],ax ; on sauvegarde la nouvelle valeur de X
mov ax,[y] ; on fait la même chose pour Y
add ax,word ptr [devy]
cmp ax,word ptr [y2]
jne suite_y2
sub ax,2
neg word ptr [devy]
jmp suite_y3
suite_y2:
cmp ax,word ptr [y1]
jne suite_y3
add ax,2
neg word ptr [devy]
suite_y3:
mov word ptr [y],ax ; Sauvegarde de Y
mov di,[x] ; calcul du nouveau di=(X,Y)
shl di,1
xor dx,dx
mov ax,[y]
mov bx,160
mul bx
add di,ax ; di=2*x+160*y ( 2 octets par caractères )
mov byte ptr es:[si],' ' ; on efface le précédent
mov byte ptr es:[di],'' ; on affiche la balle à son nouvel emplacement
jmp BoucleBalle ; on boucle ad eternam
; Ce processus étant pour la majeure partie de son temps bloqué dans la
; file d'attente du sémaphore, lorsque les autres processus auront fini,
; et que le noyau reprendra la main, il terminera lui même ce processus
; par le biais de HORLOGE qui rétablira l'ancien vecteur d'interruption 08h
Balle ENDP
; Processus d'affichage d'une horloge en temps réel à l'ecran
MonHorloge PROC
mov ax,0B800h
mov es,ax
mov bp,0
BoucleHorloge:
mov ax,@data
mov ds,ax
ASSUME DS:@data
lea si,sBalle ; on débloque le processus 'Balle'
call v
lea si,sHorloge ; on attend que l'interruption Timer nous débloque
call p
mov ax,DonneesTimer
mov ds,ax
ASSUME DS:DonneesTimer
MOV AX,[TIMER_LOW] ; prise en compte de la valeur TIMER_LOW
xor dx,dx
mov bx,1093 ; on la divise par 1093 ( en effet, Timer_low
div bx ; arrive à 65535 à chaque nouvelle heure donc
mov di,22*160+8 ; TimerLow / 1093 => Minutes
mov cx,2
CALL AFFDEC ; on affiche les minutes
mov di,22*160+6
cmp bp,9 ; petit test pour savoir si on affiche les ':'
jae deuxpoints ; oui
mov byte ptr es:[di],' '
jmp deuxpoints2 ; non, on affiche ' ' et on saute
deuxpoints:
mov byte ptr es:[di],':'
deuxpoints2:
mov di,22*160+2 ; on affiche tel quel l'heure
MOV AX,[TIMER_HIGH]
cmp ax,24 ; j'ai remarqué lors d'essais tres poussés (si!) que
jne pas24 ; entre 23:59 et 00:00, durant quelques secondes,
xor ax,ax ; on avait : 24:00 ( serait-ce un bug de ma part ? ou
; un temps nécessaire à la machine pour prendre en
; compte le changement de journée ?)
pas24:
CALL AFFDEC ; on l'affiche
inc bp ; bp est juste un compteur qui permet de temporiser
cmp bp,18 ; le clignotement des ':'
jne BoucleHorloge
mov bp,0
jmp BoucleHorloge ; on boucle
; MonHorloge,tous comme Balle, est terminé par pHorloge lorsque celui-ci
; rétablit l'ancien gestionnaire d'interruption.
MonHorloge ENDP
; Et voici sa majesté le processus Principal
Principal PROC
mov ax,@data
mov ds,ax
ASSUME ds:@data
; On initialise tous les sémaphores
; La nouvelle version d'InitVide initialise l'etat à OCCUPE et
; la priorité à INFINI
lea si,sPrincipal
mov (SEMAPHORE PTR [si]).Compteur,0
call InitVide
lea si,Synchro1
mov (SEMAPHORE PTR [si]).Compteur,0
call InitVide
lea si,Synchro2
mov (SEMAPHORE PTR [si]).Compteur,0
call InitVide
lea si,DosBios
mov (SEMAPHORE PTR [si]).Compteur,1 ; exclusion mutuelle
call InitVide
lea si,mutex
mov (SEMAPHORE PTR [si]).Compteur,1 ; idem
call InitVide
lea si,PlaceLibre
mov (SEMAPHORE PTR [si]).Compteur,32 ; 32 places libres
call InitVide
lea si,CarDisponible
mov (SEMAPHORE PTR [si]).Compteur,0 ; pas de caractères dispo pour
call InitVide ; l'instant
; On place tous les processus en queue d'exploitation
lea bx,pProcess ; on place tous les DdP dans
call eligible ; la queue d'exploitation
lea bx,pProcess2
call eligible
lea bx,pProcess3
call eligible
lea bx,pProcess4
call eligible
lea bx,pProcess5
call eligible
lea bx,pProcess6
call eligible
lea bx,pGestEcran
call eligible
lea bx,pProducteur
call eligible
lea bx,pConsommateur
call eligible
lea bx,pMonHorloge
call eligible
lea bx,pBalle
call eligible
lea si,sPrincipal ; là, Principal attend la fin de tous ces fils.
mov cx,9
attendre:
call p
loop attendre
; Arrivé à ce stade, les 9 processus fils ont fini leur travail
; MonHorloge et Balle sont coincés momentanément dans leur sémaphore
; On termine.
call Suicide ; Asta la vista baby !
Principal ENDP
; Voici le processus Producteur qui envoie toutes les touches tapées
; dans le buffer circulaire
Producteur PROC
mov ax,@data
mov ds,ax
ASSUME ds:@data
lea si,ChaineProducteur
mov di,24+12*160
call Affiche_Chaine ; on affiche l'invite.
ProdBoucle:
lea si,PlaceLibre ; on attend qu'il y ait de la place dans le buffer
call p
AttendreTouche:
lea si,DosBios
mov ah,06 ; fonction du dos, voir si une touche est frappée.
mov dl,255 ; entrée ( paramètre de la fonction)
call p ; exclusion mutuelle pour Dos & Bios
int 21h
call v
jz AttendreTouche ; ZF=1 si aucune touche, sinon AL = Code ASCII
lea si,mutex ; on place la touche dans le buffer
call p
lea si,LeTampon
call (TAMPON PTR [si]).Ajouter
lea si,mutex
call v
lea si,CarDisponible ; on signale au consommateur qu'il a du boulot
call v
cmp al,0Dh ; a-t-on appuyé sur Return ?
jne ProdBoucle ; non, on continue
lea si,sPrincipal ; si oui, on termine
call v
call Suicide
Producteur ENDP
; processus consommateur : gestion des caractères placés dans le buffer
; circulaire.
Consommateur PROC
mov ax,@data
mov ds,ax
ASSUME ds:@data
mov ax,0B800h
mov es,ax
ASSUME es:Nothing
mov di,24+13*160 ; départ de l'affichage (12,13)
AttendreTampon:
lea si,CarDisponible ; on attent le boulot
call p
lea si,mutex ; on extrait le caractère de tete
call p
lea si,LeTampon
call (TAMPON PTR [si]).Retirer
lea si,mutex
call v
lea si,PlaceLibre ; on signale la place libérée
call v ; au producteur
cmp al,0Dh ; Return ?
je finConso ; oui, on termine
cmp al,08 ; a-t'on appuyé sur Backspace
jne pas_del ; non, on saute
sub di,2 ; si oui, on efface le caractère précédent
mov byte ptr es:[di],' '
jmp del
pas_del:
mov es:[di],al ; on affiche le caractère
add di,2
del:
jmp AttendreTampon ; et on continue ....
finConso:
lea si,sPrincipal ; signale à Principal qu'un de ses fistons
call v ; va mourrir
call Suicide ; et hop !
Consommateur ENDP
GestEcran PROC ; Processus d'affichage d'un bel écran tout joli !!!
mov ax,@data
mov ds,ax
ASSUME ds:@data
call Clear_Screen ; on efface l'écran.
mov ah,10 ; on affiche un cadre (10,6)->(70,19)
mov al,6 ;
mov bh,70 ; ( Fenètre principale. )
mov bl,19 ;
mov dx,23 ; d'attribut 23
call Trace_Cadre ;
mov ah,1 ; on affiche un cadre (1,22)->(7,24)
mov al,22 ;
mov bh,7 ; ( Fenètre où sera affichée l'horloge. )
mov bl,24 ;
mov dx,5Fh ; attribut = 5Fh
call Trace_Cadre ;
mov ah,10 ; Encore un cadre (10,21)->(70,25)
mov al,21 ;
mov bh,70 ; ( Fenètre contenant la balle )
mov bl,25 ;
mov dx,26 ; attribut = 26
call Trace_Cadre ;
lea si,ChainePro1 ; on affiche les chaines de caractères
mov di,24+6*160
call Affiche_Chaine
lea si,ChainePro2
mov di,24+7*160
call Affiche_Chaine
lea si,ChainePro3
mov di,24+8*160
call Affiche_Chaine
lea si,ChainePro4
mov di,24+9*160
call Affiche_Chaine
lea si,ChainePro5
mov di,24+10*160
call Affiche_Chaine
lea si,ChainePro6
mov di,24+11*160
call Affiche_Chaine
; on trace le cadre du haut, taille et centrage automatique sur la chaine
; la plus longue ( Chaine2 ), grace à SIZEOF
mov ah,((80-SIZEOF Chaine2)/2)-2
mov al,1
mov bh,((80-SIZEOF Chaine2)/2)+(SIZEOF Chaine2)+2
mov bl,4
mov dx,71
call Trace_Cadre ; on trace un cadre
; et on affiche les deux chaines dans le cadre ( centrée également )
lea si,Chaine1
mov di,2*((80-SIZEOF Chaine1)/2)+160
call Affiche_Chaine
lea si,Chaine2
mov di,2*((80-SIZEOF Chaine2)/2)+320
call Affiche_Chaine
lea si,sPrincipal ; c'est fait, bye bye ....
call v
call Suicide
GestEcran ENDP
; processus numéro 1
; Ce processus est un compteur qui est synchronisé avec le processus 2
process PROC
mov ax,@data
mov ds,ax
ASSUME ds:@data
mov ax,0B800h
mov es,ax
mov di,57*2+160*6 ; ( affichage en (57,6))
mov cx,5 ; on effectue 5 fois le comptage
Bcl1:
mov ax,0
Boucle:
push cx
mov cx,9 ; on affiche ax sur 9 chiffres.
call Affdec
pop cx
inc ax
cmp ax,50000
jbe Boucle ; on boucle
lea si,Synchro1
call v ; on signale au process2 qu'il peut commencer
lea si,Synchro2 ; attend qu'il ait fini pour continuer.
call p
loop Bcl1
lea si,sPrincipal
call v
call Suicide
process ENDP
; Voici le processus associé au processus 1
process2 PROC
pusha
mov ax,@data
mov ds,ax
ASSUME ds:@data
mov ax,0B800h
mov es,ax
mov di,114+7*160
mov cx,5 ; idem que le processus précédent
Bcl2:
lea si,Synchro1 ; on attend le processus 1
call p
mov ax,0
Boucle2:
push cx
mov cx,9
call Affdec ; on affiche le compteur
pop cx
inc ax
cmp ax,60000 ; jusqu'à 60000
jbe Boucle2
lea si,Synchro2 ; on signale au processus 1 qu'il peut bosser
call V
loop Bcl2
lea si,sPrincipal
call v
call Suicide
process2 ENDP
; processus de compteur
process3 PROC
pusha
mov ax,@data
mov ds,ax
ASSUME ds:@data
mov ax,0B800h
mov es,ax
mov di,114+8*160
mov cx,10 ; dix fois
Bcl3:
mov ax,0
Boucle3:
push cx
mov cx,9
call Affdec ; on affiche le compteur
pop cx
inc ax
cmp ax,65000 ; jusqu'à 65000
jbe Boucle3
loop Bcl3
lea si,sPrincipal
call v
call Suicide
process3 ENDP
Process4 PROC
mov ax,@data
mov ds,ax
ASSUME ds:@data
mov ax,0B800h
mov es,ax
mov di,114+9*160
mov cx,10
Bcl4:
mov ax,0
Boucle4: ;
push cx ;
mov cx,9 ; Idem processus 3
call Affdec ;
pop cx ;
inc ax ;
cmp ax,65534 ;
jbe Boucle4 ;
loop Bcl4
lea si,sPrincipal
call v
call Suicide
Process4 ENDP
Process5 PROC
mov ax,@data
mov ds,ax
ASSUME ds:@data
mov ax,0B800h
mov es,ax
mov di,114+10*160
mov cx,10
Bcl5:
mov ax,0
Boucle5:
push cx
mov cx,9
call Affdec
pop cx
inc ax
cmp ax,65534
jbe Boucle5
loop Bcl5
lea si,sPrincipal
call v
call Suicide
Process5 ENDP
Process6 PROC
mov ax,@data
mov ds,ax
ASSUME ds:@data
mov ax,0B800h
mov es,ax
mov di,114+11*160
mov cx,10
Bcl6:
mov ax,0
Boucle6:
push cx
mov cx,9
call Affdec
pop cx
inc ax
cmp ax,65534 ; même chose
jbe Boucle6
loop Bcl6
lea si,sPrincipal
call v
call Suicide
Process6 ENDP
; Procedure d'affichage en base 10
;
; es:di = affichage
;
; cx : nombre de caractères à afficher
;
; ax = nombre à afficher
;
AFFDEC PROC
pusha
add di,cx
add di,cx
sub di,2
affich:
xor dx,dx
mov bx,10
div bx ; on divise successivement par 10
add dl,30h ; et on affiche les restes
mov es:[di],dl
sub di,2
dec cx
cmp ax,bx
jl finaff
jmp affich
finaff:
add al,30h
mov es:[di],al ; puis, on affiche le dernier résultat
sub di,2
dec cx
cmp cx,0
jz finaff3
finaff2:
mov dl,30h ; on affiche les 0 restants.
mov es:[di],dl
sub di,2
loop finaff2
finaff3:
popa
RET
AFFDEC ENDP
END