Sunteți pe pagina 1din 31

© galbeanu

ARHITECTURA
SISTEMELOR DE CALCUL
Grigore ALBEANU
© galbeanu

4. Calculatorul MMIX
„ 4.1. Instrucţiunile calculatorului MMIX
„ 4.2. Programarea calculatorului MMIX
„ 4.3. Exerciţii

http://www-cs-faculty.stanford.edu/~knuth/mmix.html

http://www-cs-faculty.stanford.edu/~knuth/index.html
© galbeanu
Curs (Video) de MMIX de la Stanford
http://scpd.stanford.edu/scpd/students/Dam_ui/pages/ArchivedVideoList56K.asp?Include=musings

„ http://scpd.stanford.edu/scpd/students/Video/embed.asp
?Stream=http://proedvid.stanford.edu/seminars/knuth/9
90209/990209-knuth-
56.asf&Course=musings&HomePage=&ChatURL=

„ http://scpd.stanford.edu/scpd/students/Video/embed.asp
?Stream=http://proedvid.stanford.edu/seminars/knuth/0
30399/030399-knuth-
100.asf&Course=musings&HomePage=&ChatURL=

In plus: http://technetcast.ddj.com/tnc_program.html?program_id=71
© galbeanu

Introducere in MMIX
„ Procesorul MMIX (arhitecură RISC) a fost propus de D. Knuth[1] (1999). Are 264 celule de
memorie (a câte un octet), 28 (= 256) registre cu rol general şi 25 (= 32) registre speciale. Fiecare
registru stochează 64 de biţi de date.
„ Celule de memorie sunt notate cu M[0], M[1], ..., M[264-1], registrele generale sunt notate $0,
$1, ..., $255, iar registrele speciale (tabelul 4.1) se numesc rA, rB, ..., rZ, rBB, rTT, rWW, rXX,
rYY şi rZZ.
„ Accesul la memorie poate fi realizat la nivel de byte, wyde, tetrabyte şi octabyte (a se revedea
secţiunea 1.3), folosind notaţiile M, M2, M4 şi M8: M2[2k] = M2[2k+1] = M[2k]M[2k+1];
M4[4k] = M4[4k+1] = M4[4k+2] =M4[4k+3] = M[4k]M[4k+1]M[4k+2]M[4k+3], respectiv
M8[8k] = M8[8k+1] = ... M8[8k+7] = M[8k]M[8k+1] ... M[8k+7], unde k parcurge intervalul
discret de la 0 la cea mai mare valoare admisă impusă de indicele folosit (exerciţiu).
„ Pentru uniformitate convenim să notăm M1[k] = M[k], oricare k în domeniul permis. Dacă k ≥
264 atunci considerăm M[k] ≡ M[k mod 264].
„ Fie x o secvenţă de biţi. Notăm prin s(x) întregul cu semn corespunzător secvenţei x, în
reprezentarea cu complement faţă de doi. Pentru întregi fără semn, se notează cu u(x) numărul
natural corespunzător secvenţei x. Considerăm ca o adresă de memorie A este un întreg fără
semn şi se evaluează întotdeauna modula 264. Vom face distincţie între notaţia $k (registrul
general cu indexul k) şi numărul natural k.
„
[1] D. Knuth (1999), MMIXware. Lecture Notes in Computer Science, 1750, Springer Verlag.
© galbeanu

Registrele procesorului MMIX (1)

Exista diferente
intre cursurile

! video (1999) si
versiunea finala
(2004) a cartii
© galbeanu

Registrele procesorului MMIX (2)


© galbeanu

Structura instructiunilor MMIX


O instrucţiune MMIX este stocată pe 32 de biţi interpretaţi
(un tetrabyte), fiecare dintre cei patru bytes având
semnificaţie separat sau pe baza unei transformări, în funcţie
de operaţia la care se referă. Cei patru bytes sunt denumiţi
convenţional: OP (codul operaţiei sau opcode), X, Y, Z
(operanzi consideraţi întregi fără semn). Când instrucţiunea
are numai doi operanzi, unul este X, iar celălalt este valoarea
desemnată de YZ. Când este un singur operand atunci acesta
este valoarea desemnată de XYZ.

OP X Y Z OP XYZ

OP X YZ
© galbeanu

Clase de instructiuni
Calculatorul MMIX dispune de următoarele
seturi de instrucţiuni:

