Tema 3 - POLI Cat Invasion

  • Actualizări:
    • 11.05.2022 - postare temă

Enunț

Sursee și prietenii ei au reușit, cu ajutorul vostru, să cucerească Facultatea de Automatică și Calculatoare. Noua lor misiune este să conducă tot campusul și să traverseze Dambovița ca să ajungă în Regie. Noii membrii ai echiei, Luna și Mushu, vor să apeleze la cunoștintele voastre în limbaj de asamblare.

Task-ul 1 - Noduri (25p)

Sursee dorește să găseasca drumul până în Rectorat ca să vadă si ea vestitul OZN. Ea știe prin ce clădiri trebuie să treacă dar lista a fost amestecată. Ajutați-o să ordoneze lista prin conectarea elementelor care inițial erau alăturate.

Trebuie să implementați funcția cu semnătura struct node* sort(int n, struct node* node); din fișierul task1.asm, care “leagă” nodurile din listă în ordine crescătoare. Funcția primește numărul de noduri și adresa vectorului și întoarce adresa primului nod din lista rezultată.

Structura unui nod este:

  struct node {
      int val;
      struct node* next;
  };

și, inițial, câmpul next este setat la NULL.

Antetul funcției este:

 struct node* sort(int n, struct node* node); 

Semnificația argumentelor este:

  • n numărul de noduri
  • node adresa vectorului ce trebuie sortat

Funcția returneaza adresa primului nod din lista ordonată.

Precizări:

  • n >= 1
  • secvența conține numere consecutive distincte începand cu 1 (ex: 1 2 3 …)
  • structura vectorulului NU trebuie modificată (interschimbarea nodurilor este interzisă)
  • sortarea trebuie facută in-place
  • este permisă folosirea unor structuri auxiliare, atâta timp cât, nodurile listei rezultate sunt cele din vectorul inițial
  • NU este permisă folosirea funcției qsort din libc

Exemplu

Inițial:

Adresă Valoare Next
0x32 2 NULL
0x3A 1 NULL
0x42 3 NULL

Apelul funcției sort întoarce 0x3A (adresa nodului cu valoarea 1) și vectorul va arăta astfel:

Adresă Valoare Next
0x32 2 0x42
0x3A 1 0x32
0x42 3 NULL

Pentru implementarea sortării vă puteți inspira din Selection Sort

Sursee va saluta :))

Task-ul 2 - Mașina cu Stivă (25p)

Mushu trebuie să ajungă la Leu, dar este împiedicat de portarul cel rău de la Precis. Acesta îi pune în față o Mașină cu stivă , adică o mașina care știe să folosească doar stiva, prin instrucțiuni de tip push și pop, pentru a lucra cu memoria. Provocarea lui Mushu este să implementeze 2 funcții pe această mașină:

CMMMC

Prima funcție este int cmmmc(int a, int b), care calculează cel mai mic multiplu comun a 2 numere, date ca parametru.

Se garantează că rezultatul înmulțirii lui a și b încape pe 4 bytes

Antetul funcției este:

 int cmmmc(int a, int b); 

Cele două argumente sunt numerele cărora trebuie să le aflăm cel mai mic multiplu comun.

Funcția returneaza cel mai mic multiplu comun al celor două numere.

Paranteze

A doua funcție este int par(int str_length, char *str), care verifică daca o secvență de paranteze este corectă. Aceasta primește un șir care contine doar paranteze rotunde si lungimea șirului, și intoarce 1, dacă secvența e corectă, sau 0, dacă secvența e greșită.

Antetul funcției este:

 int par(int str_length, char *str); 

Semnificația argumentelor este:

  • str_length numărul de noduri
  • str adresa șirului de paranteze

Funcția returneaza 0 daca parantezarea nu este corectă și 1 daca parantezarea e corectă.

