miercuri, 6 mai 2020

LFA - Compilatoare - S12

Bun venit la ora a II-a )nu uitati sa lucrati si ora I)

CUM ARATA CODURILE RULATE DE MASINA VIRTUALA

In aceasta postare voi prezenta o serie de secvente de cod foarte simple,
in limbajul masinii virtuale.

Scopul este sa intelegem cum arata codurile care vor fi rulate de masina virtuala.

Pentru fiecare voi scrie un mic program in Simple si voi prezenta codul echivalent care va rula pe masina virtuala.

Nota: Aici, mai jos, este scris in_int si nu read_int dar e aceeasi instructiune!
Nota: Aici, mai jos, este scris out_int si nu write_int dar e aceeasi instructiune!
Am inclus si fiserele sursa .sim "echivalente" cu codurile de mai jos:

Exemplul 0:  
Fisier: p0.sim

let
   integer x.
in
end

Codul:

 0: data        0      // Nu ridic varful stivei
 1: halt         0      // ma opresc


 Exemplul 1:
 Fisier: p1.sim

  0: data         0    // Am o singura variabila la baza stivei, pozitia 0
  1: in_int       0    // Citesc o valoare de la tastatura, de la prompter
                                 si o pun pe stiva la adresa variabilei, aici adresa 0
  2: ld_var      0    // Incarc in varful stivei continutul variabilei de la adresa 0
  3: out_int     0    // iau ultima valoare din stiva si o afisez pe consola
  4: halt          0    // ma opresc

 Exemplul 2:
 Fisier: p2.sim

let
   integer x.
in
   read x;
   x := x+1;
   write x;
end

Codul :

  0: data         0  // Am o singura variabila la baza stivei, pozitia 0, variabila x
  1: in_int       0  // Citesc o valoare de la tastatura, de la prompter
                                 si o pun pe stiva la adresa variabilei, aici adresa 0
  2: ld_var      0  //  Incarc variabila de la adresa 0 in varful stivei
  3: ld_int       1  //  Incarc in varful stivei un intreg: pe 1
  4: add          0  //  Scot 2 valori din stiva si le adun , obtin in virful stivei x+1
  5: store        0  //  Stochez ce e in varful stivei la adresa lui x, adica adresa 0
  6: ld_var      0  //  Incarc iar in varful stivei valoarea variabilei de la adresa 0
  7: out_int     0  // iau ultima valoare din stiva si o afisez pe consola
  8: halt          0  // ma opresc

 Exemplul 3:
 Fisier: p3.sim

let
   integer x.
in
   read x;
   if (x=0)
   then
     write 0;
   else
     write 1;
   fi;
end

Codul:

  0: data         0  // Am o singura variabila la baza stivei, pozitia 0, variabila x
  1: in_int       0  // Citesc o valoare de la tastatura, de la prompter
                                 si o pun pe stiva la adresa variabilei, aici adresa 0
  2: ld_var      0  // Incarc in varful stivei intai valoare var de la adresa 0, x-ul
  3: ld_int       0  // Incarc in varful stivei apoi valoare numarului intrg 0
  4: eq            0  // Le scot pe ambele din stiva, le compar, pun rezultatul in stiva
  5: jmp_false 9  // Daca comparatia da False,0, sar la ramura else, adresa 9
                          // Altfel continui.
  6: ld_int       0  // Incarc in stiva valoarea intreaga, constanta 0
  7: out_int     0  // Afisez ultima valoare din stiva
  8: goto        11 // Sar la Halt pt oprire.
                          // De aici incepe ramura else:
  9: ld_int       1  // Incarc in varful stivei  valoarea 1
 10: out_int    0  // Afisez ultima valoare din stiva, adica 1
 11: halt         0  // Stop.

Nota: Incarc in varful stivei este un PUSH, indicatorul de stiva se ridica cu aceasta ocazie.

 Exemplul 4:
 Fisier: p4.sim

let
   integer x.
in
   x := 100;
   while x > 10 do
     x := x -1;
     write x;
   end;
end