•încărcare şi stocare (tabelul 4.2)


•operaţii aritmetice (tabelul 4.3)
•instrucţiuni condiţionale (tabelul 4.4)
•operaţii la nivel de bit/octet (tabelul 4.5)
•instrucţiuni imediate (tabelul 4.6)
•instrucţiuni de salt (tabelul 4.7)
•operaţii în virgulă mobilă/fixă (tabelul 4.8)
•instrucţiuni avansate (tabelul 4.9)
© galbeanu

Instructiuni de incarcare si stocare (1)


Instrucţiunile de încărcare folosesc mnemonice
LoaD cu sau fără semn pentru bytes, wydes,
tetrabytes and octabytes. Când un byte, wyde
sau tetrabyte cu semn este convertit într-un
octabyte cu semn atunci bitul de semn este
extins la toate poziţiile din stânga.
Similar, instrucţiunile de stocare folosesc
mnemonice Store (tabelul 4.2). Dacă $Y şi $Z
sunt utilizaţi în formarea adresei atunci A ←
(u($Y) + u($Z)) mod 264.

% Copiere de la StdIn la StdOut, fara


% verificarea erorilor
LOC Data_Segment
GREG @
ArgR OCTA Buf,2 ; Caracter cu caracter
ArgW OCTA Buf,1
Buf LOC @+2

LOC #100
Main LDA $255,ArgR
TRAP 0,Fgets,StdIn
BN $255,Gata
LDA $255,ArgW
TRAP 0,Fwrite,StdOut
JMP Main
Gata TRAP 0,0,Halt
© galbeanu
Instructiuni de incarcare si stocare (2)
© galbeanu

Instructiuni aritmetice (1)


Main NEG $1,1
STCO 1,$1,1
CMPU $1,$1,1
STB $1,$1,$1
LDOU $1,$1,$1
INCH $1,1
16ADDU $1,$1,$1
MULU $1,$1,$1
PUT rA,1
STW $1,$1,1
SADD $1,$1,1
FLOT $1,$1
PUT rB,$1
XOR $1,$1,1
PBOD $1,@-4*1
NOR $1,$1,$1
SR $1,$1,1
SRU $1,$1,1
Instructiuni aritmetice (2) © galbeanu

Main NEG $1,1


