Sunteți pe pagina 1din 104

PREFA

Sistemul de operare reprezint un ansamblu de programe


care asigur utilizarea optim a resurselor fizice i logice ale unui
sistem de calcul. Sistemul are rolul de a gestiona funcionarea
componentelor hardware ale sistemului de calcul, de a coordona i
a controla execuia programelor i a permite accesarea sistemului
de calcul de cter utilizator. Folosirea hardware al unui sistem de
calcul ar fi dificil i ineficient n lipsa unui sistem de operare. Pe
scurt, sistemul de operare este componenta software care
coordoneaz i supravegheaz ntreaga activitate a sistemului de
calcul i asigur accesul utilizatorului la sistemul de calcul.
Procesul este o suit temporal de execuii de instruciuni,
fiind o entitate de baz n descrierea sau analiza funcionrii unui
sistem. Evoluia n timp a unui proces presupune un consum de
resurse dictat de natura i complexitatea instruciunilor de executat.
Orice utilizare a unei resurse este asociat la un moment dat unui
proces, iar procesul respectiv este responsabil de utilizarea acestei
resurse.
Lucrarea de fa conine material referitor la mijloacele
necesare pentru limbajele de asamblor i a sistemelor de operare.
n prima parte snt abordate mecanismele de sincronizare a
proceselor din cadrul sistemului de operare. n capitolul 1 snt date
noiunile i principiile de baz ale proceselor, snt analizate
mecanismele de planificare a activitii proceselor. Capitolul 2 este
destinat analizei metodelor de sincronizare a proceselor pe baza
problemei clasice a scriitorilor i cititorilor. n capitolul 3 este
expus prezentarea teoretic i snt descrise aspectele problemei
Algoritmul bancherului. n capitolul 4 snt abordate aspecte din
teoria problemei Cina filozofilor. Capitolul 5 este destinat
analizei principiilor de creare i utilizare a excepiilor.
Partea a doua este destinat studierii limbajului de asamblare i
include noiunile teoretice principale privind efectuarea a patru lucrri
de laborator.
3

n capitolul unu este descris mediul de asamblare turboassembler, modul de dezvoltare a unui program n acest mediu, plus
dou exemple executabile de tip exe i com.
Capitolul doi este destinat studierii setului de instruciuni al
microprocesorului 8086,
include nouni privind dezvoltarea
programelor liniare i a ramificrilor ct i subecte pentru efectuarea
primei lucrri de laborator.
Sarcina pentru efectuarea lucrrii de laborator numrul doi este
inclus n capitolul trei, mai fiind inserate instruciunile i directivele
uzuale pentru implementarea procedurilor i macroinstruciunilor n
programare.
Interfaa limbajului de asamblare cu limbaje de programare de
nivel nalt, precum i sarcinile privind efectuarea lucrrii de laborator
numrul trei snt incluse n capitolul patru.
Capitolul cinci este destinat studierii sistemelor de ntreruperi
BIOS i DOS, precum descrierea funciilor principale ale ntreruperii
int 21h destinate pentru efectuarea lucrrii de laborator numrul patru.
Primele patru lucrri de laborator vor fi ndeplinite utiliznd
limbajul de programare orientat pe obiect Java. Lucrrile din partea
a doua vor fi efectuate n limbajul asamblor.
Pentru a fi admis la efectuarea lucrrii de laborator, studentul
trebuie s ntruneasc urmtoarele condiii:
ndeplinirea sarcinii individuale pentru lucrarea de laborator
conform variantei;
cunoaterea materialului teoretic indicat pentru ndeplinirea
lucrrii, demonstrat prin rspunsurile la ntrebrile profesororului.
Lucrarea de laborator se consider ndeplinit doar dup ce
studenii demonstreaz profesorului corectitudinea circuitelor i a
testelor elaborate.
La fiecare lucrare de laborator studentul pregtete o dare de
seam pe care o susine n faa profesorului. Darea de seam
include: foaia de titlu, tema, scopul lucrrii, listingul programului,
rezultatul realizrii programului, concluzii i interpretarea
rezultatului.
4

PARTEA 1
1. Planificarea activitii proceselor
1.1. Timerul
Timerul este un dispozitiv care notific periodic aplicaia c a
expirat o anumit perioad de timp prestabilit. Programul specific
intervalul de timp pe care l trimite timerului indicnd intervalul de
expirare. Timerul este important pentru efectuarea multor aplicaii.
1.2. Utilizarea timerului.
Pentru a ataa un timer unui program trebuie utilizat clasa
Timer, care ofer facilitatea de a planifica diverse
aciuni pentru a fi realizate la un anumit moment de
ctre o aplicaie ce ruleaz.
Aciunile unui obiect de tip Timer snt
implementate ca instane ale clasei TimerTask i pot fi
programate pentru o singur execuie sau pentru
execuii repetate la intervale regulate. Pentru
folosirea unui timer trebue traversai urmtorii pai:
crearea unei
subclase
aciune a lui
TimerTask i
suprascrierea metodei
run()
ce va conine
aciunea planificat. Dup cum se observ, pot fi
folosite si clase anonime;
crearea unui fir de execuie prin instanierea
clasei Timer;
crearea unui obiect de tip aciune;
planificarea la execuie a obiectuluii de tip
aciune, folosind metoda schedule() din clasa Timer.
Metodele de planificare pe care le putem utiliza
au urmtoarele formate:
schedule(TimerTask task, Date time)
schedule(TimerTask task, long delay, long period)
schedule(TimerTask task, Date time, long period)
5

scheduleAtFixedRate(TimerTask task, long delay, long


period)
scheduleAtFixedRate(TimerTask task, Date time, long
period)
unde:
task - descrie aciunea ce se va executa;
delay- reprezint ntrzierea fa de momentul curent
dup care va ncepe execuia;
time - momentul exact la care va ncepe execuia;
period - intervalul de timp dintre dou execuii.
Metodele de planificare se mpart n dou
categorii:
schedule() - planificare cu ntrziere fix: dac
dintr-un anumit motiv acunea este ntrziat,
urmtoarele aciuni vor fi i ele ntrziate n
consecin;
scheduleAtFixedRate() - planificare cu numr fix de
rate: dac
aciunea este ntrziat, urmtoarele
aciuni vor fi executate mai repede, astfel nct
numrul total de aciuni dintr-o perioad de timp s
fie tot timpul acelai.
Un timer se va opri la expirarea metodei sale
run() dar tot odat poate fi oprit forat, folosind
metoda cancel(). Dup oprire acesta nu va mai putea
fi folosit pentru planificarea altor aciuni. De
asemenea, prin metoda System.exit() vom opri forat
toate firele de execuie i va termina aplicaia
curent.
Exemplul 1: folosirea claselor Timer i
TimerTask
import java.util .*;
import java.awt .*;
class Atentie extends TimerTask {
public void run () {
Toolkit.getDefaultToolkit(.beep();
6

System.out.print(".");
}}
class Alarma extends TimerTask {
public String mesaj ;
public Alarma(String mesaj) {
this.mesaj = mesaj ;
}
public void run() {
System.out.println( mesaj );
}}
public class TestTimer {
public static void main(String args []) {
// Setm o aciune repetitiv, cu rat fix
final Timer t1 = new Timer ();
t1.scheduleAtFixedRate(
new Atentie(), 0, 1*1000) ;
// Clas anonima pentru o alt aciune
Timer t2 = new Timer ();
t2. schedule ( new TimerTask() {
public void run() {
System.out.println("Au trecut 10 secunde");
// Oprim primul timer
t1. cancel();
}}, 10*1000) ;
// Setm o aciune pentru ora 13:15
Calendar calendar = Calendar.getInstance();
calendar.set( Calendar . HOUR_OF_DAY, 13);
calendar.set( Calendar .MINUTE, 15);
calendar.set( Calendar .SECOND, 0);
Date ora = calendar.getTime();
Timer t3 = new Timer();
t3.schedule(new Alarma "Ora mesei!"), ora );
}}
Rezultatul realizrii:
init:
deps-jar:
7

Compiling 1 source file to C:\Documents and


Settings\User\JavaApplication2\build\classes
compile-single:
run-single:
..........Au trecut 10 secunde
Ora mesei!
Exemplul urmtor este o fereastr cu trei butoane i cu trei obiecte
de tip Timer. Fiecare obiect Timer controleaz un buton, adic la
trecerea intervalului specific fiecrui timer se incrementeaz
numrul de pe butonul corespunztor. La crearea obiectelor de tip
Timer specificm intervalul de timp la care acioneaz respectiv i
obiectul listener, adic componenta care este notificat. Timerul
trimite mesajul actionPerformed() dup trecerea intervalului de
timp. Obiectul Timer trebuie pornit prin accesarea metodei start().
Exemplul 2: o fereastr cu trei butoane i cu
trei obiecte de tip Timer.
import javax.swing.JFrame;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.Timer;
import java.awt.event.ActionEvent;
public class MyWindow extends JFrame
implements ActionListener {
private JButton b[];
private Timer t[];
public MyWindow() {
final int n = 3;
int i;
getContentPane().setLayout( new
java.awt.FlowLayout() );
b = new JButton[ n ];
for(i=0;i<n;i++){

b[i] = new
JButton(Integer.toString( i ));
getContentPane().add( b[ i ] );
}
addWindowListener( new
java.awt.event.WindowAdapter(){
public void windowClosing
(java.awt.event.WindowEvent e )
{
setVisible( false );
System.exit( 0 );
}});
t = new Timer[ n ];
for(i=0;i<n;i++){
t[ i ] = new Timer( (i+1)*100, this );
t[ i ].start();
}}
public static void main(String[] args) {
MyWindow w = new MyWindow();
w.setBounds(1,1,400,300);
w.setVisible( true );
}
public void
actionPerformed(ActionEvent arg0) {
if( arg0.getSource() == t[0] ){
System.out.println( "Button: "+0);
b[0].setLabel(Integer.toString(
Integer.parseInt(b[0].getLabel())+1));
}
else
if( arg0.getSource() == t[1] ){
System.out.println( "Button: "+1);
b[1].setLabel( Integer.toString( Intege
r.parseInt(b[1].getLabel())+1 ));
}
9

else
if( arg0.getSource() == t[2] ){
System.out.println( "Button: "+2);
b[2].setLabel( Integer.toString( Intege
r.parseInt(b[2].getLabel())+1 ));
}}}
Rezultatul realizrii programului este prezentat n figura 1.1.
n exemplul urmtor se creeaz un MP3 Player n Java,
folosind obiectul Jslider i obiectul Timer.

Fig 1.1. Rezultatul executrii exemplului 2.


Exemplul 3: MP3 Player n Java
folosind
obiectul Jslider i obiectul Timer.
package sky.developer.java.mozku;
import java.awt.BorderLayout;
import java.util.Timer;
import java.util.TimerTask;
10

import javax.swing.JFrame;
import javax.swing.JSlider;
public class JavaSlider{
public static void main(String
[]args){
// Declarare variabile
final int valoareMinima = 0;
final int valoareMaxima = 100;
final int valoareInitiala = 0;
final int valoareDeCrestere = 10;
// Construim fereastra
JFrame fereastra = new
JFrame("Fereastra Mea");
// Construim si adaugm slider-ul
final JSlider sliderNou = new
JSlider(JSlider.HORIZONTAL,
valoareMinima, valoareMaxima,
valoareInitiala);
sliderNou.addChangeListener(null);
sliderNou.setMinorTickSpacing(10);
sliderNou.setPaintTicks(true);
fereastra.getContentPane().add(sliderNou
, BorderLayout.CENTER);
// Proprietile ferestrei
fereastra.pack();
11

fereastra.setVisible(true);
fereastra.setDefaultCloseOperation(JFram
e.EXIT_ON_CLOSE);
// Crearea timer-ul
int delay = 0;
int period = 1000; // 1000
milisecunde = 1 secunda
Timer timer = new Timer();
timer.scheduleAtFixedRate(new
TimerTask(){
int valoareCurenta = 0;
public void run(){
//Codul care se va executa la fiecare
//secund.
if (valoareCurenta <
valoareMaxima){
valoareCurenta =
valoareCurenta + valoareDeCrestere;
sliderNou.setValue(valoareCurenta);
}
else{
this.cancel();
}}
}, delay, period);
12

}}
Se va afia un Jslider, iar cu ajutorul unui Timer vom mica
slider-ul timp de 10 secunde.
Rezultatul realizrii programului este prezentat n figura
1.2. La nceputul programului snt declarate 4 variabile care se
folosesc n administrarea slider-ului. O valoare minim, o
valoare maxim i o valoare initial servesc pentru a crea
obiectul JSlider. Dupa ce a fosr construit acest obiect, se seteaz
distanta dintre liniile riglei de sub slider, fiind 10 la numr, i
snt afiate.

Fig. 1.2. Rezultatul executrii exemplului 3


n continuare, dup afisarea ferestrei, s-a construit timerul.
n cadrul clasei Timer am declarat o nou variabil, valoareCurenta,
care indic ce valoare are sliderul la un moment dat. Prin
comanda sliderNou.setValue(valoareCurenta)
setm
valoarea
sliderului.
Un fir de execuie (thread) este similar acestor programe
secveniale, n sensul ca are un nceput, o secven de execuii i un
sfrit i n orice moment pe durata execuiei firului exist un singur
punct de execuie.
ns un fir nu este el insui un program, deoarece nu poate fi
executat de sine stttor. n schimb, firul este executat (ruleaz) ntrun program. Posibilitatea utilizrii mai multor fire de execuie ntrun singur program, rulnd (fiind executate) in acelai timp i
realiznd diferite sarcini, este numit multithreading.

13

n exemplul urmror este prezentat un program "ceas" bazat pe


threads n applet.
Exemplul 4:program "ceas" bazat pe threads
import java.applet.Applet;
import java.awt.*;
import java.util.*;
import java.text.DateFormat;
public class CeasApplet extends Applet
implements Runnable {
private Thread firCeas = null;
private static int contor = 0;
public void init()
{ setBackground(Color.white); }
public void start() {// (re)pornire fir
if (firCeas == null) {
firCeas = new Thread(this, "Ceas");
firCeas.start();// apeleaza run()
} }
public void run() { // executie fir
Thread firulMeu = Thread.currentThread();
contor++;
while (firCeas == firulMeu) {
repaint();
// apeleaza paint() (redeseneaza)
try { Thread.sleep(1000); }
catch (InterruptedException e){ }
}}
public void paint(Graphics g) {
// deseneaza
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
DateFormat df =
DateFormat.getTimeInstance();
g.drawString("[" + contor + "] " +
df.format(date), 5, 10);
}
14

public void stop(){


// oprire fir
firCeas = null;
// firul dispare
}}
// Applet-ul nu are metoda principala.
// Metodele start(), stop(), run(),
//etc. snt invocate
// de Browserul Web in care este executat.
/*
Exemplu de includere intr-o pagina
Web:
<HTML>
<TITLE>
Applet Ceas
</TITLE>
<BODY>
<APPLET CODE=CeasApplet.class
WIDTH=200 HEIGHT=50>
</APPLET>
</BODY>
</HTML>
*/
1.3. Lucrare de laborator nr. 1
1. Tema lucrrii:
Elaborarea unui mecanizm de planificare a activitii proceselor.
2. Scopul lucrrii:
nsuirea modalitilor de creare a mecanizmelor de
planificare;
nsuirea modalitilor de prelucrare a mecanizmului de
planificare;
3. Etapele de efectuare:
- crearea firelor de execuie;
- crearea i iniializarea obiectelor de prelucrare a firelor de
execuie;
- crearea interfeei programului;
- prezentarea lucrrii.
15

4. Exemplu de efectuare:
import
import
import
import
import
import
import

java.awt.*;
java.io.*;
java.util.*;
java.util.logging.Level;
java.util.logging.Logger;
javax.imageio.*;
javax.swing.*;