Exemplu
  • Pentru secvența ((()())(())), rezultatul va fi 1
  • Pentru secvența (())((, rezultatul va fi 0

Nu aveti voie sa folositi intructiunile din familia mov (mov, cmov, stos, lods, etc), leave si enter. Toate operatiile de transfer din si in memorie / registre trebuie realizate folosind push si pop

Lui Mushu nu ii plac temele

Task-ul 3 - Sortare de cuvinte (25p)

Luna a mers împreună cu Sursee până în Rectorat dar acum trebuie sa ajungă în Regie. Luna are de completat un rebus folosind cuvintele unui text și vă roagă să o ajutați prin a sorta cuvintele în funcție de lungime ca să îi fie mai ușor.

Pentru acest task veți avea de separat un text în cuvinte dupa niște delimitatori și, după aceea, să sortați aceste cuvinte folosind funcția qsort. Sortarea se va face întâi după lungimea cuvintelor și în cazul egalitații se va sorta lexicografic.

Va trebui să implementați 2 funcții cu semnăturile void get_words(char *s, char **words, int number_of_words); și void sort(char **words, int number_of_words, int size); din fișierul task3.asm.

Scopul task-ului acesta este să folosiți funcții din biblioteca standard C. Dacă există ceva în libc ce va poate ajuta, folosiți cu incredere!

Antetul primei funcții este:

 void get_words(char *s, char **words, int number_of_words); 

Semnificația argumentelor este:

  • s textul din care extragem cuvintele
  • words vectorul de string-uri în care se salvează cuvintele găsite
  • number_of_words numărul de cuvinte

Atenție, funcția nu returnează nimic, cuvintele se salveaza in vectorul words!

Antetul celei de-a doua funcții este:

 void sort(char **words, int number_of_words, int size); 

Semnificația argumentelor este:

  • words vectorul de cuvinte ce trebuie sortat
  • number_of_words numărul de cuvinte
  • size dimensiunea unui cuvânt

Atenție, funcția nu returnează nimic, sortarea se face in-place!

Precizări

  • lungimea textului este mai mica decat 1000;
  • vectorul de cuvinte va avea maxim 100 de cuvine a 100 de caractere fiecare;
  • delimitatorii pe care trebuie sa ii luati in calcul sunt: spatiu( ), virgula(,), punct(.), endline (\n)
  • nu aveti voie sa folositi alta metoda de sortare in afara de qsort. In cazul in care veti folosi alta metoda punctajul pe acest task se va pierde;

Exemplu

  number_of_words: 9
  s: "Ana are 27 de mere, si 32 de pere."
  dupa apelul get_words: words = ["Ana", "are", "27", "de", "mere", "si", "32", "de", "pere"]
  dupa apelul sort: words = ["27", "32", "de", "de", "si", "Ana", "are", "mere", "pere"]

Pentru mai multe informatii despre qsort puteti accesa linkul: qsort

Luna va felicita ca ati ajuns pana aici

Task-ul 4 - CPUID (15p)

Acum că pisicile au cucerit toată Universitatea Politehnică, vor să se relaxeze aflând câteva detalii despre procesoare.

cpuid este o instrucțiune specială a procesoarelor care folosesc arhitectura x86, sau derivate, care permite aflarea unor informații despre procesorul pe care se execută această instrucțiune.

Instrucțiunea cpuid nu primește parametri, ci se execută în funcție de conținutul registrului eax și, în anumite situații, a registrului ecx. Informațiile date ca răspuns sunt stocate în registrele eax, ebx, ecx, edx. Semnificația rezultatelor este documentată în specificația producătorilor de procesoare x86, Intel si AMD.

Vi se cere sa aflați, folosind cpuid, următoarele informații despre procesorul vostru:

  • Manufacturer ID-ul (4p)
  • dacă procesorul folosește APIC (1p)
  • dacă este suportata instrucțiunea RDRAND (1p)
  • în cazul în care procesorul este de tip Intel, dacă suportă setul de instrucțiuni MPX (2p)
  • în cazul în care procesorul este de tip AMD, dacă suportă setul de instrucțiuni SVM (3p)
  • dimensiunea liniei de cache de nivel 2 (4p)
  • dimensiunea cache-ului de nivel 2, pentru un singur nucleu (bonus - 5p)

Implementarea se va realiza în fișierul `task4.asm`.

Precizări

  • Checker-ul va verifica ce tip de procesor este prezent și va verifica output-ul funcțiilor voastre in funcție de prezența componentelor cerute pe sistem (dacă procesorul vostru este Intel și nu are MPX, se va aștepta ca rezultatul pentru MPX sa fie 0)
  • Checker-ul va emula celălalt procesor, cu toate componentele cerute, folosind qemu-i386.
  • Implementarea trebuie să poată verifica și componentele specifice Intel, și cele specifice AMD, în funcție de ce tip de procesor e detectat.
  • Informatii despre cache-ul de nivelul 2 se pot obtine folosind EAX=0x80000006, EAX=0x2 sau EAX=0x04. Folosind EAX=0x80000006 se poate afisa o dimensiune de maxim 512KB. Pentru dimensiuni mai mari, trebuie folosit EAX=0x2, care implica parsarea registrelor EAX, EBX, ECX, EDX, astfel: AL indica e cate ori trebuie apelat CPUID cu EAX=0x2, pentru a obtine date valide. Bit-ul 31 din fiecare registru indica daca contine date valide (valoarea 0) sau nu (valoarea 1). Daca un registru contine date valide, acesta va contine cate o valoare pe un byte, cu o anumita specificatie. Specificatia fiecarui byte poate fi gasita aici , la sectiunea INPUT EAX = 2:.
  • Pentru EAX = 0x4, puteti consulta documentatia Intel.
  • Pentru linia de cache e suficent EAX = 0x80000006

Task-uri bonus

Ca task-uri bonus, aveți de ales din următoarele:

  • Assembly pe 64 de biti (5p)
  • Sintaxa AT&T (10p)
  • Instructiuni vectoriale (15p)
  • Instructiuni speciale: RDRAND, RDTSC (10+p)
  • Apeluri de sistem (10p)
  • Floating point (15p)
  • Altele - vor fi adaugate pe parcurs

Tunetele s-au oprit, au fost inlocuite de lene

Cerințele task-urilor bonus și punctarea lor se pot găsi în fișierele task_*.md, din cadrul folderului fiecarui task.

Trimitere și notare

Temele vor fi incarcate pe platforma de Gitlab a facultatii sau pe platforma Moodle experimentala.

Pentru incarcarea pe Gitlab, va trebui sa faceti un fork al repository-ului temei, pe care veti lucra. Puteti lucra direct pe branch-ul master al fork-ului, sau puteti face un nou branch pe fork, apoi sa creati un Pull Request spre master. In cazul variantei cu Pull Request, puteti cere review unuia dintre responsabilii temei, pentru a se uita pe cod si a va spune daca exista probleme.

Faceti branch-ul pe forkul facut din repository-ul temei. Fork-ul trebuie sa fie privat

In cazul realizarii temei pe Gitlab, fiecare commit va duce la verificarea automata a temei.

Puteti cere review pe cod pana la inceputul ultimei saptamani

Review-ul nu va include si detalii depsre cum trebuie sa implementati cerintele. Va viza, in principal, coding style-ul

A doua optiune este sa folositi checker-ul local, folosind comanda sudo ./local.sh. Asta va va reproduce mediul de testare de pe Gitlab pe masina voastra, si va verifica tema. Apoi, puteti incarca tema pe Moodle, sub forma de arhiva .zip. Tema va fi apoi verificata.

Din folderul temei (tema3/), executand comanda make zip, se va crea arhiva cu structura asteptata de checker. Fisierul README, daca este adaugat, trebuie sa fie scris in Markdown si sa aiba extensia .md

Puteti gasi procesul de rezolvare si incarcare al temelor aici

Punctajul final acordat pe o temă este compus din:

  • punctajul obținut prin testarea automată de pe vmchecker - 90p
  • coding style - 10p
  • bonus - maxim 50p

Punctajul maxim este 150p

Rezultatul rularii checker-ului se poate vedea pe Moodle. Tot acolo va aparea si corectarea facuta de catre asistenti.

Fisierul README.md este optional. Va incurajam sa detaliati implementarile folosind comentarii punctuale in cod (nu comentati fiecare linie, ci blocuri de cod). Scrieti in README daca considerati necesar sa detaliati mai mult implementarea sau daca aveti feedback legat de tema

Coding style-ul constă în:

  • prezența comentariilor în cod
  • scrierea unui cod lizibil
  • indentarea consecventă
  • utilizarea unor nume sugestive pentru label-uri
  • scrierea unor linii de cod/README de maxim 80-100 de caractere

Pentru detalii despre coding style parcurgeți acest document: coding style

Temele care nu trec de procesul de asamblare (build) nu vor fi luate în considerare.

Vă reamintim să parcurgeți atât secțiunea de depunctări cât și regulamentul de realizare a temelor.

Precizări suplimentare

Toate task-urile vor fi realizate in limbajul de asamblare x86 (32 de biti), in afara de cazurile cand se specifica explicit alt limbaj.

FAQ

  • Q: Este permisă utilizarea variabilelor globale?
    • A: Da

Resurse

iocla/teme/tema-3.txt · Last modified: 2022/05/26 10:08 by cristian.vijelie
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0