Codul:

  0: data         0       //  Declar ca am o variabila la baza stivei.
  1: ld_int       100   //  PUSH 100, pun in vf stivei valoarea 100
  2: store        0       //  O scot de acolo si o stochez la adresa var. x, adresa 0
  3: ld_var       0      //  Incarc iar in varful stivei valoarea var. de la adresa 0 
  4: ld_int        10    //  Peste ea, incarc in varful stivei valoarea constanta 10
  5: gt              0      //  Compar daca valoarea variabilei e mai mare ca a const.
                               // Practic scot ultimele 2 valori din stiva si le compar.
                               // Pun rezultatul tot in stiva.
  6: jmp_false   14   //  Iau val din varful stivei, daca e un zero, false, sar la stop
  7: ld_var        0     //  Incarc iar in vf strivei valoarea var de la dresa 0
  8: ld_int         1     // Incarc peste ea valoarea constantei 1
  9: sub            0     //  Scot doua valori, scad din cea de jos pe cea de sus
                               // si pun diferenta rezultata tot in stiva.
 10: store         0     //  iau ce gasesc in vf stivei, diferenta si o stochez la adr. 0
                               // Practic, am pus in locatia lui xvaloarea x-1
 11: ld_var        0    // Incarc iar in varful stivei valoarea lui x de la adr. 0
 12: out_int      0     // Scot din stiva o valoare si o afisez.
 13: goto          3     // Reiau bucla de la adresa 3.
 14: halt           0     // cand ajung prin slat aici, stop.

Exemplul 5:
 Fisier: p5.sim

let
    integer n, i, fact.
in
    read n;
    i := 2;
    fact := 1;
    while i < n + 1 do
        fact := fact * i;
        i := i + 1;
    end;
    write fact;
end

Acest program calculeaza n! ca produs al numerelor de la 1 la n.

  0: data         2  // Peste pozitia 0 se aloca si pozitiile 1 si 2 din stiva ca variabile
  1: in_int       0  // Citim valoare avriabilei din pozitia 0, si o stocam acolo
  2: ld_int       2  // Incarcam in stiva constanta 2
  3: store        1  // Si de acolo o luam si o stocam in variabila 1, de la adresa 1
  4: ld_int       1  // Incarcam in stiva constanta 1
  5: store        2  // O stocam la adresa 2, a celei de-a treia variabile
                          // A doua variabila va fi contorul care creste de la 1 la n.
                          // A treia variabila va fi produsul, de aceea il initializez cu 1
                          // Prima variabila e numarul n al carui factorial il calculez. 
  6: ld_var       1 // Incarc in stiva valoarea  variabilei de la adresa 1, contorul
  7: ld_var       0 // Adaug in stiva, deasupra, valoarea primei variabile, maximul
  8: ld_int       1  // Pun in stiva, deasupra , o constanta 1
  9: add          0  // Adun acel maxim, n, cu constanta 1, obtin n+1
 10: lt             0  // Compar i, contorul, var a II-a cu suma n+1 (var I + o unitate)
                          // Comparatia este practic intre i si n+1 din sursa, cu semn <

 11: jmp_false   21 // Daca este fals, adica i > n+1 sar la adresa 21, dupa bucla
                              // Aici intru in bucla.
 12: ld_var       2    // Incarc in vf stivaei valoarea variabilei a 3-a, produsul fact
 13: ld_var       1    // Incarc in vf stivaei valoarea variabilei a 2-a, contorul i
 14: mult         0    // Scot ultiemele doua valori si le inmultesc
 15: store        2    // Stochez la adresa variabilei a treia , noul produs
 16: ld_var       1   //  Pun in stiva copia contorului de la adresa 1
 17: ld_int       1    //  Peste ea pun in stiva constanta 1
 18: add          0    //  Fac suma ultiemlor 2 valori din stiva, am contorul+1
 19: store        1    //  Il stochez la adresa contorului
 20: goto         6    //  Reiau bucla de la adresa 6
 21: ld_var       2   // Incarc in varful stivei valoare variabilei de la adresa 2
 22: out_int      0   // Scot valoare din vf stivei si o afisez.
 23: halt           0   // Stop.


Exercitiul 6:
 Fisier: p6.sim

 0: data         2
  1: in_int       0
  2: in_int       1
  3: ld_var       0
  4: ld_var       1
  5: add          0
  6: ld_int       2
  7: div          0
  8: store        2
  9: ld_var       2
 10: out_int      0
 11: halt         0

Intrebare de control:

Ce calculeaza codul de mai sus:
- Suma unor numere
- Produsul unor numere
- Media unor numere, trunchiata la un intreg
- maximul unor numere

Comentati codul rand cu rand !

Exercitiul 7:
 Fisier: p7.sim

  0: data         0
  1: ld_int       1
  2: jmp_false   7
  3: in_int       0
  4: ld_var       0
  5: out_int      0
  6: goto         1
  7: halt         0


Intrebare de control:

Ce calculeaza codul de mai sus:
- citiri repetate intr-o bucla
- scrieri repetate intr-o bucla
- citire si scriere repetate intr-o bucla
- maximul a doua numere

Pauza !

Atentie: Antrenati-va la acest gen de exercitii imediat ce terminati compilatorul.

Intrucat modul de generare a acestor coduri de catre compilator este oarecum obscur il vom explica in saptamanile care urmeaza.









Niciun comentariu:

Trimiteți un comentariu