public class Lab1SO {


public static void main(String[] args) {
MyFrame f = new MyFrame();
f.setVisible(true);
}}
class MyFrame extends JFrame {
MyFrame() {
this.setSize(600, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_
CLOSE);
this.add(new MyPanel());
}}
class MyPanel extends JPanel {
MyPanel() {
c = new Ceas();
c.runH();
c.runM();
c.runS();
t.start();
url = "/home/denis/Downloads/cl/";
setBackground(Color.GREEN);
}
@Override
Protected void paintComponent(Graphics g) {
16

super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
//g2.drawString(c.toString(), 30,
30);
Image image1 = null;
Image image2 = null;
g2.drawImage(getImage1(c.getH()), 50,
50,null);
g2.drawImage(getImage2(c.getH()),
100, 50,null);
g2.drawImage(getImage1(c.getM()),
200, 50,null);
g2.drawImage(getImage2(c.getM()),
250, 50,null);
g2.drawImage(getImage1(c.getS()),
350, 50,null);
g2.drawImage(getImage2(c.getS()),
400, 50,null);
}
private Image getImage1(int n){
int p1;
p1 = n/10;
Image i1=null;
try {
i1 = ImageIO.read(new
File(url+p1+".PNG"));
} catch (IOException ex) {
Logger.getLogger(MyPanel.class.getName()).log
(Level.SEVERE, null, ex);
}
return i1;
}
private Image getImage2(int n){
int p1;
p1 = n%10;
17

Image i1=null;
try {
i1 = ImageIO.read(new
File(url+p1+".PNG"));
} catch (IOException ex) {
Logger.getLogger(MyPanel.class.getName()).log
(Level.SEVERE, null, ex);
}
return i1;
}
private Ceas c;
private String url;
private Thread t = new Thread() {
@Override
public void run() {
while (true) {
repaint();
try {
sleep(1000);
} catch (InterruptedException
e) {
}
}
}
};
}
class Ceas {
Ceas() {
Date d = new Date();
h = d.getHours();
m = d.getMinutes();
s = d.getSeconds();
}
public int getH(){
return h;
}
public int getM(){
return m;
18

}
public int getS(){
return s;
}
@Override
public String toString() {
return h + " : " + m + " : " + s;
}
private void setH() {
h = new Date().getHours();
}
private void setM() {
m = new Date().getMinutes();
}
private void setS() {
s = new Date().getSeconds();
}
public void runH() {
Thread t = new Thread() {
@Override
public void run() {
while (true) {
setH();
}
}
};
t.start();
}
public void runM() {
Thread t = new Thread() {
@Override
public void run() {
while (true) {
setM();
}
}
t.start();
}
19

};

public void runS() {


Thread t = new Thread() {
@Override
public void run() {
while (true) {
setS();
}
}
t.start();
}
private int h, m, s;

};

}
Rezultatul realizrii programului este prezentat n figura 1.3.

Fig. 1.3. Rezultatul executrii programului.


5. Probleme propuse:
Creai o aplicaie cu unu sau mai multe fire de execuie care
realizeaz:
1. Un ceas (HH: MM: SS), care folosete un timer pentru a
actualiza n fiecare secund.
2. Un ceas (HH: MM: SS), care folosete un timer pentru a
actualiza la fiecare minut.
20

3. Un ceas (HH: MM: SS), care folosete un timer pentru a


actualiza n fiecare or.
4. Un ceas (HH: MM: SS), care folosete un timer pentru a
determina reapariia procesului la fiecare minut.
5. Un ceas (HH: MM: SS), care folosete un timer pentru a
determina durata procesului n secunde.
6. Ceas Analogic, formai imagine. Utilizai un timer pentru
a actualiza n fiecare secund.
7. Ceas Analogic, formai imagine. Utilizai un timer pentru
a actualiza la fiecare minut.
8. Ceas Analogic, formai imagine. Utilizai un timer pentru
a actualiza n fiecare or.
9. Ceas Analogic, formai imagine. Utilizai un timer pentru
a determina reapariia procesului n fiecare minut.
10. Ceas Analogic, formai imagine. Utilizai un timer
pentru a determina durata procesului n secunde.
2. Sincronizarea proceselor
2.1. Problema cititorilor i scriitorilor
Un obiect (care poate fi o resurs, de exemplu un fiier sau o
zon de memorie) este partajat de mai multe procese concurente.
Dintre aceste procese, unele doar vor citi coninutul obiectului
partajat i aceste procese poart numele de cititori, iar celelalte vor
scrie n coninutul obiectului partajat, purtnd numele de scriitori.
Cerina este ca scriitorii s aib acces exclusiv la obiectul
partajat, n timp ce cititorii s poat accesa obiectul n mod
concurent (neexclusiv).
Exist mai multe posibiliti de a soluiona aceast
problem. Vom aminti dou variante:
Varianta 1
Nici un cititor nu va fi inut n ateptare, dect dac un
scriitor a obinut deja permisiunea de acces la obiectul partajat.
La un acces simultan la obiectul partajat att al scriitorilor, ct i al
cititorilor, cititorii au prioritate.
21

Varianta 2
Cnd un scriitor este gata de scriere, el va executa scrierea
ct mai curnd posibil. La un acces simultan, scriitorii snt
prioritari.
Oricum, n ambele cazuri, problema principal ce trebuie
rezolvat este nfometarea, adic ateptarea la infinit a obinerii
dreptului de acces.
Implementm un program pentru prima variant, folosind
urmtoarele semafoare, mutexuri i variabile:
scrie un semafor cu mai multe roluri; el asigur excluderea
mutual a scriitorilor; este folosit de ctre primul cititor care intr n
propria seciune critic; de remarcat c acest semafor nu este utilizat de
cititorii care intr sau ies din seciunea critic n timp ce ali cititori se afl
n propria seciune critic;
contorcitire o variabil care are rolul de a ine evidena
numrului de procese existente n cursul citirii;
semcontor un semafor care asigur excluderea mutual cnd
este actualizat variabila contorcitire.

Dac un scriitor este n seciunea critic i n cititori


ateapt, atunci un cititor ateapt la semaforul scriere, iar ceilali
nu-1 ateapt la semcontor.
La signal(scrie) se poate relua fie execuia unui singur
scriitor, fie a cititorilor aflai n ateptare, decizia fiind luat de
planificator.
n continuare dm programul algoritm pentru prima
variant:
Exemplul 1: nici un cititor nu va fi inut n
ateptare, dect dac un scriitor a obinut
deja
permisiunea
de
acces
la
obiectul
partajat.
int semafor;
/*declaraii i iniializri*/
int contorcitire=0;
semafor scrie=1,
semcontor=1 ;
void scriitor()
22

{wait(scrie) ;
scriereobiect() ;
signal(scrie) ;}
void cititor()
{wait(semcontor) ;
contor citire++;
if(contorcitire==1)wait(scrie);
//primul cititor
signal(semcontor);
citireobiect();
wait(semcontor);
contor citire--;
if(contorcitire==0)signal(scrie);
//ultimul cititor
signal(semcontor);}
Considerm o baz de date i multe procese prin care se
poate accesa aceast baz de date pentru scriere sau citire. Se
permite ca mai multe procese s citeasc simultan, dar dac unul din
procese vrea s scrie (s modifice) baza de date, nici unul din
celelalte procese nu are voie s acceseze baza de date (nici pentru
scriere, nici pentru citire).
Mai jos, prezentm o soluie.
Primul cititor care acceseaz baza de date execut un
DOWN pe un semafor db (nepermiand nici unui scriitor s
acceseze baza de date). Urmtorii cititori incrementeaz un contor
rc. Pe msur ce cititorii pleac, contorul este decrementat, iar
ultimul execut un UP pe semaforul db, permiand astfel scriitorului
blocat, dac exist, s acceseze baza de date.
Aceast soluie d prioritate cititorilor asupra scriitorilor.
Astfel, dac un scriitor apare n timp ce ali cititori se afl deja n
baza de date, scriitorul trebuie s astepte pn pleac toi cititorii.
Exemplul
2:
prioritatea
cititorilor
asupra scriitorilor.
int semafor;
/*Controleaz accesul
semafor mutex=1; la rc controleaz accesul
23

semafor db=1;
int rc=0;
void
cititor(void){
while(1){
down(mutex);
if(+
+rc==1)
down(db);

la baza de date */
/* nr. procese cititor */

/* ciclu infinit */
/* acces exclusiv al
variabilei rc */
/*dac este primul
cititor => nici un alt
scriitor nu mai*/
/*poate accesa baza de date*/
/*iese din regiunea critic*/

