Să se implementeze un program în limbaj de asamblare care simulează calculator cu următoarele operaţii posibile:
+
(adunare)*
(înmulţire)<<
(shiftare la stânga)>>
(shiftare la dreapta)Numerele sunt cu semn şi pot depăşii dimensiunea unui operand cu care poate lucra arhitectura folosită la laborator (i386).
Implementarea efectivă trebuie să înceapă iniţial din fişierul calc.asm.
Execuţia programului începe cu un apel la convert_to_native(). Această funcţie are următoarea semnătură:
a_str şi b_str reprezintă string-urile date ca input pentru a simboliza operanzii A şi B. Voi va trebui să îi convertiţi pe aceştia la o altă reprezentare la adresele a şi b. Primii 4 bytes vor fi semnul numărului, urmat de lungimea numărului reprezentat tot pe 4 bytes şi o serie lungime bytes care reprezintă efectiv numărul în little endian.
/* Exemple: */ /* Dacă a_str ar fi “-2FC23”, >>a<< ar fi reprezentat în felul următor: */ unsigned char actual_number[] = [0x23, 0xFC, 0x02]; unsigned int *a_int = a; unsigned char *a_char = a_int + 2; a_int[0] = 0xFFFFFFFF; /* all ones */ a_int[1] = 3; memcpy(a_char, actual_number, length); /* Dacă a_str ar fi “2FC23”, >>a<< ar fi reprezentat în felul următor: */ unsigned char actual_number[] = [0x23, 0xFC, 0x02]; unsigned int *a_int = a; unsigned char *a_char = a_int + 2; a_int[0] = 0x00000000; /* all zeros */ a_int[1] = 3; memcpy(a_char, actual_number, length);
Reprezentarea efectivă şi calculele se vor face pe o reprezentare pozitivă (actual_number, din exemplul anterior, va fi pozitiv mereu după cum reiese şi din exemplu).
Părţile de length şi sign vor fi gata setate înainte să vă fie apelată funcţia convert_to_native(). Dacă nu se respectă şi foloseşte această reprezentare la calculele efective, punctajul pe temă va fi anul complet.
Când conversia a fost terminată, vi se va apela funcţia do_operation(), care are următoarea semnătură:
În această funcţie trebuie să implementaţi efectiv execuţia operaţilor. operation este un string cu operatorul primit din linie de comandă.
Rezultatul trebuie depus în a. Atât a, cât şi b, au spaţiu suficient pentru execuţia calculelor. Urmăriţi implementarea lui allocate_vectors() dacă vreţi să înțelegeți mai în detaliu ce înseamnă “suficient”.
Avem următoarele precizări în privinţa algoritmilor folosiţi pentru operaţii:
Ultima funcţie pe care va trebui să o implementaţi se numeşte print_number() şi are următoarea semnătură:
Această funcţie primeşte un număr pe care trebuie să-l afişeze într-un format similar celui de input: caracterul -, dacă numărul este negativ, urmat de reprezentarea în hex big endian fără padding.
./calc $A op $B
op trebuie să fie între apostrofe, pentru că bash-ul încearcă să îl interpreteze şi expandeze înainte să ajungă la programul vostru. De exemplu:
Exemplu input şi output:
arcade@Arcade-PC:~/workspace/iocla_tema2 > ./calc -234FF '+' 2343 FF3402 ; memory dump la reprezentarea operandului A 4323 ; memory dump la reprezentarea operandului B BC1102 ; memory dump la reprezentarea rezultatului -211BC ; afişarea “normală” a rezultatului, asemănătoare inputului
Temele vor trebui încărcate pe platforma vmchecker (în secțiunea IOCLA) și vor fi testate automat. Arhiva încărcată va fi o arhivă .zip
care trebuie să conțină:
Makefile
, main.c
, macro.c
și orice fișier de tip .asm
şi/sau *.inc
README
ce conține descrierea implementării
Makefile
pentru crearea arhivei care va fi încărcată pe vmchecker folosind comanda
make pack
Punctajul final acordat pe o temă este compus din:
Temele care nu trec de procesul de asamblare (build) nu vor fi luate în considerare.
Arhiva ce conține checker-ul, testele și fișierele de la care puteți începe implementarea este aici.