STCO 1,$1,1
CMPU $1,$1,1
STB $1,$1,$1
LDOU $1,$1,$1
INCH $1,1
16ADDU $1,$1,$1
MULU $1,$1,$1
PUT rA,1
STW $1,$1,1
SADD $1,$1,1
FLOT $1,$1
PUT rB,$1
XOR $1,$1,1
PBOD $1,@-4*1
NOR $1,$1,$1
SR $1,$1,1
SRU $1,$1,1
© galbeanu
Instructiuni aritmetice: Asamblare / Dezasamblare
F:\USH-2007\MMIX>mmixal number2.mms
F:\USH-2007\MMIX>mmix1 -i number2.mmo
mmix> (fffffffffffffffc: fb0000ff (UNSAVE)) privileged instruction! 0 instructions, 0 mems, 0 oops; 0 good guesses, 0 bad
(now at location #0000000000000000)
mmix> 1. 0000000000000000: 35010001 (NEGI) rL=2, $1=l[240] = 0 - 1 = -1 1 instruction, 0 mems, 1 oop; 0 good guesses, 0 bad
(now at location #0000000000000004)
mmix> 1. 0000000000000004: b5010101 (STCOI) M8[#ffffffffffffffff+1] = 1 2 instructions, 1 mem, 2 oops; 0 good guesses, 0 bad
(now at location #0000000000000008)
mmix> 1. 0000000000000008: 33010101 (CMPUI) $1=l[240] = #ffffffffffffffff cmp 1 = 1 3 instructions, 1 mem, 3 oops; 0 good guesses, 0 bad
(now at location #000000000000000c)
mmix> 1. 000000000000000c: a0010101 (STB) M1[#1+#1] = 1, M8[#0]=#10000000001 4 instructions, 2 mems, 4 oops; 0 good guesses, 0 bad
(now at location #0000000000000010)
mmix> 1. 0000000000000010: 8e010101 (LDOU) $1=l[240] = M8[#1+#1] = #10000000001 5 instructions, 3 mems, 5 oops; 0 good guesses, 0
bad
(now at location #0000000000000014)
mmix> 1. 0000000000000014: e4010001 (INCH) $1=l[240] = #10000000001 + #1000000000000 = #1010000000001
6 instructions, 3 mems, 6 oops; 0 good guesses, 0 bad
(now at location #0000000000000018)
mmix> 1. 0000000000000018: 2e010101 (16ADDU) $1=l[240] = #1010000000001 <<4+#1010000000001 = #11110000000011
7 instructions, 3 mems, 7 oops; 0 good guesses, 0 bad
(now at location #000000000000001c)
mmix> 1. 000000000000001c: 1a010101 (MULU) $1=l[240] = #11110000000011 * #11110000000011 = #244420000000121,
rH=#12343210000
8 instructions, 3 mems, 17 oops; 0 good guesses, 0 bad
(now at location #0000000000000020)
mmix> 1. 0000000000000020: f7150001 (PUTI) rA = 1 = #1 9 instructions, 3 mems, 18 oops; 0 good guesses, 0 bad
(now at location #0000000000000024)
mmix> 1. 0000000000000024: a5010101 (STWI) M2[#244420000000121+1] = 163328054259613985,
M8[#244420000000120]=#12100000000, rA=#00041
10 instructions, 4 mems, 19 oops; 0 good guesses, 0 bad
(now at location #0000000000000028)
mmix>
Instructiuni conditionale (1) © galbeanu
© galbeanu

Instructiuni conditionale (2)


Operaţii la nivel de © galbeanu

bit/octet/wyde/tetrabyte/octabyte/matrice
Conţinutul unui registru este negativ dacă bitul său cel mai din stânga este 1 (bitul de semn) şi este impar dacă bitul său cel
mai din dreapta este 1.
Mnemonicele care au C ca prim caracter modifică conţinutul registrului $X prin copiere numai dacă este îndeplinită condiţia,
iar cel care au Z ca prefix modifică întotdeauna conţinutul (fie prin copiere, fie prin iniţializare cu zero).
Operaţiile la nivel de bit/octet au numeroase aplicaţii şi presupun organizarea şirului de biţi ca un tablou liniar/bidimensional
a câte 64 de componente. În cazul bidimensional este vorba de o matrice booleana 8x8, cu liniile de sus în jos reprezentând
octeţii şirului de biţi de la stânga la dreapta.
Dacă operaţiile la nivel de bit sunt utile în analiza semnalelor, realizarea sistemelor de operare etc., operaţiile la nivel de octet
pot fi întâlnite în procesarea textelor şi grafica pe calculator, pentru a menţiona doar câteva domenii.
Dacă x şi y sunt valori de tip byte/wyde/tetrabyte sau octabyte, notăm prin xTy = max(0, x-y)
diferenţa saturată dintre x şi y. La nivel de bit vor fi folosite notaţiile and, or, xor şi not utilizate asupra algebrei Boole B =
({0, 1}, or, and, not).
Dacă x este un octabyte atunci v(x) reprezintă tabloul unidimensional cu biţii lui x, b(x) tabloul unidimensional cu datele de
tip byte, w(x) tabloul unidimensional cu datele de tip wyde, t(x) tabloul unidimensional cu datele de tip tetrabyte, o(x)
valoarea de tip octabyte, m(x) reprezintă matricea formată cu biţii lui x, iar mT(x) este transpusa matricei m(x).
Operaţiile mor şi mxor între matricele booleene A = (aij)1≤i≤m,1≤j≤n şi B = (bjk)1≤j≤n,1≤k≤p conduc la matricele C = A mor B şi D
= A mxor B, cu elemente
cik = (ai1 and b1k) or (ai2 and b2k) or ... or ( ain and bnk),
respectiv
dik = (ai1 and b1k) xor (ai2 and b2k) xor ... xor ( ain and bnk),
unde 1 ≤ i ≤ m şi 1 ≤ k ≤ p.
Toate instrucţiunile descrise mai jos admit şi forma simplificată în care în loc de $Z se foloseşte Z.
Tabelul 4.6 prezintă instrucţiunile ce utilizează constante imediate, dar pentru care unul dintre operanzi este de forma YZ.
Operaţii la nivel de © galbeanu
bit/octet/wyde/tetrabyte/octabyte/matrice
Instructiuni imediate © galbeanu
© galbeanu
Instructiuni de salt / ramificare
Deoarece pentru a rezolva probleme cu ajutorul
calculatorului este nevoie de înlănţuirea etapelor
de rezolvare, de ramificarea fluxului în funcţie de
anumite evenimente şi de repetarea unor secvenţe
de operaţii, orice procesor trebuie să dispună de
mecanisme de direcţionare a controlului.
Tabelul 4.7 descrie instrucţiunile de salt şi
ramificare puse la dispoziţie de procesorul MMIX.
Acestea constituie baza oricărei structuri de nivel
înalt de tip if, while, etc.
Pentru instrucţiunile BN, BZ, BP, BOD, BNN,
BNZ, BNP, BEV şi variantele de tip probabilist
(prefixate prin P), adresa relativă AR se formează
numai cu doi octeţi. Spunem că astfel de salturi
sunt la mică distanţă de punctul curent, spre
deoebire de JMP a cărui adresă relativă de salt este
formată cu ajutorul a trei octeţi.
Se recomandă utilizarea ramificărilor de tip
probabilist ori de câte ori programatorul ştie că
probabilitatea apariţiei unei ramificări depăşeste
0.5. Aceasta corespunde tendinţei actuale de
proiectare a procesoarelor care pot anticipa
salturile. Instrucţiunea GO are şi varianta de tip
imediat, iar celelalte instrucţiuni pot executa saltul
şi înapoi (având sufixul B şi codul incrementat).
© galbeanu
Instructiuni de
calcul in virgula
mobila (IEEE 754)
MMIX permite şi reprezentarea
în virgulă mobilă, în format
scurt, cu 32 de biţi, dintre care
8 pentru obţinerea exponentului
şi 23 de biţi pentru mantisă.
Reprezentarea numerelor cu
virgulă fixă presupune o poziţie
fixă a virgulei. MMIX dispune
de instrucţiuni de conversie
între reprezentările "virgulă
fixă" şi "virgulă mobilă scurtă."
Instructiuni avansate (1) © galbeanu

În categoria instrucţiunilor
avansate includem instrucţiunile
pentru apel de subrutine
(proceduri / funcţii), instrucţiunile
pentru tratarea întreruperilor (eng.
traps) şi devierilor (eng. trips),
instrucţiunile relative la registrele
speciale precum şi instrucţiunile
pentru procesare ultrarapidă.
Instrucţiunile din tabelele de mai
sus având sufixul [I] admit şi
modul imediat, iar cele cu sufixul
[B] specifică modul de operare
back.
Trip – deviere – tratata de
catre programul utilizatorului;
Trap – intrerupere – tratata
de catre sistemul de operare;
SAVe / UNSAVE – salveaza
/reface starea procesului curent.
Instructiuni avansate (2) © galbeanu
© galbeanu

MMIXAL (1)
Programele sursă MMIX (fişier text cu extensia .mms) constituite din declaraţii şi
instrucţiuni, trebuie asamblate folosind programul mmixal care produce un fişier obiect (cu
extensia .mmo). Interpretarea codului obiect se va realiza folosind simulatorul MMIX.
Programul poate admite argumente în linia de comandă (similar limbajelor C, C++, Java),
numărul argumentelor se va stoca în $0, iar adresa de început a şirului de argumente (primul
fiind numele programlui) este plasată în $1.
Instrucţiunile unui program MMIX încep întotdeauna de la locaţia simbolică
Main.
Programele MMIX conţin simboluri (secvenţe de litere şi cifre care încep obligatoriu cu
literă), constante (zecimale – baza 10, hexazecimale – baza 16 – încep cu #), caracter (între
apostrofuri), şiruri de caractere încadrate de ghilimele), expresii şi instrucţiuni. Unele
simboluri sunt predefinite. Există elemente primare (simboluri, constante, @, expresie
încadrată de paranteze, operator unar urmat de element primar) şi termeni (unul sau mai
multe elemente primare separate prin operatori binari puternici: *, /, //, %, <<m >>, &).
Expresiile sunt formate cu operatori binari slabi: +, -, |, ^.
© galbeanu

MMIXAL (2)
O instrucţiune are trei câmpuri: zona etichetei (spaţiu sau simbol), zona operaţiei OP (conform tabelelor de mai sus,
sau o pseudo-operaţie MMIXAL), zona expresilor (separate prin virgulă) şi eventual zona comentariu. Comentariile
de tip linie încep cu %, ; sau //, iar cele de tip bloc sunt delimitate de /* şi */.
Exemplul 4.1. Programul de mai jos afişează la mediul de ieşire (StdOut) mesajul compus dintr-un şir introdus în
linia de comandă, spaţiu, şi BRAVO. Observaţi că #a este caracterul ASCII de trecere la linie nouă, iar #0 este
terminatorul de şir.
argv IS $1
LOC #100
Main LDOU $255,argv, 0 //Incarcă octa
TRAP 0, Fputs, StdOut //fara semn si TRAP
GETA $255, String
TRAP 0, Fputs, StdOut
TRAP 0, Halt,0
String BYTE " BRAVO", #a,

Procesul de asamblare decurge în trei paşi astfel: locaţia curentă este aliniată la multiplu de 8 (OP = OCTA), 4 (OP =
TETRA sau operaţie MMIX), 2 (OP =WYDE); se defineşte simbolul @ ca fiind eticheta, în afara cazului în care OP =
IS sau OP = GREG. Dacă OP este o operaţie MMIX atunci zona operaţie şi zona expresie definesc un tetrabyte, iar @
este incrementat cu 4. Daca OP este o pseudo-operaţie MMIXAL atunci se analizează operaţia şi se realizează
următoarele acţiuni:
a) Dacă OP = IS atunci simbolul din zona etichetei devine echivalent cu valoarea unicei expresii prezente în zona
expresiilor.
b) Daca OP = LOC atunci locaţia curentă @ devine valoarea unicei expresii, care trebuie să aibă o valoare pură.
c) Dacă OP = BYTE, WYDE, TETRA sau OCTA, atunci în zona expresiilor sunt prezente mai multe expresii stocabile
pe 1, 2, 4 sau 8 octeţi începând cu adresa indicată simbolic în zona etichetei.
d) Daca OP = GREG, atunci unica expresie evaluată la o valoare pură x se atribuie acelui registru global (în mod read
only) al cărui cel mai mare număr nealocat încă este asociat simbolului din zona etichetă.
MMIXAL (3)
Un comportament important al oricărui asamblor
© galbeanu
este cel relativ la operaţiile de intrare-ieşire. Dacă
considerăm stilul limbajului C pentru operaţiile
Fopen, Fclose, Fread, Fgets (extins şi la Fgetws),
Fwrite, Fputs (extins şi la Fputws), Fseek, şi Ftell,
aceste pot fi simulate conform tabelului 4.10.
Relativ la operaţiile de intrare-ieşire, următoarele
simboluri sunt predefinite în MMIXAL: Fopen = 1,
Fclose = 2, Fread = 3, Fgets = 4, Fgetws = 5, Fwrite
= 6, Fputs = 7, Fputws = 8, Fseek = 9, Ftell = 10,
TextRead = 0, TextWrite = 1, BinaryRead = 2,
BinaryWrite = 3, BinaryReadWrite = 4.
argc IS $0
argv IS $1
LOC #100
Main SUB argc,argc,2
PBNN argc,2F
JMP 9F
Blank BYTE ' ',0
1H GETA $255,Blank
TRAP 0,Fputs,StdOut
SUB argc,argc,1
ADD argv,argv,8
2H LDOU $255,argv,8
TRAP 0,Fputs,StdOut
PBNZ argc,1B
9H GETA $255,NewLine
TRAP 0,Fputs,StdOut
TRAP 0,Halt,0
NewLine BYTE #a,0
Lucrul cu MMIXAL © galbeanu
Presupunem că textul de mai sus este introdus folosind un editor de texte (de exemplu Edit sau NotePad) şi este salvat sub forma fibo.mms.
Prin comanda:
mmixal -l fibo.lst -o fibo.mmo fibo.mms
se vor crea fişierele: fibo.lst (list-ing) şi fibo.mmo (fişierul obiect).
Fişierul fibo.lst are următorul conţinut (cititorul este invitat să observe codurile instrucţiunilor şi modul cum este asamblat programul):
($254) sp GREG
($253) fp GREG Symbol table:
($252) n GREG Fib = #0000000000000100 (6)
($252) fn IS n Main = #000000000000014c (1)
LOC #100 fn = $252 (5)
($251=#00000000 GREG @ fp = $253 (3)
00000100) n = $252 (4)
...100: 3101fc02 Fib CMP $1,n,2 sp = $254 (2)
...104: 5001xxxx PBN $1,1F
...108: adfdfe00 STO fp,sp,0
...10c: c1fdfe00 SET fp,sp
...110: e7fe0020 INCL sp,8*4
...114: ad00fd08 STO $0,fp,8 Fişierul fibo.mmo va fi transmis simulatorului mmix
...118: adfcfd10 STO n,fp,16 prin comanda:
...11c: 25fcfc01 SUB n,n,1
...120: 9f00fb00 GO $0,Fib
mmix <opţiuni> fibo
...124: adfcfd18 STO fn,fp,24 // F[n-1] unde opţiunile descriu modul delucru permis.
...128: 8dfcfd10 LDO n,fp,16 Câteva opţiuni sunt:
...12c: 25fcfc02 SUB n,n,2 -t, respective -e pentru executarea
...130: 9f00fb00 GO $0,Fib instrucţiunii de un număr de ori
...134: 8d00fd18 LDO $0,fp,24
...138: 22fcfc00 ADDU fn,fn,$0
sau întâlnirea unei excepţii,
...13c: 8d00fd08 LDO $0,fp,8 -l pentru listarea liniilor sursă în timpul
...140: c1fefd00 SET sp,fp executării instrucţiunilor,
...144: 8dfdfe00 LDO fp,sp,0 -s pentru furnizarea de statistici, -q pentru oprire,
...148: 9f000000 1H GO $0,$0,0 -i pentru a intra în mod interactiv,
...14c: e0fe2000 Main SETH sp,Data_Segment>>48
...150: e3fc0005 SET n,5
-f pentru a specifica fişierul utilizat pentru
...154: 9f00fb00 GO $0,Fib a simula introducerea datelor şi
-D pentru a produce un fişier utilizabil de

către alte simulatoare .


© galbeanu

Simulatorul MMIX
© galbeanu
Executarea pas cu pas a programului hello.mms
mmix>
(00000000000000fc: fb0000ff (UNSAVE)) #6000000000000080: rG=255, ...,
rL=2
0 instructions, 0 mems, 0 oops; 0 good guesses, 0 bad
(now at location #0000000000000100)
mmix>
1. 0000000000000100:
8fff0100 (LDOUI) $255=g[255] = M8[#4000000000000008] = #4000000000000018
1 instruction, 1 mem, 1 oop; 0 good guesses, 0 bad
(now at location #0000000000000104)
argv IS $1 mmix>
LOC #100 1. 0000000000000104: 00000701 (TRAP) $255 = Fputs(StdOut,#4000000000000018) = 9
2 instructions, 1 mem, 6 oops; 0 good guesses, 0 bad
Main LDOU $255,argv,0 (now at location #0000000000000108)
TRAP 0,Fputs,StdOut mmix>
GETA $255,String 1. 0000000000000108: f4ff0003 (GETA) $255=g[255] = #114
3 instructions, 1 mem, 7 oops; 0 good guesses, 0 bad
TRAP 0,Fputs,StdOut (now at location #000000000000010c)
TRAP 0,Halt,0 mmix>
String BYTE ", world",#a,0 1. 000000000000010c: 00000701 (TRAP) $255 = Fputs(StdOut,#114) = 8
4 instructions, 1 mem, 12 oops; 0 good guesses, 0 bad
(now at location #0000000000000110)
mmix>
1. 0000000000000110: 00000000 (TRAP) Halt(0)
5 instructions, 1 mem, 17 oops; 0 good guesses, 0 bad
(halted at location #0000000000000110)
mmix>
5 instructions, 1 mem, 17 oops; 0 good guesses, 0 bad
(halted at location #0000000000000110)
F:\USH-2007\MMIX>
© galbeanu

MMIX Tracer

http://www.arno-fleck.de/mmix/english.htm
© galbeanu

Compilator de Pascal care genereaza cod MMIX


© galbeanu

http://www.pspu.ru/personal/eremin/emmi/pas/pas.html

Bibliografie
„ Grigore ALBEANU, Arhitectura sistemelor
de calcul, Editura FRM, Bucuresti, 2007.
„ D. Knuth, Arta programarii calculatoarelor,
MMIX – un calculator RISC pentru noul
mileniu, Editura TEORA, 2005.

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