up(mutex);
/*acceseaz baza de date */
citeste_baza_de_
date();
down(mutex);
if(-rc==0)
up(db);
up(mutex);
}
}
void scriitor(){
while(1){
down(db);
scrie_n_baza_de
_date();
up(db);

/* acces exclusiv al
variabilei rc */
/* dac este ultimul
cititor => se permite
accesul scriitorilor */
/*iese din regiunea critic*/

/*
/*
de
/*

ciclu infinit */
acces exclusiv la baza
date */
modific baza de date */

/* permite altor procese


s acceseze baza de date*/
24

}}
Soluionarea problemii clasice a cititorilor i scriitorilor
pentru mai muli cititori i mai muli scriitori. Scriitorii i cititorii
lucreaz cu mai multe obiecte.
Exemplul 3: realizarea problemei cititorilor
i scriitorilor
import java.util.*;
public class Lab2Sola {
int NrWritters=16;
int NrReaders=30;
int NrBooks=9;
int[] stare=new int[NrWritters];
class Writer extends Thread {
private Library lyb;
private int number;
private int writenBooks;
public Writer(Library c, int number) {
lyb = c;
this.number = number;
this.writenBooks=0;
}
public @Override void run() {
Random r=new Random();
int value=0;
int index=0;
while(this.writenBooks<NrBooks) {
if(lyb.accessAllowed){
lyb.accessAllowed=false;
System.out.println("Scriitorul "+number+"
asteapta...");
while(true){
if(lyb.readersCount<=0){
System.out.println("Scriitorul "+number+
" a intrat in biblioteca.");
25

value=r.nextInt(100);
index=r.nextInt(lyb.capacity);
lyb.write(value,index);
this.writenBooks++;
lyb.readersCount=0;
break;
}
else{
try{
sleep(50);
}
catch(InterruptedException e) { }
}}
lyb.accessAllowed=true;
System.out.println("Scriitorul "+number+"
scrie: "+value+" a "+this.writenBooks+" carte
in indexul: "+index);
//notify();//All();
try{
sleep(300);
}catch(InterruptedException
e) { }
}
else{
try{
sleep(200);
}catch(InterruptedException
e) { }
}}
if(this.writenBooks>=NrBooks)
{
stare[this.number]=1;
}}}
class Reader extends Thread {
private Library lyb;
private int number;
public Reader(Library c, int number) {
26

lyb = c;
this.number = number;
}
public @Override void run() {
Random r=new Random();
int value;
int index;
while(verify()!=1){
if(lyb.accessAllowed){
lyb.readersCount++;
System.out.println("Cititorul "+number+"
a intrat in biblioteca.");
index=r.nextInt(lyb.capacity);
value = lyb.read(index);
try{
sleep(1);
}catch(InterruptedException
e) { }
System.out.println("Cititorul "+number+" a
citit: "+value+" la indexul: "+index);
System.out.println("Cititorul "+number+" a
iesit din biblioteca.");
lyb.readersCount--;
//notify();
try{
sleep(100);
}catch(InterruptedException
e) { }
}
else{
try{
sleep(200);
}catch(InterruptedException
e) { }
}}}}
static class Library {
27

public boolean accessAllowed;


public int readersCount;
public int info[];
public int capacity;
public Library(){
accessAllowed=true;
readersCount=0;
capacity=30;
info=new int[30];
for(int i=0;i<capacity;i++){
info[i]=i;
}}
public int read(int i) {
return info[i];
}
public void write(int newInfo,int i)
info[i]=newInfo;
}}
private int verify(){
for (int i=0;i<NrWritters;i++){
if (this.stare[i]==0)
return 0;
}
return 1;
}
public void run(){
for( int i=0;i<16;i++){
Library lib=new Library();
Writer scriitor=new Writer(lib, i);
scriitor.start();
}
for(int j=0;j<30;j++){
Library lib=new Library();
Reader cititor=new Reader(lib,j);
cititor.start();
}
while(true){
28

if(this.verify()==1)
// System.exit(0);
{
System.out.println("Scriitorii au
terminat de scris");
System.exit(0);
}}}
public static void main(String[] args) {
new Lab2Sola().run();
}}
2.2. Lucrarea de laborator nr. 2
1. Tema lucrrii:
Implimentarea metodelor de sincronizare a proceselor
2. Scopul lucrrii:
nsuirea modalitilor i a mecanizmelor de sincronizare;
nsuirea modalitilor de realizare a mecanizmelor de
sincronizare;
3. Etapele de efectuare:
sincronizarea firelor de execuie;
realizarea metodelor de sincronizare a firelor de execuie;
crearea interfeii programului;
prezentarea lucrrii.
4. Exemplu de efectuare:
package sola5_nb;
import java.util.*;
class Writer extends Thread{
private static int writtenbooks=0;
private String name;
public static int semaphore=0;
public static Vector<String>
writtenCount=new Vector<String>();
29

// public static int writerCount=9;


public static int bookCount=14;
public Writer(int name){
this.name=String.valueOf(name);
System.out.println(name + " Scriitor ");
}
public void run(){
while(writtenbooks<bookCount){
if (semaphore==0){
semaphore=1;
writtenbooks++;
writtenCount.add(String.valueOf
(writtenbooks));
System.out.println(" Obiectul este scris "
+ writtenbooks + " de scriitorul " + name);
System.out.println(" Obiecte scrise " +
writtenCount.size());
if (writtenCount.size()==bookCount){
System.out.println("\n---Toate obiectele
snt scrise---\n");
}
semaphore=0;
try
{sleep(1000);}
catch(InterruptedException e){
}}}
this.stop();
}}
class Reader extends Thread{
private static int readbooks=0;
private static int stopAll=0;
private String name;
public static Vector<String>
readCount=new Vector<String>();
public Reader(int name){
this.name=String.valueOf(name);
30

System.out.println("
"+name + " Cititor");
}
public void run(){
if (Writer.semaphore==0)
while (readbooks<Writer.bookCount){
for(int i=0; i<Writer.writtenCount.size();
i++){
if (readCount.size()==readbooks){
if (stopAll==0){
System.out.println(" Obiecte necitite "
+ (Writer.bookCount-readbooks));
System.out.println("----Toate obiectele
scrise snt citite-----");
stopAll=1;
}
this.stop();
}
else{
System.out.println(" Este citit obiectul "
+ Writer.writtenCount.elementAt(i) + " de
cititorul " + name);
if (readCount.elementAt(i).equals("0")){
readCount.set(i, "1");
readbooks++;
}
try
{ sleep(500);}
catch(InterruptedException e){
}}}}
this.stop();
}}
public class lab_sola{
public static void main(String[] args){
Reader.readCount=new Vector<String>();
//vectorul pentru obiectele citite
31

for (int i=0; i<14; i++)


Reader.readCount.add(String.valueOf(0));
//iniializarea tabloului cu 0
Vector<Writer> w=new Vector<Writer>();
//cititorii
for(int i=0; i<9; i++){
/*fiecare scriitor adaug n poziia "i" cu
numele, identic cu numrul poziiei*/
w.add(i, new Writer(i+1));
}
Vector<Reader> r=new Vector<Reader>()
//cititorii
for(int i=0; i<2; i++){
r.add(i, new Reader(i+1));
}
/*ciclu pentru firele de execuie, egal
max(numrul de scriitori, numrul de
cititori)*/
for(int i=0; i<Math.max(w.size(), r.size());
i++)
{
/*dac elementul curent este ntre
scriitori/citirori, l activm */
if (i<w.size())
w.elementAt(i).start();
if (i<r.size())
r.elementAt(i).start();
}}}
Rezultatul realizrii programului:
run:
1 Scriitor
2 Scriitor
3 Scriitor
4 Scriitor
32

5 Scriitor
6 Scriitor
7 Scriitor
8 Scriitor
9 Scriitor
1 Cititor
2 Cititor
E scris obiectul 1 de scriitorul 1
Obiecte scrise 1
E scris obiectul 2 de scriitorul 2
Obiecte scrise 2
E scris obiectul 3 de scriitorul 3
Obiecte scrise 3
A fost citit obiectul 1 de cititorul 2
E scris obiectul 4 de scriitorul 5
Obiecte scrise 4
E scris obiectul 5 de scriitorul 4
Obiecte scrise 5
E scris obiectul 6 de scriitorul 9
Obiecte scrise 6
E scris obiectul 7 de scriitorul 6
Obiecte scrise 7
E scris obiectul 8 de scriitorul 8
Obiecte scrise 8
A fost citit obiectul 1 de cititorul 1
E scris obiectul 9 de scriitorul 7
Obiecte scrise 9
A fost citit obiectul 2 de cititorul 2
A fost citit obiectul 2 de cititorul 1
E scris obiectul 10 de scriitorul 2
Obiecte scrise 10
A fost citit obiectul 3 de cititorul 2
E scris obiectul 11 de scriitorul 5
Obiecte scrise 11
E scris obiectul 12 de scriitorul 1
33

Obiecte scrise 12
E scris obiectul 13 de scriitorul 3
Obiecte scrise 13
E scris obiectul 14 de scriitorul 6
A fost citit obiectul 3 de cititorul 1
Obiecte scrise 14
-----Obiectele toate snt scrise----A fost citit obiectul 4 de cititorul 2
A fost citit obiectul 4 de cititorul 1
A fost citit obiectul 5 de cititorul 2
A fost citit obiectul 5 de cititorul 1
A fost citit obiectul 6 de cititorul 2
A fost citit obiectul 6 de cititorul 1
A fost citit obiectul 7 de cititorul 2
A fost citit obiectul 7 de cititorul 1
A fost citit obiectul 8 de cititorul 2
A fost citit obiectul 8 de cititorul 1
A fost citit obiectul 9 de cititorul 2
A fost citit obiectul 9 de cititorul 1
A fost citit obiectul 10 de cititorul 2
A fost citit obiectul 10 de cititorul 1
A fost citit obiectul 11 de cititorul 2
A fost citit obiectul 11 de cititorul 1
A fost citit obiectul 12 de cititorul 2
A fost citit obiectul 12 de cititorul 1
A fost citit obiectul 13 de cititorul 2
A fost citit obiectul 13 de cititorul 1
A fost citit obiectul 14 de cititorul 2
Obiecte necitite 0
-----Toate obiectele scrise au fost citite----BUILD SUCCESSFUL (total time: 7 seconds)
5. Probleme propuse:
Scriei un program pentru X (unde X este egal cu numrul
variantei plus numrul subgrupei) scriitori i Y (unde Y este egal
34

cu numrul variantei nmulit cu 2 plus numrul subgrupei) cititori,


fiecare scriitor scrie cte Z (unde Z este egal cu numrul variantei
plus 3) obiecte.
3. Problema clasic Algoritmul Bancher
Un algoritm clasic de evaluare a interblocrii, bazat pe
noiunea de secven sigur, este algoritmul bancherului. Se
numete astfel, deoarece poate fi folosit n sistemul bancar pentru
plata unor sume diferitor clieni ai bncii, sum care trebuie s fie
mereu n stare sigur. Pentru a putea aplica acest algoritm, trebuie
s se cunoasc la nceput numrul maxim de resurse cerute de
fiecare proces.
La fiecare cerere a unor resurse noi se aplic
algoritmul pentru a observa dac aceast cerere duce la o stare
sigur sau nesigur. Dac e sigur, cererea este acceptat, dac nu e
sigur, cererea nu este acceptat i procesul rmne n ateptare.
3.1. Algoritmul bancherului pentru un tip de resurse
Algoritmul de planificare, care permite
evitarea
interblocrii, este numit algoritmul Bancher. Acesta reprezint o
extindere a algoritmului pentru detectarea blocrii. Modelul
algoritmului este bazat pe exemplul de bancher ntr-un ora mic,
care are de afacere cu un grup de clieni crora le-a eliberat o serie
de mprumuturi. Algoritmul controleaz dac realizarea fiecrei
interogri duce la situaia de nesiguran. Dac da, atunci cererea
este respins. n cazul n care cererea unei resurse aduce la stare de
siguran, resursa este disponibil pentru proces.
Pentru a crea o analogie cu sistemul informatic, obinem:
clienii snt procese, unitile snt resurse, iar bancher - un sistem
de operare.
Algoritmul Banker controleaz fiecare cerere i verific
dac aceasta poate fi realizat n condiii de siguran. Dac da,
atunci procesul i se elibereaz resursa cerut, altfel solicitarea fiind
amnat. Pentru a nelege dac starea e sigur, bancherul verific
35

dac acesta poate asigura resurse necesare pentru a finaliza lucrrile


clientului. Dac da, atunci aceste mprumuturi snt acceptate i
achitate, apoi se verific limita creditelor acordate clienilor. n
cazul n care, n final, toate mprumuturile pot fi acordate, starea se
numete de siguran i interogarea iniial poate fi satisfcut.

3.2. Algoritmul Banker pentru mai multe tipuri de


resurse
Algoritmul Bancher poate fi generalizat pentru a dirija
sistemul cu mai multe tipuri de resurse.
Resurse distribuite snt resursele necesare pe parcursul
realizrii . Algoritmul Banker ntr-un sistem cu mai multe tipuri de
resurse este reprezentat n forma a dou matrice. Matricea C arat
cte resurse de fiecare tip ocup n prezent fiecare proces. Matricea
R arat tipurile resurselor care trebuie s fie adugate pentru fiecare
proces ca s finalizeze cu succes. Ca i n cazul unui singur tip de
resurse, procesele au necesitatea de a determina cu exactitate
totalitatea resurselor necesare pn la nceputul lucrului, pentru a
calcula matricea n orice moment.
Resursele existente snt indicate de trei vectori (E vector),
resursele utilizate (vector P) i resursele disponibile (vector A).
Este necesar s se sumeze cele patru coloane ce corespund
resurselor n matricea C. Vectorul resurselor disponibile este
diferena dintre ceea ce exist n sistem i ceeia ce se utilizeaz n
prezent.
Acum poate fi descris un algoritm pentru a verifica starea de
securitate a sistemului.
1. Se caut n matricea R rndul corespunztor unui proces
a crui necesitate de resurse este mai mic sau egal cu vectorul A.
n cazul n care un astfel de rnd nu exist, sistemul ajunge n stare
de blocare, deoarece nici un proces nu poate lucra pn la sfrit cu
succes.
36

2. Se presupune c procesul linia cruia a fost aleas n


punctul 1, cere toate resursele necesare (acest lucru este posibil) i
finalizarea cu succes. Menionm c dup finalizarea procesului,
adugm toate resursele eliberate vectorului A.
3. S se repete paii 1 i 2 pn cnd toate procesele vor fi
marcate ca finalizate, iar starea n acest caz este sigur sau va avea
loc interblocarea - atunci starea este nesigur.
n cazul n care la primul pas se pot selecta mai multe
procese, nu conteaz care dintre ele va fi luat: numrul total de
resurse disponibile sau va crete, sau va rmne neschimbat.
Dei algoritmul este efectiv n teorie, n practic este inutil,
deoarece rareori e posibil s se stabileasc n avans numrul de
resurse care vor fi necesare proceselor viitoare. n plus, numrul de
procese nu este fix, i se schimb dinamic n dependen de numrul
de utilizatori ai sistemului, iar resursele care ar putea fi
disponibile, pot disprea brusc. Astfel, n practic puine sisteme
folosesc algoritmul Bancher pentru a evita interblocarea.
Algoritmul de prevenire poate fi mbuntit dac exist
informaii anticipate despre cererile de resurse. Dac fiecare proces
prezint n avans o declaraie de intenii (anun), adic valoarea unei
borne superioare a cererilor sale pentru numrul de resurse de
fiecare tip, algoritmul Bancher permite evitarea blocrii, reevalund
riscul acestora la fiecare alocare. Acest algoritm se bazeaz pe
noiunea de stare fiabil: o stare de alocare este numit fiabil dac,
pornind de la aceast stare, este posibil s se asigure funcionarea
sistemului fr blocri n care fiecare proces cere efectiv cantitatea
maxim presupus de fiecare dintre resurse. Algoritmul Bancher va
aloca o resurs doar dac aceast alocare pstreaz starea fiabil a
sistemului.
Considerm un sistem care conine n procese i m clase de
resurse. Starea acestuia este reprezentat de urmtoarele structuri de
date:
Res, Disp: array[0..m-1] of integer
37

Anunt, Aloc: array[0..n-1, 0..m-1] of integer


Unde:
Res[j]- este numrul total de resurse din clasa j,
Anunt[i, j] - numrul maxim de resurse din clasa j necesare
la un moment de timp procesului i,
Aloc[i, j] - numrul maxim de resurse din clasa j alocate la
un moment de timp procesului i,
Disp[j] - numrul de resurse din clasa j disponibile la un
moment de timp dat.
Avem, prin definiie, pentru un moment oarecare de timp:
Disp[j]=Res[j]- INCLUDEPICTURE "http://ti.webfaq.com/ti/ACSO Part 2/info/31.files/image001.png" \*
MERGEFORMATINET INCLUDEPICTURE "http://ti.webfaq.com/ti/ACSO Part 2/info/31.files/image001.png" \*
MERGEFORMATINET

pentru j=0, 1,..., m-1.

Notm prin A[i,*] vectorul format din linia i a matricei A.


Dac U i V snt doi vectori de aceeai lungime k, vom conveni s
scriem:
UV dac i numai dac U[i] V[i] pentru i=0, 1,..., k-1
U<V dac i numai dac U V i UV.
Specificaiile sistemului impun urmtoarele restricii:
0 Aloc[i,*] Anunt[i,*] Res,
38

pentru i=0,...,n-1

Aloc[i,*] Res
Disp 0

vectorul nul.

Aceste relaii denat, pentru fiecare clas de resurse, c anunul


nu poate depi numrul resurselor disponibile, iar cantitatea
resurselor alocate unui proces nu poate depi anunul su i, n
sfrit, c sistemul nu poate elibera mai multe resurse dect exist n
total. O stare a sistemului se numete realizabil, dac este
conform acestor specificaii.
Fie E0 o stare realizabil a sistemului. ncercm s gsim un
proces pi, care, dac dac ar fi fost executat singur, pornind de la
starea E0, utiliznd totalitatea resurselor specificate de anunul su,
procesul ar putea ajunge pn la sfrit. Un asemenea proces trebuie
s fie n starea E0:
Anunt[i, *]-Aloc[i, *] Disp.
Presupunem c a fost gsit un astfel de proces, fie pi0, i c acesta
este executat pn la sfrit. Atunci se elibereaz toate resursele i
sistemul trece ntr-o stare realizabil E1, definit prin:
DispE1=DispE0+Aloc[i0,*].
Operaia poate fi repetat, cutnd un proces nou pi1 i aa mai
departe pe ct este posibil. Aceste procese, se numesc fiabil. O
stare a sistemului se numete fiabil, dac, pornind din aceast
stare, putem construi o suit fiabil complet (adic, care conine
toate procesele sistemului).
Conform acestei definiii, un sistem ntr-o stare fiabil nu este n
blocare, deoarece poate fi definit drept ordonare a proceselor care
permite execuia tuturor proceselor. Putem demonstra afirmaia
reciproc (exerciiu): dac un proces nu este n blocare, el se afl n
39

stare fiabil. Algoritmul Bancher se bazeaz pe aceast proprietate,


fiind executat la fiecare cerere de resurs de un proces. Fie
Cerere[i, j] numrul de resurse cerute din clasa j n starea curent a
sistemului de ctre procesul i.
if Aloc[i,j]+Cerere[i,j]>Anunt[i,j]
then <eroare>-- cererea total > anunul
else
if Cerere[i,j]>Disp[j]
then <pune procesul p n ateptare>
else -- simularea alocrii
<definire stare nou prin:
Aloc[i,j]:=Aloc[i,j]+Cerere[i,j]
Disp[j]:=Disp[j]-Cerere[i,j]>
endif;
if starea nou este fiabil
then <efectuare alocare>
else <restaurare stare primitiv>
<pune procesul p n ateptare> endif endif
Principalul n acest
Algoritm este testarea fiabilitii unei stri, care se reduce la
ncercarea construirii unei suite fiabile. Este vorba de un algoritm
combinat, care presupune iniial o complexitate de ordinul n!, ns
complexitatea poate fi redus la n2 datorit urmtoarei proprieti,
care exclude necesitatea rentoarcerii n caz de eec: dintr-o stare
fiabil orice suit fiabil poate fi prelungit pn la o suit fiabil
complet.
Cu alte cuvinte, dac tentativa de extindere a unei suite fiabile
pariale eueaz, starea sistemului nu este fiabil i fiind inutil s
se ncerce construirea unei alte suite.

40

innd cont de aceast proprietate, fiabilitatea este testat


realizat cu ajutorul algoritmului de mai jos.
Dispcurente:array[0..m-1] of integer;
Rest:set
of
procese;
Dispcurente:=Disponibil;
Rest:={toate procesele};
posibil:=true;
while posibil do
cutare p din Rest astfel ca
Anunt[i,*]-Aloc[i,*]Dispcurente;
if gsit
then simularea execuiei procesului p
Dispcurente:=Dispcurente+Aloc[i,*];
Rest:=Rest-{p}
Else posibil:=false endif endwhile;
stare fiabil:=(Rest=<vid>)
3.3. Lucrarea de laborator nr. 3
1. Tema lucrrii: Problema Algoritmului Bancher
2. Scopul lucrrii:
41

nsuirea modalitilor de sincronizare a algoritmului


Bancher;
efectuarea sincronizrii firelor de execuie pentru
algoritmul Bancher;
3. Etapele de realizare:
sincronizarea
firelor de execuie pentru algoritmul
Bancher;
realizarea metodelor de sincronizare a firelor de execuie
pentru algoritmul Bancher;
crearea interfeii programului;
prezentarea lucrrii.
4. Exemplu de efectuare:
public class sola_nr3
{
static int n=5, k=4;
static Integer c[][]=new Integer[n]
[k]; //starea curent
static Integer r[][]=new Integer[n]
[k]; //resursele necesare
static Integer e[]=new Integer[k];
//resursele existente
static Integer p[]=new Integer[k];
//resursele utilizare
static Integer a[]=new Integer[k];
//resursele disponibile
static Integer s[]=new Integer[n];
//starea rndurilor din 'r'

42

/* Iniializarea vectorului strii


rndurilor rnduri stabile i nestabile n
'r'*/
static void defineS()
{
/* inializarea vectorului strii
prin 0 */
for (int i=0; i<n; i++)
s[i]=0;
}
/* inializarea vectorului cu resurse
ocupate 'p'*/
static void defineP()
{
/* inializarea vectorului p cu 0 */
for (int j=0; j<k; j++)
{
p[j]=0;
}
/*Determinm vectorul cu resurse
ocupate. Coninutul vectorului 'p' este suma
elementelor rndului corespunztor a matricii
cu resurse ocupate. */
for (int j=0; j<k; j++)
for (int i=0; i<n; i++)
p[j]+=c[i][j];
/* Exstragem P */
System.out.print("P=( ");
for (int j=0; j<k; j++)
System.out.print(p[j] + " ");
System.out.println(")");
}

43

/* Aprecierea valorilor vectorului cu


resurse disponibile */
static boolean defineA()
{
for (int j=0; j<k; j++)
{
a[j]=e[j]-p[j];
/* controlul vectorului cu resurse existente
i al matricei cu resurse ocupate */
if (a[j]<0)
{
System.out.println("Date
iniiale incorecte");
return false;
}
}
/* Exstragem A */
System.out.print("A=( ");
for (int j=0; j<k; j++)
System.out.print(a[j] + " ");
System.out.println(")");
return true;
}
public static void main(String[] args)
{
/* Iniializarea matricei cu starea
curent */
/**/
c[0][0]=3; c[0][1]=0;
c[0][2]=1; c[0][3]=1;
c[1][0]=0; c[1][1]=1;
c[1][2]=0; c[1][3]=0;
c[2][0]=1; c[2][1]=1;
44

c[2][2]=1; c[2][3]=0;
c[3][0]=1; c[3][1]=1;
c[3][2]=0; c[3][3]=1;
c[4][0]=0; c[4][1]=0;
c[4][2]=0; c[4][3]=0;
c[0][0]=1; c[0][1]=0;
c[0][2]=1; c[0][3]=1;
c[1][0]=0; c[1][1]=1;
c[1][2]=0; c[1][3]=0;
c[2][0]=1; c[2][1]=1;
c[2][2]=1; c[2][3]=0;
c[3][0]=1; c[3][1]=1;
c[3][2]=0; c[3][3]=1;
c[4][0]=0; c[4][1]=0;
c[4][2]=0; c[4][3]=0;
/**/
/*Extragem C */
System.out.println("C={");
for (int i=0; i<n; i++)
{
System.out.print("
");
for (int j=0; j<k; j++)
System.out.print(c[i][j] + "
");
System.out.println();
}
System.out.println(" }");
/*
necesare R
/*
r[0][0]=1;
r[0][2]=0;
r[1][0]=0;
r[1][2]=1;
r[2][0]=3;
r[2][2]=0;

Iniializarea matricei cu resurse


*/
r[0][1]=1;
r[0][3]=0;
r[1][1]=1;
r[1][3]=2;
r[2][1]=1;
r[2][3]=0;
45

r[3][0]=0; r[3][1]=0;
r[3][2]=1; r[3][3]=0;
r[4][0]=2; r[4][1]=1;
r[4][2]=1; r[4][3]=0;
r[0][0]=0; r[0][1]=1;
r[0][2]=0; r[0][3]=0;
r[1][0]=0; r[1][1]=0;
r[1][2]=1; r[1][3]=1;
r[2][0]=1; r[2][1]=1;
r[2][2]=0; r[2][3]=0;
r[3][0]=0; r[3][1]=3;
r[3][2]=0; r[3][3]=0;
//modificnd r[3][1] cu 4- va fi srare
//nestabil, cu 3 va fi stare stabil
r[4][0]=1; r[4][1]=0; r[4][2]=1; r[4][3]=0;
/*Extragem R */
System.out.println("R={ ");
for (int i=0; i<n; i++)
{
System.out.print("
");
for (int j=0; j<k; j++)
System.out.print(r[i][j] + " ");
System.out.println();
}
System.out.println(" }");
/* Iniializarea vectorului cu
resurse existente*/
// e[0]=6;
e[1]=3;
e[2]=4; e[3]=2;
e[0]=6;
e[1]=4;
e[2]=5; e[3]=4;
//Extragem E
System.out.print("E=( ");
for (int j=0; j<k; j++)
System.out.print(e[j] + " ");
System.out.println(")");
defineP();
defineS();
46

if (defineA()==true){
int quantityOfGoodStrings=0;
for (int i=0; i<n; i++){
if(s[i]!=1){
int g=0;
for(int j=0; j<k; j++)
if (r[i][j]<=a[j])
g++;
if (g==k)
{
System.out.println("
Rnd bun " + (i));
for(int j=0; j<k; j++){
a[j]+=r[i][j];
r[i][j]=0;
//Iniializarea rndurilor bune
s[i]=1;
quantityOfGoodStrings++;
i=0;
}}
if (quantityOfGoodStrings==n){
System.out.println("Stare
stabil");
return;
}
else{
if (i==(n-1)){
System.out.println("Stare nestabil");
return;
}}}}}}
Rezultatul realizrii programului:
C={
1011
0100
1110
1101
47

0000
}
R={
0100
0011
1100
0300
1010
}
E=( 6 4 5 4 )
P=( 3 3 2 2 )
A=( 3 1 3 2 )
Rnd bun 0
Rnd bun 1
Rnd bun 2
Rnd bun 3
Rnd bun 4
Stare stabil
C={
1011
0100
1110
1101
0000
}
R={
0100
0011
1100
0400
1010
}
E=( 6 4 5 4 )
P=( 3 3 2 2 )
A=( 3 1 3 2 )
48

Rnd bun 0
Rnd bun 1
Rnd bun 2
Rnd bun 4
Stare nestabil
5. Probleme propuse:
Scrie un program pentru algoritmul Bancher pentru X procese
(numrul variantei plus numrul subgrupei) i Y resurse (numarul
variantei plus numrul subgrupei plus trei) cu specificarea timpului
de utilizare.
4. Problema Cina filozofilor.
Problema Cina filozofilor (The Dining philosophers
problem) modeleaz procese care concureaz pentru accesul
exclusiv la un numr limitat de resurse, cum ar fi dispozitivele I/O.
Problema poate fi formulat astfel.
Cinci filozofi chinezi i petrec viaa gndind i mncnd n
jurul unei mese rotunde nconjurat de cinci scaune, fiecare filozof
ocupnd un scaun (fig. 4.1). n centrul mesei este un platou cu orez
i n dreptul fiecrui filozof se afl o farfurie. n stnga i n dreapta
farfuriei cte un beior. Deci, n total, cinci farfurii i cinci
beioare. Un filozof poate efectua dou operaii: gndete sau
mnnc. Pentru a putea mnca, un filozof are nevoie de dou
beioare, unul din dreapta i unul din stnga. Dar acesta poate
ridica un singur beior odat. Problema cere o soluie pentru
aceast cin.
2
1
3
5
49

Fig. 4.1. Ilustrarea problemei celor 5 filozofi.


Trebuie rezolvate dou probleme importante cum ar fi:
interblocarea care poate s apar. De exemplu, dac fiecare
filozof ridic beiorul din dreapta sa, nimeni nu mai poate s-l
ridice i pe cel din stnga i apare o situaie clar de ateptare
circular, deci de interblocare.
problema nfometrii unui filozof care nu poate ridica
niciodat cele dou beioare.
Aceast problem a fost enunat i rezolvat de ctre
Deikstra n 1965. Exist mai multe soluii ale acestei probleme,
majoritatea utiliznd excluderea mutual.
4.1. Sincronizarea problemei cinei filosofilor

Pentru a nu aprea interblocarea, se folosesc, n general,


soluii de prevenire a acesteia, adic se impun unele restricii n ceea
ce privete aciunile filozofilor, cum ar fi:
unui filozof i se permite s ia un beior numai atunci cnd
ambele beioare, din dreapta i din stnga sa, snt disponibile;
se creeaz o coresponden biunivoc ntre mulimea
numerelor naturale i filozofi, fiecare filozof avnd un numr
natural; o soluie asimetric impune filozofilor cu numr impar s ia
mai nti beiorul din stnga, apoi pe cel din dreapta, iar filozofilor
cu numr par s ia mai nti beiorul din dreapta i apoi pe cel din
stnga.
Vom expune n continuare, o soluie clasic a acestei
probleme, care rezolv i situaia interblocrii, i a nfometrii. n
acest algoritm se poate generaliza problema pentru n filozofi. Se
50

urmrete n ce stare poate fi un filozof, existnd trei stri posibile:


mnnc, gndete i este nfometat.
Unui filozof i se permite s intre n starea mnnc numai
dac cel puin unul din vecinii si nu este n aceast stare. Prin
aceast restricie se previne interblocarea.
Pentru implementare, se utilizeaz urmtoarele structuri:

stare[n] un vector n-dimensional n care pe


poziia i se gsete starea filozofului la un moment dat;
aceasta poate fi:
o
pentru starea gndete
o
pentru starea nfometat
o
pentru starea mnnc

sem[n] un vector n-dimensional n care


sem[i] este un semafor pentru filozoful i;

mutexfil un mutex pentru excludere


mutual;

funciafilozof(i) este funcia principal care


coordoneaz toate celelalte funcii i care se refer la
filozoful i;

funcia ridic beior(i) este funcia care


asigur pentru filozoful i ridicarea ambelor beioare;

funcia pune beior i este funcia care


asigur pentru fiecare filozof i punerea ambelor beioare
pe mas;

funcia test(i) este funcia care testeaz n ce


stare este filozoful i.
Implementarea este:
Int

n = 5

int stang =
1)%n
int

i+n-

drept = (i+1)%n

/*am definit numrul


de filozofi*/
/*numrul vecinului
din stnga
filozofului i*/
/*numrul vecinului
51

din stnga
filozofului i*/
int gandeste = 0
Infometat = 1
Mananca= 2
int semafor;
int mutex;
int stare[n];
mutex mutexfil=1
semafor sem[n];
void filozof(int i)
while(i) {
gandeste();
ridicabetisor(i);
mananca();
punebetisor(i);
void
ridicabetisor(int i)
{wait(mutexfil);
stare[i]=infometat;
test(i);
signal(mutexfil);
wait(sem[i]);}

/*filozoful i
gndete*/
/*filozoful i ridic
cele dou beioare*/
/*filozoful i
mnnc*/
/*filozoful i pune pe
mas dou beioare*/

/*se intr n
regiunea critic*/
/*filozoful i este n
starea nfometat*/
/*ncearc s
acapareze cele dou
beioare*/
/*se iese din
regiunea critic*/
/*procesul se
blocheaz dac nu se
52

pot lua cele dou


beioare*/
void punebetisor(int
i)
{wait(mutexfil);
stare [i]=gandeste;
test(stang);

test(drept);

signal(mutexfil);

/*se intr n
regiunea critic*/
/*filozoful i a
terminat de gndit*/
/*se testeaz dac
vecinul din stnga
filozofului i
mnnc*/
/*se testeaz dac
vecinul din
dreaptafilozofului i
mnnc*/
/*se iese din
regiunea critic*/

}
void test(int i);
{if stare [i]==
infometat&&stare[sta
ng]!=
mananca&&stare[drept
]!=
mananca)
{stare[i]=mananca;
signal(sem[i]);}}
Programul mai folosete un tablou de semafoare, cte unul
pentru fiecare filozof, folosit pentru a bloca filozoful dac nu poate
obine furculiele de care are nevoie.
4.1. Lucrare de laborator nr. 4
1. Tema lucrrii: Problema Cina filozofilor
53

2. Scopul lucrrii:
nsuirea modalitilor de sincronizare pentru algoritmului
Cina filozofilor;
realizarea sincronizrii firelor de execuie pentru algoritmul
Cina filozofilor;
3. Etapele de efectuare:
sincronizarea firelor de execuie pentru algoritmul Cina
filozofilor;
realizarea metodelor de sincronizare a firelor de execuie
pentru algoritmul cina filosofilor;
crearea interfeii programului;
prezentarea lucrrii.
4. Exemplu de efectuare:
import java.util.concurrent.locks.*;
import java.util.logging.Level;
import java.util.logging.Logger;
class Philosopher extends Thread {
public Philosopher(Forks forks) {
this.forks = forks;
this.currentState = state.Hungry;
this.name = currentName++;
System.out.println("Philosopher
#"+name+" has riched the table!");
}
@Override
public void run() {
while (true) {
switch (currentState) {
case Hungry:
54

if (wasHungry == false) {
System.out.println("Philosopher #"+name+" is
hungry");
}
wasHungry = true;
if (forks.takeForks(name) == true) {
this.currentState = state.Eating;
}
break;
case Eating:
System.out.println("Philosopher #"+name+" is
eating");
try {
Thread.sleep( (int)(Math.random()*1000)
);
}
catch (InterruptedException ex) {
Logger.getLogger(Philosopher.class.getName())
.log(Level.SEVERE, null, ex);
}
forks.leaveForks(name);
this.currentState = state.Thinking;
wasHungry = false;
break;
case Thinking:
System.out.println("Philosopher #"+name+" is
thinking");
try {
Thread.sleep( (int)
(Math.random()*2000) );
}
catch (InterruptedException ex) {
Logger.getLogger(Philosopher.class.getName())
.log(Level.SEVERE, null, ex);
55

}
this.currentState = state.Hungry;
wasHungry = false;
break;
}}}
private int name;
private state currentState;
private enum state {Hungry, Eating,
Thinking};
private Forks forks;
private boolean wasHungry = false;
private static int currentName = 0;
}
class Forks {
public Forks(int number) {
this.number = number;
this.forks = new state[number];
for (int i = 0; i < number; i++) {
forks[i] = state.Free;
}
System.out.println("Forks are
created!");
printState();
}
public boolean takeForks (int position) {
boolean success = false;
lock.lock();
state leftState;
state rightState;
if (position == 0) {
leftState = forks[number-1];
}
else {
leftState = forks[position-1];
}
56

rightState = forks[position];
if (leftState == state.Free && rightState
== state.Free) {
if (position == 0) {
forks[number-1] = state.inUse;
}
else {
forks[position-1] = state.inUse;
}
forks[position] = state.inUse;
System.out.println("Philosopher
#"+position+" has taken the forks.");
printState();
success = true;
}
lock.unlock();
return success;
}
public void leaveForks (int position) {
lock.lock();
state leftState;
state rightState;
if (position == 0) {
forks[number-1] = state.Free;
}
else {
forks[position-1] = state.Free;
}
forks[position] = state.Free;
System.out.println("Philosopher
#"+position+" has left the forks.");
printState();
lock.unlock();
}
private void printState() {
57

System.out.print("Current state: ");


for (int i = 0; i<number; i++){
System.out.print(i+":"+forks[i]+" ");
}
System.out.println();
}
private int number;
private state forks[];
private enum state { Free, inUse
};
private Lock lock = new
ReentrantLock();
}
public class Main {
public static void main(String[]
args) {
int number = 5;
Forks forks = new Forks(number);
Philosopher[] philosophers = new
Philosopher[number];
for (int i = 0; i<number; i++){
philosophers[i] = new
Philosopher(forks);
}
for (int i = 0; i<number; i++){
philosophers[i].start();
}}}
5. Probleme propuse
Scriei un program care soluioneaz problema Cina filozofilor
pentru n filosofi, unde n este varianta plus patru. Elaborai i
efectuai condiia de finalizare a programului.

58

PARTEA 2
1. Mediul de programare Turbo - Assembler
1.1. Descrierea pachetului de programe Turbo - Assembler
Pachetul de programe Turbo - Assembler pune la dispoziia
utilizatorului toate instrumentele necesare pentru dezvoltarea
programelor n limbaj de asamblare.
Pachetul cuprinde:
1) macroasamblorul TASM;
2) editorul de legturi TLINK;
3) bibliotecarul TLIB;
4) depanatorul simbolic TD.
1.2. Alegerea tipului de fiier executabil
Snt posibile urmtoarele formate de fiiere executabile:
.EXE - este formatul uzual pentru fiiere executabile. Programele
executabile pstrate n acest format pot avea segmente multiple. Este
formatul recomandat pentru programe de dimensiuni mari. Extensia
lor implicit este .EXE;

59

.COM - programele n acest format snt limitate pentru un singur


segment, din acest motiv, nu depesc 64Ko (exceptnd cazurile cnd
nu se specific segmente). Se recomand pentru programe mici.
1.3. Dezvoltarea programelor n limbaj de asamblare
Procesul general de lucru este urmtorul:
1. Se folosete un editor de texte pentru crearea sau
modificarea modulelor surs. Prin convenie acestea au extensia
implicit .ASM.
2. Se utilizeaz programul TASM pentru asamblarea fiecrui
modul de program. Ca rezultat al asamblrii, pentru fiecare fiier surs
.ASM se creeaz:
a) un fiier obiect cu extensia implicit .OBJ;
b) un fiier listing cu extensia implicit .LST (optional);
c) un fiier de referine ncruciate cu extensia implicit .REF
(opional).
3. Opional se folosete TLIB pentru plasarea mai multor fiiere
obiect ntr-un singur fiier bibliotec cu extensia implicit .LIB. Acest
lucru se ntmpl cnd se dorete legarea unor fiiere obiect standard la
mai multe programe.
4. Se folosete TLINK pentru a combina toate fiierele obiect i
modulele bibliotec ce formeaz un program n cadrul unui singur
fiier executabil care are implicit extensia .EXE.
5. Se poate efectua editarea legturilor cu opiunea /l pentru crearea
(dac este necesar) unui fiier executabil n format binar. Aceast
operaie este necesar pentru programele scrise n format COM (care
vor avea extensia .COM) sau pentru fiierele binare.
6. Se depaneaz programul pentru depistarea erorilor de logic.
Dintre tehnicile utilizate se amintesc:
a) analiza rspunsului programului la diferite seturi de date de
intrare;
b) studiul fiierelor surs i listing;
c) utilizarea fiierului listing cu referine ncruciate;
d) utilizarea depanatorului simbolic TD pentru depanare dinamic.
60

Exemplu de program n format EXE


.MODEL
SMALL
.STACK
100h
.DATA
mesaj
DB
"Salut!",13,10
lmesaj
EQU $-mesaj
.CODE
start:
mov ax,@data
mov ds,ax
mov bx,1
mov cx,lmesaj
mov dx,OFFSET mesaj
mov ah,40h
int 21h
mov ax,4C00h
int 21h
END start
Se remarc urmatoarele:
1. Directiva .MODEL este folosit pentru iniializarea modelului
de memorie.
2. Directiva .STACK definete o stiv de 256 octei, suficient
pentru programe mici.
3. Directiva .DATA marcheaz nceputul segmentului de date.
4. Eticheta primei instruciuni ce urmeaz dup directiva .CODE
marcheaz nceputul poriunii executabile a programului. Aceeai
etichet este utilizat dup directiva END, ea definind astfel punctul
de unde va ncepe execuia programului (numit i punctul de intrare
n program).
5. Primele dou instruciuni iniializeaz registrul ds. Simbolul
@data reprezint numele segmentului creat cu directiva .DATA.
Registrul ds va fi ntotdeauna iniializat pentru fiiere surs n format
EXE.
6. Coninutul variabilei de tip ir de caractere definit n program
se afieaz pe ecran, utiliznd funcia DOS cu codul 40h. Fiierul
61

"handle" 1 (driver predefinit pentru ieirea standard) este specificat


pentru afiarea pe ecran. irurile pot fi de asemenea afiate pe ecran
cu funcia DOS cu codul 09h;
7. Funcia DOS cu codul 4Ch este utilizat pentru finalizarea
programului i ieirea n sistem. Exist i alte tehnici de ieire n
sistem, dar aceasta este cea mai recomandat.
Exemplu de program n format COM
.MODEL TINY
.CODE
ORG 100h
start:
jmp inceput
mesaj
DB
"Salut!",13,10
lmesaj
EQU $-mesaj
inceput: mov bx,1
mov cx,lmesaj
mov dx,OFFSET mesaj
mov ah,40h
int 21h
mov ax,4C00h
int 21h
END start

Programele cu extensiunea COM difer de cele EXE prin


urmtoarele:
1. Directiva .MODEL nu poate fi folosit la definirea segmentelor
implicite pentru fiiere COM.
2. Toate registrele segment snt asignate unuia i acelui segment.
3. Directiva ORG se utilizeaz pentru a indica pornirea asamblrii
de la octetul 256 (100h). Astfel se creeaz spaiu pentru prefixul
segmentului de program (PSP) care este automat ncrcat n memorie
n momentul execuiei;
4. Dei datele programului trebuie incluse n segmentul unic ele nu
vor fi executate. Se poate "sri" peste ele cu o instruciune jmp (ca n
exemplul precedent) sau se pot plasa datele la sfirit, dup punctul n
care programul revine n sistem.

62

1.4. Comenzi necesare pentru dezvoltarea unui program


Pentru aflarea informaiei despre comenzile TASM i TLINK se
lanseaz n execuie aceste programe fr nici un parametru n linia de
comand. Efectul execuiei const n afiarea sintaxei liniei de
comand mpreun cu opiunile disponibile.
Comenzile uzuale snt:
- pentru asamblarea unui program:
TASM nume - unde nume este numele fiierului ce conine programul
surs, implicit cu extensia .ASM.
- pentru asamblarea unui program cu obinerea fiierului listing:
TASM /l nume - unde nume este numele fiierului ce conine
programul surs, implicit cu extensia .ASM.
- pentru asamblarea unui program cu depunerea de informaii
simbolice n fiierul obiect rezultat necesare depanatorului simbolic
TD:
TASM /zi nume - unde nume este numele fiierului ce conine
programul surs, implicit cu extensia .ASM.
- pentru editarea legturilor unui program:
TLINK nume - unde nume este numele fiierului obiect rezultat n
urma asamblrii, implicit cu extensia .OBJ. Totodat se genereaz i
harta de alocare a memoriei.
- pentru editarea legturilor unui program cu depunerea de
informaii simbolice n fiierul executabil rezultat necesare
depanatorului simbolic TD:
TLINK /v nume unde nume este numele fiierului obiect rezultat n
urma asamblrii cu opiunea /zi, implicit cu extensia .OBJ. Implicit se
genereaz i harta de alocare a memoriei.

63

- pentru editarea legaturilor unui program n vederea obinerii unui


fiier executabil n format COM:
TLINK /t nume unde nume este numele fiierului obiect rezultat n
urma asamblrii unui program surs n format COM; implicit are
extensia .OBJ.
- pentru depanarea programului executabil obinut:
TD nume unde nume este numele fiierului executabil rezultat n
urma editrii legturilor, implicit cu extensia .EXE sau .COM.
Depanarea cu TD poate fi obinuit sau simbolic. Depanarea
obinuit presupune ca n momentul depanrii s se cunoasc adresele
variabilelor din program mpreun cu segmentele n care se afl aceste
variabile. Depanarea simbolic presupune c n momentul execuiei
programul depanator are acces la numele simbolice ale variabilelor
din program, depanarea fiind n acest caz realizat mai uor.
2. Programe liniare i programe cu ramificri
2.1 Programe liniare
Instruciunile de transfer permit copierea unui octet sau cuvnt
de la surs la destinaie. Destinaia poate fi un registru, locaie de
memorie sau un port de ieire, iar sursa poate fi un registru, o
locaie de memorie, constante sau port de intrare. De regul,
destinaia i sursa nu pot fi ambele locaii de memorie. n
specificarea sursei i destinaiei se vor folosi notaiile:
- segment: offset pentru adrese fizice;
- (x) paranteze rotunde pentru a desemna coninutul lui x.
Instruciunile aritmetice snt: adunarea, scderea, nmulirea,
mprirea numerelor binare cu i fr semn, precum i a numerelor
zecimale n form compact i necompact.
Microprocesorul i80X86 salveaz numerele n memorie nu n
ordine natural, ci invers: biii inferiori snt memorai n octei cu
adres mic, iar biii superiori - n octei cu adres mai mare.
Microprocesorul ntotdeauna prelucreaz toate numerele uniform i

64

le interpreteaz ca numere binare. Este evident c dac numarul e


zecimal, rezultatul va fi incorect.
De aceea, pentru compensarea acestei erori exist instruciuni
speciale de corectare a rezultatului.
Majoritatea instruciunilor aritmetice conin doi operanzi i
trebuie s reinem c rezultatul operaiei va fi memorat n locaia
primului operand.
Exemple rezolvate i comenttate
Exemplul 1.
n acest exemplu snt prezentate cteva tehnici de adresare specifice
procesoarelor din familia i80x86
TITLE exemplul_1
.MODEL SMALL
.STACK 10h
.DATA
alfa
DW
3 DUP(?)
CODE
begin: mov
ax,@DATA
mov
ds,ax
mov
ax,17
; Adresare imediat a operandului surs care este o
;constanta zecimal;
mov
ax,10001b
; Sursa este o constant binar
mov
ax,11h
; Sursa este o constant hexa
mov
alfa,ax
; Adresare direct a operandului destinaie
mov
cx,ax
mov
si,2
mov
alfa[si],ax
; Adresare relativ cu registrul
; i a operandului destinaie
mov
si,2
mov
bx,OFFSET alfa
; Adresare imediata a operandului
; surs (adresa variabilei alfa)
; datorit operatorului OFFSET

65

lea
bx,alfa
; Aceast instruciune are acelai
; efect cu cea anterioara cu toate
; c sursa este adresat direct
mov
cx,[bx][si]
; Adresare bazat indexat a sursei
mov
cx,alfa+2
; Aceast instruciune are acelai
; efect cu cea anterioar, sursa
; fiind ns adresat direct
mov
cx,alfa[2]
; Notaii echivalente pentru
mov
cx,[alfa+2]
; instruciunea anterioar
mov
di,4
mov
[bx][di],55h
; Se va semnala eroare deoarece nu
; s-a precizat tipul destinaiei
; care este o variabil anonim
mov
BYTE PTR [bx][di],55h
; Se va folosi aceast
; variant cnd se dorete o
; adresare la nivel de octet
mov
BYTE PTR alfa+4,55h
; Aceast instruciune are
; acelai efect cu cea anterioar,
; destinaia fiind ns adresat
; direct. Dei alfa este definit cu
; DW, operaia este realizat la
; nivel de octet
mov
si,2
mov
alfa[bx][si],33h
; Adresare bazat indexat
; relativ a operandului destinaie
mov
alfa[bx+si],33h
; Notaii echivalente pentru
mov
[alpha+bx+si],33h
; instructiunea anterioar
mov
[bx][si].alfa,33h
mov
[bx][si]+alfa,33h
END
begin

66

Pentru exemplificri s-a folosit instruciunea mov n diferite


variante de adresare: registru la registru, din memorie n registru i din
registru n memorie.
Exemplul 2.
S se adune dou numere folosind diferite moduri de adresare.
data segment
a
dw
75h
; primul operand
b
dw
?
; al doilea operand
c
dw
?
; rezultatul
data ends
cod segment
assume cs:cod,ds:data
start:
mov ax,data
mov ds,ax
; ncarc ds adresa de segment de date dat
mov b,0a3bh
; transfer la adresa b valoarea 0a3bh
; operandul surs este adresat imediat
; operandul destinaie este adresat direct
;la memorie
mov bx,offset a
; ncarc in bx adresa variabilei a
; operandul destinaie este adresat direct la
;registru
mov ax,[bx]
; ncarc n ax coninurul adresei aflate in bx,
;adic valoarea variabilei a
; operandul surs adresat indirect
add ax, b
; adun la ax valoarea variabilei b
mov di, offset c
; ncarc n di adresa lui c
mov [di], ax
; transfer la dresa lui di, adic n c coninutul
; lui ax
mov ax,4c00h
; ncarc in 0h valoarea 4c, functia...
int 21h
; ntrerupere

67

cod ends
end start

2.2. Programe cu ramificri i bucle


2.2.1. Instruciunea de salt necondiionat JMP
Forma general:
JMP operand
unde operand este adresa de salt necondiionat. Exist urmtoarele
tipuri de instruciuni JMP:
de tip SHORT B cnd operandul specific o adres n
domeniul B 128, 127 fa de (IP) actualizat
de tip NEAR - operandul specific o adres din acelai
segment de cod;
de tip FAR - operandul specific o adres din alt segment de
cod.
2.2.2. Instruciuni de salt condiionat
Aceste instruciuni se refer la salturile condiionate de indicatorii
de condiie.
Forma general:
Jcond operand
unde:
- cond este condiia de salt reprezentat de unul, dou sau trei
caractere(vezi tabelul de mai jos);
- operand este un offset cuprins ntre -128 i 128.
Dac condiia se ndeplinete, are loc saltul la adresa
indicat de operand, dac nu se continua n secvena modulului dat.
Se observ c exist dou categorii de instruciuni pentru
relaiile mai mic i mai mare, cele care conin cuvintele above
sau bellow i cele care conin cuvintele less sau greater.
Primele se folosesc n situaia comparrii a dou valori fr semn,
iar ultimele n situaia comparrii a dou valori cu semn.

68

Instruciune
(mnemonica)
JE, JZ
JL, JNGE
JLE,JNG
JB, JNAE, JC

Condiie de salt

nterpretare

ZF = 1
SF OF
SF OF sau ZF = 1
CF = 1

JBE, JNA
JP, JPE
JO
JS
JNE, JNZ
JNL, JGE
JNLE, JG
JNB, JAE,
JNC
JNBE, JA
JNP, JPO
JNO
JNS
JCXZ

CF = 1 sau ZF = 1
PF = 1
OF = 1
SF = 1
ZF = 0
SF = OF
SF = OF si ZF = 0
CF = 0

Zero, Equal
Less, Not Greater or Equal
Less or Equal, Not Greater
Below, Not Above or Equal,
Carry
Below or Equal, Not Above
Parity, Parity Even
Overflow
Sign
Not Zero, Not Equal
Not Less, Greater or Equal
Not Less or Equal, Greater
Not Below, Above or Equal,
Not Carry
Not Below or Equal, Above
Not Parity, Parity Odd
Not Overflow
Not Sign
JUMP if CX is Zero

CF = 0 si ZF = 0
PF = 0
OF = 0
SF = 0
CX=0

2.2.3. Instruciuni de ciclare


Instruciunea LOOP
Forma general:
LOOP eticheta
Are ca efect ndeplinirea urmtoarelor secvene:
cx cx B1
daca cx 0 atunci
(IP) (IP) + D8,
adic se decrementeaz CX i dac acesta este diferit de zero, se
execut un salt la eticheta specificat. n caz contrar se continu cu
instruciunea urmtoare. D8 este un deplasament pe 8 bii i
69

reprezint diferena dintre (IP-ul instruciunii ce urmeaz dup


instruciunea LOOP i offset-ul etichetei).
Instruciunea LOOPZ/LOOPE (LOOP While Zero/Equal)
Forma general:
LOOPZ eticheta
sau
LOOPE eticheta
Semnificaia:
cx cx B 1
dac cx 0 si ZF = 1 atunci
(IP) (IP) + D8
Se decrementeaz cx i dac acesta este diferit de zero i indicatorul
ZF este 1 (rezultatul ultimei operaii aritmetice a fost zero), se
execut un salt la eticheta specificat.
Instruciunea LOOPNZ/LOOPNE (Loop While Not Zero/Not
Equal)
Forma general:
LOOPNZ eticheta
sau
LOOPNE eticheta
Semnificaia:
cx cx - 1
dac cx 0 si ZF = 0, atunci
(IP) (IP) + D8
Efectul acestei instruciuni const n faptul c se cicleaz atta
timp, pn cnd rezultatul ultimei operaii aritmetice este diferit de
zero, dar numrul iteraiilor nu trebue s fie mai mare dect
continuul iniial a lui cx.

70

2.3. Prelucrarea irurilor


Instruciunile speciale ale microprocesoarelor din familia 8086
pentru tratarea irurilor implementeaz foarte eficient funcii pentru
prelucrarea irurilor de octei sau cuvinte.
Instruciunile speciale pentru tratarea irurilor se mai numesc
i primitive pentru tratarea irurilor. Acestea snt:
a) movs dst,srs
movsb
movsw
b) cmps srs,dst
cmpsb
cmpsw
c) scas dst
scasb
scasw
d) lods srs
lodsb
lodsw
e) stos dst
stosb
stosw

;(di)) <- - ((si))


;(si) <- - (si) + D
;(di) <-- (di) + D
;((si)) - ((di))
;(si) <- - (si) + D
;(di) <-- (di) + D
; (REG) - ((di))
;(di) <-- (di) + D
;(REG) <- - ((si))
;(si) <-- (si) + D
;((di)) <- - (REG)
;(di) <-- (di) + D

Pentru operaia pe octet D=1 i REG=al, iar pentru operaia


pe cuvnt D=2 i REG=ax. Dac (df)=0, se realizeaz
autoincrementarea registrelor
si i di, altfel se realizeaz
autodecrementarea lor. Fiecare dintre cele cinci primitive poate avea,
dupa cum se observa, trei forme externe. n cazul primei forme - n
care operanzii snt explicii - n funcie de tipurile acestora se
determin dac instruciunea opereaz la nivel de octet sau cuvnt.
Forma a doua se utilizeaz pentru operare pe octet, iar forma a treia
pentru operare pe cuvnt. Indiferent de formatul primitivei, adresele
efective ale operanzilor se determina din coninuturile registrelor si i
71

di, i anume, din coninutul lui si pentru operandul surs i din


coninutul lui di pentru operandul destinaie. Pentru operandul surs
adresa fizic se calculeaz utiliznd implicit registrul de segment ds,
acesta putnd ns fi redirecionat la es, cs sau ss. Pentru operandul
destinaie adresa fizic se calculeaz utiliznd implicit registrul de
segment es care nu poate fi redirecionat.
Exemplul 1. {Deplasare unui bloc de memorie de la o adres surs la
o adres destinaie}. Vom prezenta o prim variant a acestei
probleme n care nu se utilizeaz primitivele pentru iruri.
DATA

SEGMENT
DB
100 DUP(7)
DB
100 DUP(?)
ENDS
SEGMENT
ASSUME
cs:CODE,ds:DATA
start:
mov ax,DATA
mov ds,ax
mov si,OFFSET sir1
mov di,OFFSET sir2
mov cx,LENGTH sir1
muta:
mov al,[si]
mov [di],al
inc si
inc di
loop muta
CODE
ENDS
END start
sir1
sir2
DATA
CODE

Varianta care utilizeaz primitiva movs este urmtoarea:


DATA
sir1
sir2
DATA
CODE
start:

SEGMENT
DB
100 DUP(7)
DB
100 DUP(?)
ENDS
SEGMENT
ASSUME
cs:CODE,ds:DATA,es:DATA
mov ax,DATA
mov ds,ax
mov es,ax

72

muta:
CODE

mov si,OFFSET sir1


mov di,OFFSET sir2
mov cx,LENGTH sir1
cld
movs sir1,sir2
loop muta
ENDS
END start

Limbajul de asamblare
permite cresterea eficienei
implementrii buclelor de prelucrare a irurilor prin prefixarea
instruciunii repetate cu un prefix, avnd lungimea de un octet al crui
efect este executarea repetat a primitivei prefixate. Specificarea
prefixului n limbaj de asamblare se face prin plasarea unui mnemonic
special naintea primitivei respective. Mnemonicele posibile snt: rep,
repe/repz, repne/repnz.
Prima mnemonic se folosete cu primitivele movs, lods i stos, iar
urmtoarele dou cu toate cele cinci primitive.
Utiliznd prefixul rep bucl:
muta:movssir1,sir2
loopmuta
din exemplul 1 se poate rescrie astfel:
repmovssir1,sir2
Exemplul 2. {Compararea a dou iruri de octei}. Varianta fr
prefix rep este:
DATA
sir1
sir2
DATA
CODE
start:

comp:

SEGMENT
DB
DB
ENDS
SEGMENT
ASSUME
mov
mov
mov
mov
mov
mov
cmps

'AAAABC'
'AAAACB'
cs:CODE,ds:DATA,es:DATA
ax,DATA
ds,ax
es,ax
si,OFFSET sir1
di,OFFSET sir2
cx,LENGTH sir1
sir1,sir2

73

exit:
CODE

jne
loop
nop
ENDS
END

exit
comp
start

Dac la terminarea secvenei de program avem (zf)=1, atunci


irurile snt identice, n caz contrar nu snt identice.
n varianta cu prefix rep bucla:
compar:
ies:

cmps
jne
loop
nop

sir1,sir2
ies
compar

se nlocuiete cu:
exit:

repe cmps
jne exit
nop

sir1,sir2

Primitivele pentru iruri snt n special utilizate pentru


prelucrarea irurilor de caractere.

2.4. Lucrarea de laborator nr. 1


1. Tema lucrrii: Programe liniare i programe cu ramificri.
2. Scopul lucrrii:
Lucrarea are drept scop nsuirea instruciunilor pentru transferuri
de date, a instruciunilor n aritmetica binar i n aritmetica binarzecimal, deprinderea studenilor de a proiecta i a implementa
programe cu ramificri i bucle, famializarea cu probleme legate de
prelucrarea irurilor n limbajul de asamblare.
74

3. Probleme propuse pentru lucrrile de laborator


1. S se inverseze un ir de octei sau cuvinte.
2. S se numere toate apariiile secvenei 'XX' dintr-un ir de octei,
reprezentnd un ir de caractere.
3. Se consider un text reprezentat sub forma unei secvene de
iruri de caractere, fiecare ir de caractere reprezentnd o linie de text.
S se transforme textul astfel nct n textul final cuvintele s fie
separate n cadrul fiecarei linii prin exact un blanc.
4. Se consider c pentru reprezentarea n memorie a unui ir de
caractere se folosete urmtoarea structur de date:
n = numrul de componente
caracter 1
.
.
caracter n
Se cere s se scrie o procedur care primete ca parametri trei adrese
de memorie A1, A2 i A3 i concateneaz irurile de caractere de la
adresele A1 si A2 n aceast ordine, depunnd rezultatul la adresa A3.
Dac acesta depete 255 caractere lungime, flagul cf se va
poziiona pe 1, ultimele caractere din irul al doilea pierzndu-se.
Altfel, cf se va poziiona pe 0.
5. Din structura de date propus n problema anterioar pentru
reprezentarea intern a unui ir de caractere, s se scrie o procedur
care primete ca parametri dou adrese de memorie A1 i A2 i un
caracter CAR, i elimin caracterul CAR din irul de caractere,
ncepnd de la adresa A1, depunnd rezultatul ncepnd de la adresa A2.

75

6. Din structura de date propus n problema 4 pentru reprezentarea


ntern a unui ir de caractere, se cere s se scrie o procedur care
primete ca parametri:
- dou adrese, S1 i S2, reprezentnd adresele a dou iruri de
caractere;
- dou numere ntregi I i J care satisface relaia
1 < I < J < lungimea irului de caractere de la adresa S1
i depune ncepnd de la adresa S2 subirul irului de caractere
ncepnd de la adresa S1, cuprins ntre poziiile I i J ale acestuia. Dac
I i J nu satisfac condiiile cerute, se va poziiona cf pe 1
abandonndu-se procedura, altfel se va poziiona cf pe 0.
7. Din structura de date propusa n problema 4 pentru reprezentarea
ntern a unui ir de caractere, s se scrie o procedur care primete ca
parametri:
- dou adrese, S1 i S2, reprezentnd adresele a dou iruri de
caractere;
- o adres I reprezentnd adresa unui numr ntreg
i caut n irul de caractere, ncepnd de la adresa S1 prima apariie a
irului de caractere, ncepnd de la adresa S2 i o returneaz n ntregul
I. n cazul n care cutarea va eua, se va returna I=0.
8. Din structura de date propusa n problema 4 pentru reprezentarea
ntern a unui ir de caractere, s se scrie o procedur care primete ca
parametri dou adrese S1 i S2, reprezentnd adresele a dou iruri de
caractere i returneaz, ncepnd de la adresa S2, irul obinut prin
nlocuirea secvenelor succesive de blancuri din irul ncepnd de la
adresa S1 cu cte un singur blanc.
9. Din structura de date propus n problema 4 pentru reprezentarea
ntern a unui ir de caractere, se cere s se scrie o procedur care
primeteca parametri trei adrese de memorie S1, S2 i S3 i are ca efect
tergerea din irul de caractere, ncepnd la adresa S1 a primei apariii
a irului de caractere, ncepnd de la adresa S2, irul de caractere
rezultat depunndu-se ncepnd de la adresa S3.
10. Din structura de date propusa n problema 4 pentru
reprezentarea ntern a unui ir de caractere, s se scrie o procedur
care primete ca parametri:
76

- trei adrese de memorie S1, S2 i S3, reprezentnd adresele unor


iruri de caractere;
- un numr ntreg I
i realizeaz inserarea naintea poziiei I din irul S1 a irului S2,
rezultatul fiind returnat n S3. De exemplu dac S1='ABC', S2='123',
atunci, dac I=1 atunci S3='123AAA', dac I=3 atunci S3='AB123C',
iar dac I < 4 atunci S3='ABC123'. Dac irul rezultat depete
lungimea 255, operaia nu se va executa i se va poziiona cf pe 1,
altfel se va poziiona cf pe 0.
11. Realizai un program care creeaz un tablou de simboluri
(64 caractere de la caracterul blanc pn la caracterul "-") i
imprimai tabloul obinut pe ecran.
12. Realizai un program cu ajutorul cruia poate fi urmrit
partea a doua a tabelului de coduri ASCII (codurile 128-255 de
tot 128 caractere). Pentru aceasta, creai un tablou alctuit din
codurile acestor caractere i imprimai tabloul pe ecran.
13. Realizai un program care copie un bloc de 2000 de octei
dintr-o zon 1 n zona 2 i din zona 2 n zona 3 i imprimai blocul
3 pe ecran.
14. Compararea a dou zone de memorie. Realizai un
program ce compar dou zone de memorie cu acelai coninut i
imprimi pe ecran rezultatul comparrii. Modificai cmpul de
date al programului, modificnd i zonele de memorie ca ele s nu
coincid i programul s fie executat din nou.
3. Proceduri i macroinstruciuni
3.1. Macroinstruciuni
O macroinstruciune reprezint o secven de instruciuni creia
i se asociaz un nume. Apariia macroinstruciunii n textul
programului este nlocuit automat de ctre asamblor cu secvena de
instruciuni asociat. Ea poate fi parametrizat, adic poate fi
definit n funcie de o serie de parametri formali care snt
actualizai la utilizarea macroinstruciunii, fiind, deci, nlocuii cu
77

parametri actuali.
Sintaxa de definire a unei macroinstruciuni este:
< nume_macro > MACRO [ lista_parametri_formali ]
< corpul macroinstruciunii >
[;comentarii]
ENDM
n corpul macroinstruciunii pot s apar orice instruciuni,
apeluri sau definiri de macroinstruciuni. Comentariile din corpul
su vor aprea la fiecare apel al macroinstruciunii. Dac se dorete
ca aceste comentarii s apar numai n definiia macroinstruciunii,
se va dubla caracterul ; utilizat pentru comentarii. Utilizarea
macroinstruciunii
se
face
prin
specificarea
numelui
macroinstruciunii, urmat de parametrii efectivi.
Numele parametrilor actuali pot fi i cuvinte rezervate, dar
numele parametrilor formali nu pot fi cuvinte rezervate. Dac n
definirea unei macroinstruciuni, se utilizeaz etichete, acestea
trebuie declarate LOCAL, deoarece pentru diferitele utilizri ale
macroinstruciunii s-ar obine redefiniri multiple ale etichetei.
Sintaxa pentru utilizarea acestei directive este:
LOCAL < lista_etichete >
Rolul su este de a declara ca locale simbolurile din list pentru
fiecare apel. Directiva se poate utiliza numai n macroinstruciuni i
precede instruciunile din corpul macroinstruciunii.
Exemple:
1) Calculul puterii ntregi a unui numr ntreg.
putere macro numar,exponent
local iar,gata
xor dx,dx ;rezultatul este returnat n (DX,AX)
mov ax,1 ;pregatire rezultat,dac exponentul este 0
push cx
;salvare (CX) i (BX)
push bx
mov cx,exponent
jcxz gata
;dac CX=0, puterea este 1
78

bx,numar ;inmulitorul n BX
bx
gata ; dac apare eroare la nmulire, se
; poziioneaz CF
loop iar
gata:pop bx ; refacerea registrelor salvate
pop cx
endm
; progrmul ce utilizeaz aceast macro. va testa
; valoarea lui CF, dac este 0 valoare corect n
; (DX,AX), dac ns CF=1, a aparut depaire

mov
iar: mul
je

2) S se calculeze modulul unui numr.


modul
macro val
local
gata
cmp
val,0
jge
gata
neg
val
gata:
endm
Macroinstniciui de repetare
Limbajul de asamblare permite i utilizarea unor
macroinstruciuni predefinite cu format fix: REPT, IRP i IRPC.
REPT - aceast macroinstruciune permite efectuarea unor repetri
parametrizate ale unor secvene.
Sintaxa macroinstruciunii REPT:
REPT <expresie_contor>
< corpul macroinstructiunii >
ENDM
unde <expresie_contor> reprezint numrul de repetri ale
secvenei de instruciuni, cuprinse ntre REPT i ENDM.
IRP - Macroinstruciuni de repetare condiionat
79

O alt macroinstruciune predefinit este:


IRP <nume>,<<lista>>
< corpul macroinstructiunii >
ENDM
unde <nume> va fi nlocuit, n instruciunile ce formeaz corpul
macroinstruciunii, cu valorile din <lista> de argumente. Deci, se va
repeta corpul macroinstruciunii pentru fiecare valoare din list
(numrul de repetiii este egal cu numrul de valori din list).
Macroinstruciunea IRPC este asemntoare cu IRP, cu deosebirea
c n acest caz, rolul valorilor numerice este preluat de caractere.
Utilizarea operatorilor &,%
Operatorul & este utilzat pentru substituirea valorilor ce l preced,
cu valoarea numeric sau subirul de caractere asociat simbolului
respectiv(concatenare).
Operatorul % efectuiaz conversia simbolului care urmeaz de la
o valoare numeric la un ir de caractere ce poate fi utilizat n
scopul de a substitui un argument, pentru un apel de
macroinstruciune.
3.2. Proceduri n limbajul de asamblare
Definirea i utilizarea procedurilor
O procedur este constituit dintr-o secven de instruciuni,
care poate fi apelat ori de cte ori este nevoie i se declar
folosind urmtoarea sintax:
nume_procedura

proc

[ near / far ]

< corpul procedurii >


nute_procedura

ret(constant)
endp

Dac atributul NEAR i FAR lipsesc, n cazul utilizrii


definiiilor complete se consider implicit NEAR, iar n cazul
80

definiiilor simplificate se folosesc valorile implicite n funcie de


modelul de memorie utilizat.
Instruciunea CALL (apel de procedur)
Poate aprea sub una din formele:
CALL nume_proc
CALL NEAR PTR nume_proc
CALL FAR PTR nume_proc
Tipul apelului poate fi dedus din tipul procedurii (primul caz) sau
specificat explicit prin atributele NEAR i FAR. Tipul apelului
trebuie s coincid cu tipul procedurii i cu tipul instruciunii
RETURN din interiorul procedurii.
Instruciunea de apel a subrutinelor CALL poate fi utilizat n
patru moduri.
Apelul poate fi:
- n apropiere (n cadrul unui segment curent):
- la distan (procedura poate fi situat ntr-un alt segment de cod
);
- indirect n apropiere (n cadrul segmentului de cod curent prin
intermediul locaiei ce conine adresa de salt);
- indirect la distan (n alt segment de cod prin intermediul
locaiei ce conine adresa de salt).
n calitate de subrutin poate fi folosit orice sector al
programului ce se sfrete cu instruciunea RET. Punctul de
intrare n acest sector poate fi marcat printr-o etichet care permite
apelarea subrutinei. n cadrul apelului indirect n care adresa de
salt calculat ntr-un mod oarecare este ncrcat ntr-o locaie de
memorie, prezena etichetei n punctul de intrare n subrutin nu
este obligatorie.
Instruciunea RET (RETURN)
Instruciunea RET poate aprea sub una din formele:
RETN [n]
RETF [n]
RET [n]
81

unde n este o constant ntreag opional.


Tipul instruciunii RET este dedus implicit din tipul procedurii sau
explicit prin prezenta lui N sau F n mnemonica instruciunii RET.
Parametrii (datele de intrare) pot fi transmii n diferite moduri:
- prin registre;
- prin memorie, care presupune rezervarea de memorie pentru
aceti parametri;
- prin stiv, care este metoda cea mai avantajoas, ntruct
permite accesul uor la informaie (cu instruciunile PUSH i
respectiv POP.
n ceea ce privete parametrii transmii prin stiv acetea pot fi de
tipul:
valoare, adic se transmite valoarea parametrului;
adres, adic se transmite adresa parametrului.
n ceea ce privete parametrii returnai de procedur, acetia pot fi
returnai utiliznd una dintre metodele folosite pentru transmiterea
parametrilor spre procedur.
n general, pentru definirea unei proceduri se parcurg urmtoarele
etape:
- stabilirea prelucrrilor efectuate de procedur;
- definirea datelor de intrare/ieire, precum i a modului de
transmitere a parametrilor (registre, memorie sau stiv);
- definirea tipului procedurii (NEAR/FAR), mai ales dac
parametrii se transmit prin stiv, situaie n care trebuie determinat
poziia lor n stiv;
- pentru directivele simplificate de segmentare nu este
necesar precizarea tipului procedurii, deoarece tipul este
determinat de asamblor, din directiva MODEL; dac se utilizeaz
nume simbolice n procedur. Pentru a le accesa corect trebuie
salvat DS n stiv, dup care se ncarc noua valoare i se folosete
directiva ASSUME, pentru a preciza asocierea segmentului la DS,
iar la sfrit se reface registrul DS cu valoarea din stiv. nainte de
orice prelucrare, trebuie salvate n stiv registrele utilizate de
procedur, iar nainte de revenirea n programul apelant acestea
trebuie restabilite.
82

Exemplu: Subprogram pentru calculul sumei


elementelor unui tablou. Subprogramul se
implementeaz ca procedur cu trei parametri:
adresa tabloului (relativ la DS), numrul de
componente i adresa unde se va depune rezultatul.
DATA SEGMENT
vec
SWORD 1, -2, 3, -4, 5, 6
s
SWORD ?
DATA ENDS
COD
SEGMENT
...
; depune pe stiva adresa tabloului
mov ax,OFFSET vec
push ax
; depune pe stiva numarul de elemente ale
tabloului
mov ax,LENGTHOF vec
push ax
; depune pe stiva adresa rezultatului
mov ax,OFFSET s
push ax
; apeleaza procedura
call suma_vec
...
COD
ENDS
PROC_S SEGMENT
...
CADRU_STIVA STRUCT
bp_vechi
WORD ?
cs_ip_vechi WORD 2 DUP(?)
adr_s
WORD ?
lun_vec
WORD ?
adr_vec
WORD ?
CADRU_STIVA ENDS
...
; codul procedurii
suma_vec PROC FAR
push bp
; se utilizeaza BP pentru accesul parametrilor
mov bp,sp
push ax
push cx

83

push
push
xor
mov
jcxz
mov
mov
urm:

si
di
ax,ax
cx,(CADRU_STIVA [bp]).lun_vec
@F
si,(CADRU_STIVA [bp]).adr_vec
di,( CADRU_STIVA [bp]).adr_s

add ax,[si]
add si,2
loop urm

@@:

mov [di],ax
pop di
pop si
pop cx
pop ax
pop bp
ret 6
suma_vec ENDP
...
PROC_S ENDS

3.3. Programe compuse din mai multe module


Fie urmtoarea structur de program compus din dou module:
modulul A
definire S
declarare P
start:
. . .
call P
. . .
end Start

modulul B
definire P
declarare S
P proc
refer S
. . .
endp

Dup cum se observ simbolul S este alocat n modulul A i


folosit n modulul B. De asemenea, modulul A (programul
principal) apeleaz procedura P, care folosete n calculele sale
valoarea simbolului definit n modulul A.

84

Directivele minimale pentru rezolvarea acestei comunicri


ntre module snt EXTRN i PUBLIC. Revenind la contextul de
mai sus, va trebui ca simbolul P s fie definit n B astfel:
PUBLIC P

Simbolul P devine cunoscut n exterior. Pentru a referi valoarea


simbolului S, definit n A, vom scrie:
EXTRN S

n acelai modul B. n mod similar, vom ntlni n modulul A linia


surs urmtoare:
PUBLIC S

care va face accesibil simbolul S i din acest modul. Vom crea n


continuare programul urmtor alctuit din dou module.
Programul principal care apeleaz o procedur
.MODEL small
.STACK 200h
.DATA
PUBLIC Mesaj,Lungime_Mesaj
Raspuns db ?
Mesaj
db "Cunoatem limbajul
Assembler ? (D/N) "
Lungime_Mesaj equ $-Mesaj
.CODE
EXTRN PRINT_String : PROC
Start:
mov AX,@data
;
Adresm segmentul de date
mov DS,AX
call print_string
; apelul
procedurii
mov AH,1
;
ateptm introducerea unui
int 21h
;
caracter
; afiat prin ecou
and AL,5fh
; l
transformm n liter mare
mov Rspuns,AL

;
85

mov AH,4ch
int 21h
end Start

Procedura apelat

.model small
.data
EXTRN lungime_Mesaj:ABS,Mesaj:Byte
.code
PUBLIC PRINT_STRING
Print_String PROC
mov BX,1
mov CX,lungime_Mesaj
mov DX,offset Mesaj
mov AH,40h
int 21h
ret
Print_String ENDP
end

Declaraia EXTRN nu realizeaz i alocarea memoriei. Deci,


contorul de program nu va avansa n procesul translatrii.
Formele sintactice pentru aceste directive PUBLIC i EXTRN snt
urmtoarele:
PUBLIC nume, [nume,...]
EXTRN nume:tip[,nume:tip...]

n formele prezentate ntlnim specificatori de tip ce pot fi


clasificai astfel:

Tabel: Specificatorii de tip

86

Descrierea
Specificator de distan
Specificator de dimensiune
Absolut

Tipul
NEAR, FAR sau PROC
BYTE, WORD, DWORD,
PWORD, FWORD,
QWORD sau BYTE
ABS

Tipul ABS este folosit pentru simboluri care reprezint nume


de constante. Simbolul lungime-mesaj definit prin directiva equ
poate transmite proprietatea ABS simbolui pe care l definete tipul.
Tipul PROC reprezint tipul implicit pentru o procedur.
Pentru asamblarea celor dou module de program de mai sus,
denumite de exemplu, main i wrstr, vom utiliza comenzile
urmtoare:
tasm main
tasm wrstr

Pentru legarea celor dou module ntr-un program comun


".EXE", comanda de editare a legturilor are forma
tlink main wrstr

Fiierul executabil se va numi main.exe. Acesta va fi lansat n


execuie cu ajutorul comenzii : main
3.4. Lucrarea de laborator nr. 2
1. Tema lucrrii: Proceduri i macroinstruciuni.
2. Scopul lucrrii:
Lucrarea are drept scop nsuirea tehnicilor de programare,
utilizund macroinstruciuni i subprograme n limbajul de
asamblare, nsuirea tehnicilor de transfer a parametrilor ctre
subprograme, precum i dezvoltarea subprogramelor recursive i
reentrante.
3. Probleme propuse pentru lucrarea de laborator:
1. Scriei un subprogram care caut ntr-un tablou de numere
ntregi un element dat. Procedura va returna indexul elementului n
87

tablou (numrat ncepnd de la 1) dac elementul a fost gsit, altfel


returneaz valoarea 0.
2. Scriei un set de subprograme pentru realizarea unor operaii
aritmetice fr semn pe operanzi reprezentai pe cte un dublu
cuvnt:
(a) adunare: adun cei 2 operanzi;
(b) scdere: se scad cei 2 operanzi;
(c) nmulire: nmulete cei doi operanzi i ntoarce 32 de
bii ai rezultatului, cel mai puin semnificativi;
(d) mparire: mparte cei doi operanzi returnnd ctul.
3. Scriei un subprogram pentru evaluarea expresiei ax+b.
Parametrii a, b, x snt ntregi fr semn n dubl precizie.
4. Scriei un subprogram pentru evaluarea polinomului
P(x) = a0 + a1x + ... + anx. Procedura primete ca parametri: tabloul
coeficienilor, numrul elementelor acestui tablou i valoarea lui x.
5. S se scrie un subprogram care primete ca parametri: adresa
unui ir de caractere, lungimea irului, valorile a dou caractere
car1 i car2 i inlocuiete n irul dat toate apariiile lui car1 cu
car2. Utiliznd acest subprogram, s se nlocuiasc toate blancurile
dintr-un ir cu liniue de subliniere, apoi s se afieze irul.
6. S se scrie un subprogram care primete ca parameri: adresa
unui ir de caractere, lungimea irului i nlocuiete toate secvenele
succesive de blancuri din ir cu cte un singur blanc, apoi returneaz
lungimea noua a irului.
7. S se scrie un subprogram care determin suma elementelor
unui vector de numere ntregi cu semn reprezentate n dubla
precizie. Procedura primete ca parametri: adresa irului, numarul
de componente ale acestuia i returneaz suma calculat.
8. S se scrie un subprogram care determin inversarea unui ir
de caractere terminat cu caracterul null (codul ASCII 00h).
Subprogramul primete ca parametru adresa irului de caractere.
9. S se scrie un subprogram care parcurge un tablou de numere
ntregi cu semn reprezentate n dubla precizie i nlocuiete fiecare
element al tabloului cu valoarea sa absolut. Subprogramul primete
88

ca parametri adresa tabloului i adresa unei locaii de memorie unde


se afl numrul de componente ale vectorului.
10. Se consider o tabel, fiecare intrare din tabel avnd
dimensiunea de un octet, ultimul element al tabelului avnd valoarea
0ffh. S se scrie un subprogram care determin numrul de intrri n
tabel care ndeplinesc urmtoarele condiii:
- au bitul 6 setat;
- conin exact patru bii setai n 1.
Subprogramul primete ca parametri adresa tabelului i adresa unde
se va depune numrul de intrari determinate.
11. S se scrie un subprogram care realizeaza urmtoarele:
- primete ca parametru adresa unui ir de caractere terminat
cu caracterul '$';
- parcurge irul respectiv, ignornd blancurile i tab-urile n
scopul determinrii primului subir al acestuia care ncepe cu o
liter i conine doar litere i cifre;
- dac nu exist nici un astfel de subir, adic irul iniial
este format doar din blancuri i tab-uri sau este vid, se returneaz n
cx valoarea zero i cf se pune pe zero. Dac primul caracter din ir
diferit de blanc i tab este o liter, se extrage subirul maximal care
ndeplinete condiia menionat anterior, fiind returnat n bx
adresa acestuia, n cx numarul de caractere ale sale cf punndu-se tot
pe zero. Dac ns primul caracter din ir diferit de blanc i tab nu
este o liter, cutarea este abandonat, cf punndu-se pe unu.
12. Considerm un tablou de numere ntregi cu semn
reprezentate pe cte un cuvnt, ordonat cresctor. S se scrie o
procedur care realizeaz o cutare binar a unei valori n acest ir.
Procedura primete ca parametru adresa vectorului, numrul de
elemente ale vectorului i returneaz poziia n care valoarea
respectiv a fost determinat n ir. Dac valoarea cautat nu a fost
gasit n ir, se returneaz valoarea zero.
13. S se scrie un subprogram pentru calculul sumei valorilor
absolute a trei numere ntregi cu semn reprezentate n dubla
precizie.

89

14. S se scrie un subprogram pentru ordonarea cresctoare a


elementelor unui tablou, avnd ca componente numere ntregi cu
semn reprezentate n dubl precizie. Subprogramul primete ca
parametru adresa tabloului.
4. Interfaa ASM - limbaje de nivel nalt
Programarea mixt
Procesul de creare de programe folosind dou sau mai multe
limbaje surs se numete programare n limbaj mixt sau mai simplu
programare mixt. Vom utiliza n continuare tehnici de programare
mixt pentru cazul n care unul din limbaje este limbajul de
asamblare, iar cellalt limbaj este un limbaj de nivel nalt, n cazul
nostru C++.
Distingem dou situaii:
a) Includerea de module sau secvene scrise in limbaj de
asamblare ntr-un program scris n limbaj de nivel nalt;
b) Apelul dintr-un modul scris n limbaj de asamblare a unor
module scrise n limbaje de nivel nalt.
Menionm c modalitaile efective de realizare de programe
n limbaj mixt depind de compilatoare i de sistemul de operare
folosit. n cele ce urmeaz vom evidenia unele aspecte invariante ale
programrii mixte tip limbaj de nivel inalt+limbaj de asamblare,
modulele apelate fiind funcii.
Pentru scrierea unei proceduri n limbaj de asamblare ce va fi
apelat de un program scris n limbaj de nivel nalt Borland C++ se
vor parcurge urmatorii pai:
1. Editarea textului programului C++ ntr-un fiier cu extensia
.cpp
2. Editarea textului procedurii scrise n limbajul de asamblare
ntr-un fiier cu extensia .asm
3. Compilarea i linkeditarea modulelor cu ajutorul liniei de
comand:
bcc nume_cpp.cpp nume_asm.asm
90

Asamblorul integrat compilatorului C++


Mediul C++ conine
un asamblor integrat care permite
inserarea direct n program a unor secvene scrise direct n limbajul
de asamblare. Aceste secvene snt ncadrate ntre cuvintele-cheie asm
i end, formnd aa-numitele blocuri asm. Sintaxa unui bloc asm este
urmtoarea:
asm
{

Instruciuni
...

Exemplul 1. Acest exemplu reprezint un program C++ care


apeleaz o funcie pentru adunarea a doi ntregi, scris n limbaj de
asamblare:
Pasul 1
// programul apelant

cnume.cpp

#include <conio.h>
#include <iostream.h>
extern "C" int adun(int i,int j) ;
void main(void)
{
clrscr();
int a,b,r;
cout<<"Introduceti doua numere intregi\n";
cin>>a>>b;
r=adun(a,b);
cout<<"Suma este:\n "<<r<<"\n";
getch();
}
Pasul 2
; Subprogramul in asembler anume.asm
.model small
.stack 100h
.code
public _adun
_adun
PROC c near i:word,j:word

91

_adun

mov ax,i
add ax,j
ret
ENDP
end

Pasul 3
rem fisierul cnume.bat destinat pentru
rem compilare,linkeditare si executie
bcc cnume.cpp anume.asm
cnume

Observaie: dac fiierele cnume.cpp, anume.asm, cnume.bat sunt


plasate ntr-un directoriu propriu, atunci este necesar s fie indicat
calea unde se gsete compilatorul bcc.
Exemplul 2. Acest program realizeaz afiarea unui caracter de
un numr specificat de ori.
void main()
{
char car;
int nr;
cout<<Inceput\n;
cin>>car;
asm
{
mov cx,nr
@1: mov ah,02h
mov dl,car
int 21h
loop @1
}
Cout<<Sfirsit;
}

Din interiorul unui bloc asm este posibil s se apeleze o


procedur C++, ca n exemplul urmtor.
Astfel, instruciunea TASM: mov ax,es:[di]
se va scrie sub forma: SEGES mov ax,[di]
92

Asamblorul integrat nu d posibilitatea definirii variabilelor n


segmentul de date. Folosind directivele DB, DW, DD, exist
posibilitatea definirii datelor n segmentul de cod. Datele pot fi
precedate de o etichet local. Adresele acestor variabile pot fi
obinute prin intermediul operatorului OFFSET.
Exemplul 3. n acest exemplu se definesc datele n segmentul
de cod.

program date_in_cod;
procedure er_fatala;
begin
asm
push ds
mov ax,OFFSET @mesaj
push cs
pop ds
mov ah,09h
int 21h
jmp @1
@mesaj:
DB
'Eroare fatala. Oprire
program!'
DB
13,10,'$'
@1:
pop ds
end
end{er_fatala};
begin
er_fatala;
end.

Asamblorul integrat permite definirea procedurilor i funciilor


n ntregime scrise n limbajul de asamblare fr a mai fi necesar
perechea begin end. n acest scop, antetul procedurii sau funciei
pstreaz sintaxa normal din PASCAL i este urmat de cuvntulcheie assembler. Prima instruciune din subprogram nu va fi begin, ci
direct asm. Corpul subprogramului se termin cu o linie end
corespunztoare liniei asm.

4.1. Lucrarea de laborator nr. 3

93

1. Tema lucrrii: Interfaa ASM - limbaje de nivel nalt.


2. Scopul lucrrii:
Lucrarea are drept scop deprinderea studenilor cu crearea
programelor prin legarea de module scrise in limbaj de nivel nalt cu
module scrise in limbaj de asamblare. Ca limbaj de nivel inalt se va
folosi C++. Totodat se urmrete utilizarea unor tehnici ct mai
generale, valabile pentru orice alte implementri C++.

3. Probleme propuse pentru lucrarea de laborator


1. S se scrie o funcie prin care se calculeaz suma
elementelor unui vector de n componente ntregi, n limbaj de
asamblare i s utilizeze aceast funcie n cadrul unui progrm C++.
S se explice de ce o asemenea funcie este mai eficient dect cea
echivalent scris n C++. S se scrie funcia echivalent n C++ i s
se fac o comparaie a timpilor de execuie a celor dou funcii pentru
n, avnd o valoare mai mare (n=30000).
2. S se scrie un program n care se utilizeaz proceduri
imbricate n urmtoarele condiii:
- programul conine o procedur ScrieStr care afieaz un ir de
caractere;
- programul conine o procedur A, care are o variabil local S i o
procedur imbricat B. Procedura B apeleaz procedura ScrieStr
pentru afiarea irului de caractere S;
- corpul procedurii A const n atribuirea unei valori variabilei S i
apelarea procedurii B;
- corpul programului principal consta n apelarea procedurii A;
- procedura B are corpul implementat cu ajutorul unei instruciuni
inline.
3. S se scrie o procedur n limbaj de asamblare, apelabil din
C++, pentru scrierea absolut a unui caracter pe ecran. Procedura are
drept parametri: indicele liniei n gama 1..25; indicele coloanei, n
gama 1..80 i codul caracterului. Adresa de nceput a memoriei video
este B800:0000 (pentru adaptor video CGA). Informaia de pe ecran
94

este codificat sub forma unei secvene de cuvinte cu octetul c.m.p.s


pstrnd codul caracterului i cellalt octet fiind octetul de atribute.
4. S se scrie un program C++ care citete un ir de numere
ntregi (ca n exemplul 3) i cu ajutorul unei proceduri scrise n
limbajul de asamblare determin i afieaz numrul de numere
pozitive, negative i nule din ir. Pentru afiarea rezultatelor, aceast
procedur apeleaz o alta procedur scris n C++.
5. S se scrie o procedur inline, care afieaz un ir de
caractere terminat cu '$', utiliznd funcia DOS cu codul 09h. S se
scrie apoi un program n C++, care afieaz valoarea unei variabile de
tip string, utiliznd procedura inline scris. La apelul DOS cu codul
09h, ah va conine valoarea 09h, iar perechea ds:dx va contine un
pointer la ir.
6. S se scrie un program C++, prin care se calculeaz suma a
dou numere complexe, utiliznd o rutin scrisa n limbaj de
asamblare. Pentru reprezentarea unui numr complex se utilizeaz un
record cu dou cmpuri de tip integer, reprezentnd prile real i
imaginar. Se va rezolva problema n dou situatii:
- rutina este de tip procedur, returnnd suma n parametru;
- rutina este de tip funcie, ntorcnd un pointer la record-ul ce
reprezint suma.
7. S se scrie un program C++, prin care se calculeaz suma a
dou numere ntregi cu semne reprezentate n tripl precizie, utiliznd
o rutin scris n limbaj de asamblare. Pentru reprezentarea unui
numr ntreg cu semn n tripl precizie se utilizeaz un record cu trei
cmpuri de tip integer, reprezentnd cele trei cuvinte corespunztoare
numrului respectiv.
8. S se rezolve problema 7 n condiiile n care cele dou
numere ntregi cu semn snt de tip long int.
9. S se rezolve problema 7 n condiiile n care cele dou
numere ntregi cu semn snt reprezentate n multipl precizie prin
patru cuvinte de memorie. Pentru reprezentare se utilizeaz un record
cu dou cmpuri de tip longint, reprezentnd partea cea mai puin
semnificativ, precum i cea mai semnificativ a numerelor
respective.
95

10. S se scrie o functie,prin care se calculeaza suma


elementelor unui vector de n componente ntregi n limbaj de
asamblare i s utilizeze aceast funcie n cadrul unui progrm C++.
S se explice de ce o asemenea funcie este mai eficient dect cea
echivalent scris n C++. S se scrie funcia echivalent n C++ i s
se fac o comparaie a timpilor de execuie a celor dou funcii pentru,
n avnd o valoare mai mare (n=30000).
11. S se scrie o procedur n limbaj de asamblare, apelabil din
C++, pentru extragerea unui caracter pe ecran. Procedura primete ca
parametri: indicele liniei n gama 1..25; indicele coloanei n gama
1..80 i codul caracterului n poziia indicat de linia i coloana
determinate mai sus.
12. S se scrie un program C++, prin care se citete un ir de
numere ntregi i cu ajutorul unei proceduri scrise n limbaj de
asamblare determin i afieaz numrul de numere pozitive, negative
i nule din ir. Pentru afiarea rezultatelor, aceast procedur apeleaz
o alta procedur scrisa n C++.
13. S se scrie un program C++, prin care se calculeaz suma a
dou numere complexe, utiliznd o rutin scris n limbaj de
asamblare. Pentru reprezentarea unui numr complex, se utilizeaz un
record cu doua cmpuri de tip int, reprezentnd partea real i
imaginar. Rutina este de tip funcie, returnnd un pointer la record-ul
ce reprezint suma.
5. Utilizarea ntreruperilor DOS
5.1. Tratarea ntreruperilor
Aciunea provocat de ndeplinirea unei condiii (intern sau
extern n raport cu programul aflat n execuie) prin care se realizeaz
automat transferul controlului unei rutine speciale de tratare se
numete ntrerupere, iar rutina respectiv se numete rutin de
ntrerupere. Exist dou clase de ntreruperi:
ntreruperi interne: acestea snt iniiate de starea programului aflat
n execuie sau prin executarea unor instruciuni speciale de

96

ntrerupere. Ele se caracterizeaz prin faptul c snt sincrone n raport


cu programul aflat n execuie. Se mai numesc ntreruperi software.
ntreruperi externe: acestea snt iniiate de partea hardware prin
intermediul semnalelor de ntrerupere trimise spre procesor.
Declanarea lor semnific ndeplinirea unor evenimente externe
procesorului. Ele se caracterizeaz prin faptul ca snt asincrone n
raport cu programul aflat n execuie. Se mai numesc ntreruperi
hardware.
O rutin de ntrerupere este asemntoare unei proceduri n sensul
c dup execuia ei se revine n programul ntrerupt la instruciunea
imediat urmtoare celei ntrerupte. Modalitatea de declanare a unei
rutine de ntrerupere este n general diferit de apelul unei proceduri,
existnd ns, pentru anumite clase de ntreruperi i similitudini (la
microprocesoarele 8086/88 exist aproape o similitudine perfect ntre
apelul procedurilor ndepartate i instructiunile de ntrerupere). Ca
element comun notm necesitatea salvrii contextului programului
ntrerupt (cuvnt de stare program, numrtor de program, registre
generale) la intrarea n rutin de ntrerupere. Deoarece anumite
ntreruperi snt iniiate de evenimente externe procesorului, asincron
n raport cu programul aflat n executie, acesta nu le poate transmite
nici un fel de parametrii, comunicaiile de date putnd avea loc numai
utiliznd variabile direct accesibile ambelor secvene de program:
secvena curent executabil i rutina de ntrerupere.
Aciunile ce rezult n urma apariiei unei ntreruperi i care
determin transferul controlului rutinei de ntrerupere se numete
secven de ntrerupere. Secvena de ntrerupere care specific
microprocesoarelor i8086 este urmtoarea:
1. Se salveaz valorile curente ale psw, cs i ip n stiv;
2. Se ncarc perechea de registre cs:ip dintr-un pointer determinat
pe baza unei valori calculate folosind tipul ntreruperii, i anume, dac
n este tipul ntreruperii, valoarea calculat este 4n. Pointerul ce
conine noile valori ale registrelor cs i ip se numete vector de
ntrerupere;
3. Se terg flagurile if i tf.

97

Noile coninuturi ale registrelor cs i ip determin adresa de


nceput a rutinei de ntrerupere.
Tipul ntreruperii este un numr ntreg n gama 0..255. Adresa
vectorului de ntrerupere rezult din nmulirea tipului ntreruperii cu
4. Primele 5 tipuri de ntrerupere, i anume 0, 1, 2, 3 i 4, au
semnificaii speciale predefinite:
a) tipul 0 este utilizat pentru tratarea erorii de mprire la zero.
Dac se realizeaz o mprire la zero, se declaneaz automat o
ntrerupere cu tipul 0. O astfel de situaie poate aprea ori de cte ori,
dup executarea unei instruciuni idiv sau div, ctul are o depire de
format, indiferent de valoarea flagului if;
b) tipul 1 este utilizat pentru executarea programelor n regim "pas
cu pas". Dac flagul tf este setat se va declansa automat o ntrerupere
cu tipul 1 la sfiritul fiecrei instruciuni executate de procesor.
Deoarece flagul tf este ters n urma secvenei de ntrerupere, nu vor fi
declanate ntreruperi i dup instruciunile din rutina de ntrerupere;
c) tipul 2 este utilizat de ctre ntreruperea nemascabil.
ntreruperea nemascabil este o ntrerupere extern care poate aprea
indiferent de starea flagului if;
d) tipul 3 este rezervat unei instruciuni speciale de ntrerupere cu
lungimea de un octet cu codul 0cc16. Aceast instruciune este utilizat
pentru implementarea facilitaii de executare a unui program cu
puncte de oprire (breakpoint) din cadrul programelor depanatoare
(debugger);
e) tipul 4 este utilizat pentru tratarea depirilor. Dac se execut o
instruciune into cnd flagul of este setat, se va declana o ntrerupere
cu tipul 4.
Instruciunile cu care pot provoca treruperi prin program se
numesc instructiuni de ntrerupere. Aceste instructiuni snt
urmtoarele:
int TIP
int
into

Executarea unei instruciuni de ntrerupere are ca rezultat apelul


unei proceduri ndeprtate a crei adres este egal cu valoarea
98

vectorului de ntrerupere determinat pe baza tipului ntreruperii.


Revenirea n secvena ntrerupt (apelanta) se face printr-o
instruciune special de revenire care efectueaz n ordine invers
aciunile realizate la apelul rutinei. Aceast instruciune este iret.
5.2. Interfaa limbaj de asamblare - sistem de operare DOS
Rutinele pe care sistemul de operare DOS le utilizeaz pentru
dirijarea resurselor calculatorului pot fi apelate din programele scrise
n limbaj de asamblare. Aceste rutine se mai numesc apeluri-sistem
(system calls). Utilizarea apelurilor sistem de ctre programele de
aplicaie permite obinerea de programe independente de maina
fizic, garantndu-se compatibilitatea acestora cu versiunile superioare
ale sistemului de operare DOS.
Instruciunile de ntrerupere cu tipurile 20 16, ..., 3f16 snt rezervate
apelurilorsistem. Majoritatea apelurilor-sistem snt grupate la
ntreruperea cu tipul 2116. Aceste apeluri snt cunoscute cu numele de
funcii sistem. Pentru executarea unui apel-sistem se procedeaz
astfel:
- se transfer parametrii apelului n registrele procesorului.
Parametrii mpreun cu registrele corespunztoare snt specifici
fiecarui apel n parte;
- se execut instruciune int cu tipul corespunztor apelului
respectiv.
Pentru executarea unei funcii-sistem se procedeaza astfel:
- se transfer parametrii funciei n registre;
- se transfer numarul funciei n registrul ah;
- se transfer un cod suplimentar, dac acest lucru este cerut de
funcia respectiv, n registrul al;
- se execut instruciunea int 21h.
Majoritatea funciilor-sistem seteaz flagul cf dac a aprut o
eroare, codul de eroare fiind returnat n registrul ax.
Principalele funcii-sistem pot fi grupate n urmtoarele categorii:
a) Funcii pentru operaiile de I/E standard, specifice urmtoarelor
dispozitive de I/E: consol, imprimant, interfa serial. Dac un
99

program folosete pentru implementarea operaiilor I/E aceste funcii,


intrarea respectiv ieirea sa pote fi redirecionate. Dintre aceste funcii,
le menionm pe urmtoarele:
- funcia 0116: aceast funcie citete un caracter de la intrarea
standard, pe care l trimite cu ecou la ieirea standard. Dac caracterul
citit este CTRL-C, se execut int 23h. La apel (ah)=0116, iar dup
execuie (al)=codul ASCII al caracterului citit;
- funcia 0216: aceast funcie scrie un caracter la ieirea standard.
Dac se tasteaza CTRL-C, se execut int 23h. La apel (ah)=0216,
(dl)=codul ASCII al caracterului care trebuie scris.
- funcia 0716: aceast funcie citete un caracter de la intrarea
standard. Caracterul citit nu este trimis n ecou la ieirea standard i nu
se efectueaz nici un test pentru CTRL-C. La apel (ah)=0716 i dup
execuie (al)=codul ASCII al caracterului citit;
- funcia 0916: aceast funcie realizeaz afiarea unui ir de
caractere la ieirea standard, irul de caractere fiind terminat cu '$'.
Caracterul '$' nu se afieaz. La apel (ah)=0916, (ds):(dx)=adresa de
nceput a irului de caractere respectiv;
- funcia 0a16: aceast funcie realizeaz citirea unui ir de caractere
de la intrarea standard. La apel (ah)=0a16, (ds):(dx)=adresa unei zone
tampon cu urmtoarea structur:
- primul octet al zonei va conine la apel numrul maxim (fie acesta
n) de caractere care vor fi citite, inclusiv un caracter CR;
- al doilea octet al zonei va conine dup execuia funciei numrul
de caractere efectiv citite, caracterul CR nefiind contorizat;
- restul zonei va trebui s conin cel puin atia octei ci au fost
specificai n primul octet. Dup execuia funciei aici va fi depus irul
citit, primul caracter din ir fiind plasat la adresa cea mai mic.
Caracterele citite snt plasate n zona-tampon specificat, ncepnd
cu al treilea octet al zonei. Citirea se termin cnd se tasteaz CR.
Dac se ncearc introducerea mai multor caractere dect numrul
specificat, adic n-1, caracterele n plus se ignor, fiind trimis la
ieirea standard caracterul BEL (0716). Ultimul caracter din zonatampon este ntotdeauna CR. Dac se tasteaz CTRL-C, se execut
int 23h.
100

Exemplul 1. Urmatorul program citete o tast, determin dac este o


tast obinuit sau funcional i apoi afieaz codul tastei. Citirea
tastei se face cu funcia 0716. Dac la primul apel se ntoarce codul 0
n registrul al, nseamn c tasta accesat este o tast funcional,
codul extins al tastei fiind determinat printr-un al doilea apel al
funciei.
DATA
cerere
sir
mesaj1
mesaj2

SEGMENT
DB 'Tastati o tasta',0ah,0dh,'$'
DB 3 DUP (?),0ah,0dh,'$'
DB 'Codul tastei este:',0ah,0dh,'$'
DB Codul extins al tastei
este:',0ah,0dh,'$'
DATA
ENDS
STIVA
SEGMENT STACK 'STACK'
DW
30 DUP(?)
virf
LABEL
WORD
STIVA
ENDS
COD
SEGMENT
ASSUME cs:COD,ds:DATA,ss:STIVA
start:
jmp
incep
conv
PROC
NEAR
; Primete n registrul al un numar ntreg i n
;registrul bx
; adresa unei zone de 3 octeti. Intoarce n aceast
;zon irul de
; caractere corespunztor scrierii zecimale a ;numrului
push
dx
xor
ah,ah
mov
dl,10
div
dl
add
ah,'0'
mov
[bx+2],ah
xor
ah,ah
div
dl
add
ah,'0'
mov
[bx+1],ah
add
al,'0'
mov
[bx],al
pop
dx

101

conv

ret
ENDP

incep:

; Se

; Se
; Se
; Se
; Se

; Se
; Se
; Se

; Se

mov
ax,DATA
mov
ds,ax
mov
ax,STIVA
mov
ss,ax
mov
sp,OFFSET virf
afiseaz mesajul care cere tastarea unei taste
lea
dx,cerere
mov
ah,09h
int
21h
citete o tasta
mov
ah,07h
int
21h
testeaza daca este tasta funcionala
cmp
al,0
jz
cod_extins
determina codul tastei
lea
bx,sir
call
conv
afieaz mesaj1
lea
dx,mesaj1
mov
ah,09h
int
21h
jmp
afis
citete codul extins
cod_extins: mov
ah,07h
int
21h
determina codul extins
lea
bx,sir
call
conv
afieaza mesaj2
lea
dx,mesaj2
mov
ah,09h
int
21h
afieaza codul tastei
afis:
lea
dx,sir
mov
ah,09h
int
21h
mov
ax,4c00h
int
21h
COD
ENDS

102

END

start

5.3. Lucrarea de laborator nr. 4


1. Tema lucrrii: Utilizarea ntreruperilor DOS.
2. Scopul lucrrii:
Lucrarea are drept scop prezentarea introductiv a modului de
lucru cu ntreruperile al microprocesoarelor i8086, punndu-se accent
pe evidenierea unor tehnici de implementare a programelor n limbaj
de asamblare ce folosesc apeluri de sistem DOS. Se vor considera
funciilesistem pentru dirijarea operaiilor de I/E, a memoriei i
proceselor.
3. Probleme propuse pentru lucrarea de laborator
1. Scriei un program care calculeaz numrul de elemente ale
unui fiier care snt mai mici dect valoarea medie aritmetic a
tuturor elementelor acestui fiier.
2. Scriei un program care compar dou fiiere date.
3. Scriei un program care determin numrul maximal i cel
minimal dintr-un ir de numere aleatoare dintr-un fiier.
Subconsecutivitatea de elemente dintre numrul maximal i cel
minimal determinat s se nregistreze ntr-un nou fiier.
4. Scriei un program care tiprete toate cuvintele diferite de
ultimul cuvnt dintr-un fiier. Cuvintele din fiier snt separate prin
virgul, iar dup ultimul cuvnt se pune punct.
5. Scriei un program care formeaz un fiier nou, selectndu-se
din trei fiiere date mai nti numerele negative, zerourile, apoi
numerele pozitive.
6. Scriei un program care ordoneaz lexicografic o
consecutivitate de nregistrri (dintr-un fiier) de tipul
struct
{ char nume [30]; int ani} nregistrare.
7. Scriei un program care formeaz un fiier nou din trei fiiere
date dup urmtoarea legitate: se selecteaz mai nti numerele
103

divizibile la 3, la 5 i la 7, apoi numerele pozitive pare de pe locuri


impare.
8. Scriei un program care sorteaz lexicografic cuvintele dintrun text. Pentru fiecare element sortat s se indice numrul de
repetri ale cuvntului n textul dat.
9. Scriei un program care din dou fiiere ordonate descresctor
se vor uni n unul nou n care se va pstra ordinea descresctoare de
sortare.
10. Scriei un program care va tipri n ordine invers
subconsecutivitatea de numere dintre valoarea minim i maxim
ale unei consecutiviti de numere citit dintr-un fiier.
11. Scriei un program prin care se calculeaz suma nmulirii
numerelor vecine pe locuri pare dintr-un fiier dat.
12. Scriei un program care determin frecvena cu care a fost
generat fiecare element n fiierului creat. Valorile elementelor snt
cuprinse ntre 1 i 100.
13. Scriei un program care determin numrul maximal i cel
minimal din numerele unui fiier dat. S se determine elementele
mai mari dect cel minimal i mai mici ca numrul maximal.
14. Scriei un program care formeaz un fiier nou din cel dat
dup urmtoarea legitate: elementele fiierului nou se obine din
inversul numerelor din fiierul dat.

104

BIBLIOGRAFIE
1. Vasile Lungu. Procesoare Intel. Programarea n limbaj de
asamblare. Bucureti: Editura Teora , 2000.
2.
Gh. Musca. Programarea in limbaj de asamblare. Bucureti:
Editura Teora, 1997.
3. Gh.Marian, C.Badica, A.Badica. Limbaje de asamblare. ndrumar
de laborator. Tipografia Universitaii din Craiova, 2000.
4. I. Athanasiu, A. Panoiu. Microprocesoarele 8086, 286, 386.
Bucureti: Editura Teora, 1992.
5. Russel Rector, George Alexy. The 8086 Book, Osborne, McGrawHill, Berkeley, California, 1991.
6. William J. Eccles. Microprocessor Systems, A 16-Bit Approach,
Addison Wesley Publishing Company, 1993.
7. Liu Yu-Cheng, Gibson Glenn A. Microcomputer Systems, The
8086 Family, Prentice Hall, 1986.
8. A. Silberschatz, P.B. Galvin and G. Gagne. Operating Systems
Concepts, 7th edn. John Wiley & Sons 2005.
9. .. .
. , 2002.
10. Joshua Engel. Programming for the Java Virtual Machine.
ADDISON WESLEY, 2000.
11. D.W. Barron. Computer Operating Systems. Chapman and Hall,
London, 1971.
12. . . . : , 1974.
13. .. . . :
, 1974.
14. . . . :
, 2002.

105

106

S-ar putea să vă placă și