L.09Partea 2 / Calculatorul
Cuprins

Programul stocat

Instrucțiunile unei mașini de calcul sunt numere, iar numerele pot locui pașnic în memorie. Dacă memoria găzduiește laolaltă instrucțiunile și datele, calculatorul încetează să mai fie o unealtă cu un singur scop și devine o mașină universală. Aceasta este ideea genială care desparte calculatorul modern de toate uneltele inventate vreodată de omenire.

Termeni: program stocat limbaj de asamblare asamblor compilator scara abstracțiilor

O singură memorie

Înainte de nașterea calculatoarelor moderne, mașinile de calcul aveau „programul” turnat direct în cabluri și întrerupătoare fizice. Pentru a schimba sarcina unui colos precum ENIAC — de exemplu, pentru a trece de la calculul traiectoriei unui proiectil la prognoza vremii —, o echipă întreagă de ingineri trebuia să deconecteze sute de cabluri groase, să le rearanjeze pe panouri uriașe și să rotească manual sute de comutatoare, o trudă manuală care dura zile întregi. Pe atunci, programul nu era un text care se tasta, ci o schelărie fizică ce trebuia reclădită la fiecare utilizare.

Marea cotitură s-a produs în 1945, odată cu faimosul raport al matematicianului John von Neumann despre proiectul mașinii EDVAC. Ideea programului stocat este de o simplitate dezarmantă: de ce să tratăm comenzile ca pe niște cablaje fixe, când le putem scrie ca simple numere și le putem așeza în aceeași memorie comună în care ținem și datele de calcul? Odată adoptat acest principiu, reconfigurarea mașinii nu mai cere clești și fire, ci doar rescrierea unor octeți în căsuțele de memorie — o operațiune pe care procesorul o poate desăvârși singur într-o clipită.

Consecința acestei unificări depășește cu mult simpla comoditate tehnică; este o revoluție filozofică. Un ciocan rămâne veșnic un ciocan; un strung nu poate fi decât un strung. Dar un calculator cu program stocat nu are o identitate bătută în cuie. Dacă îi încarci în memorie regulile șahului, devine un maestru șahist; dacă îi încarci un registru contabil, devine un contabil neobosit; dacă îi încarci un sintetizator de sunet, devine un instrument muzical. Este primul obiect din istoria civilizației umane a cărui natură intimă este tocmai aceea de a nu avea o natură fixă: el devine orice mașină îi dictează programul stocat în memoria sa.

Același număr, trei citiri

Dacă aruncăm o privire într-un cip de memorie, un octet nu vine însoțit de o etichetă care să spună ce reprezintă. Opt biți de siliciu sunt doar opt tranzistoare aflate sub tensiune sau nu. Același șir de opt biți poate fi privit ca un număr întreg, ca o instrucțiune de adunare, ca o literă dintr-un roman, ca o nuanță de culoare pe ecran sau ca o notă muzicală dintr-un cântec. Înțelesul nu zace prizonier în interiorul octetului; înțelesul depinde în întregime de ochiul care îl citește și de contextul în care este chemat.

Opt octeți, citiți în trei feluri deodată

Când contorul de program (PC) se oprește la o adresă, procesorul tratează orbește octetul de acolo ca pe o instrucțiune de executat. Când o operație de adunare citește aceeași adresă, ea tratează octetul ca pe un număr de socotit. În memoria însăși nu se schimbă absolut nimic! De aceea, dacă un program se rătăcește din greșeală și începe să citească o fotografie ca și cum ar fi o listă de instrucțiuni, procesorul va încerca cu toată seriozitatea să execute pixelii imaginii, interpretând culorile ca ordine de calcul până când se va bloca într-o eroare.

În figura interactivă de mai sus, literele respectă convenția pe care am stabilit-o în prima parte a cursului: primii cinci biți aleg un caracter dintr-un alfabet de 32 de semne, în timp ce primii trei biți — care la o instrucțiune reprezintă codul operației — rămân invizibili pentru text.

Programe care scriu programe

Iată o concluzie spectaculoasă a arhitecturii von Neumann: dacă programele sunt doar șiruri de numere, iar calculatoarele sunt experte în prelucrarea numerelor, înseamnă că un calculator poate prelucra, genera și modifica alte programe! Această buclă reflexivă — programe care construiesc alte programe — reprezintă motorul secret care a permis dezvoltarea întregii lumi digitale moderne.

Nimeni nu mai programează astăzi tastând șiruri chinuitoare de 0 și 1. Primul pas de eliberare a fost crearea unui text cu prescurtări omenești ușor de reținut (de pildă PUNE, ADUNA, SARI). Acest text poartă numele de limbaj de asamblare, iar programul care îl parcurge și îl traduce literă cu literă în codul binar al mașinii se numește asamblor. Traducerea este directă și riguroasă: fiecărui rând scris de om îi corespunde cu precizie de ceasornic un octet binar înțeles de procesor.

Scrie instrucțiuni cu nume; numerele ies singure

ce a arătat

—

Dar ascensiunea nu se oprește la asamblor. Un pas mai sus găsim compilatorul: un program mult mai sofisticat, capabil să citească limbaje de nivel înalt (precum Python, C sau JavaScript), unde scriem concepte matematice elegante, condiții logice și formule naturale. Compilatorul descompune aceste idei umane abstracte și le traduce în mii de mici instrucțiuni binare pentru mașină. Iar compilatorul este el însuși un program scris odinioară de un alt compilator, clădind o scară vertiginoasă de inteligență tehnică.

Un program își poate scrie propriile instrucțiuni

Fiindcă instrucțiunile împart aceeași memorie vie cu datele, nimic nu împiedică un program să calculeze o valoare și să o salveze chiar peste propriile sale linii de cod viitoare, modificându-și comportamentul din mers! În zorii informaticii, această tehnică a „codului automodificator” era folosită intens pentru a economisi memoria infimă a acelor vremuri: ca să parcurgi o listă lungă, programul își modifica la fiecare iterație adresa scrisă în propria instrucțiune de citire.

În sistemele moderne, practica este privită cu maximă prudență din două motive pragmatice. În primul rând, procesoarele de azi anticipează pașii viitori și preîncarcă instrucțiunile într-un depozit ultrarapid (cache); dacă programul rescrie brusc memoria din urmă, tot depozitul trebuie aruncat la gunoi, ceea ce distruge performanța. În al doilea rând, capacitatea unui program de a-și rescrie propriul cod este visul oricărui virus informatic. Din acest motiv, sistemele de operare moderne separă strict zonele de memorie, interzicând scrierea în spațiul rezervat instrucțiunilor.

Totuși, spiritul acestei idei trăiește triumfător în altă haină: compilatoarele „Just-In-Time” (JIT) care dau viață browserelor web contemporane analizează codul JavaScript în timp ce navigăm pe internet, generează instrucțiuni de mașină proaspete chiar în memorie și le execută pe loc la viteze uluitoare.

Scara

Priviți în urmă la traseul pe care l-am parcurs în această a doua parte a cursului: am înălțat o scară impresionantă de nouă trepte conceptuale. Fiecare treaptă este clădită în întregime pe umerii celei de dedesubt, dar are darul minunat de a ascunde complet complexitatea inferioară. Inginerul care scrie un algoritm nu este nevoit să se gândească la tranzistoare, iar cel care proiectează sumatorul nu are nevoie să știe ce program va rula pe el peste zece ani. Această separare în straturi protectoare poartă numele de abstracție — și este singurul motiv pentru care mintea omenească poate stăpâni sisteme alcătuite din zeci de miliarde de piese.

De jos în sus; apasă pe orice treaptă
Fiecare treaptă e construită din treapta de sub ea și nu are nevoie de nimic de mai jos.

Scara continuă să se înalțe mult peste marginile acestei lecții: peste limbajele de asamblare s-au clădit compilatoare, peste ele sisteme de operare, rețele planetare și platforme uriașe de calcul distribuit. O piramidă gigantică de idei, la a cărei bază modestă se află, la fel de liniștit și ascultător ca în prima zi, un simplu comutator care lasă sau nu un curent electric să treacă.

Mașina pe care am desăvârșit-o până aici este o minune a logicii deterministe: este ascultătoare, rapidă și nu greșește niciodată dacă rețeta este corectă. Însă întreaga ei forță depinde de o condiție uriașă: ca un om inteligent să fi scris în prealabil, pas cu pas, algoritmul necesar. Dar ce ne facem atunci când ne lovim de probleme pe care orice copil le rezolvă într-o fracțiune de secundă, dar pentru care niciun matematician nu poate așterne o rețetă mecanică — cum ar fi recunoașterea chipului mamei într-o fotografie sau înțelegerea unei glume? Înainte de a trece la această mare enigmă a inteligenței artificiale, trebuie să lămurim ultimul mare concept al lumii clasice: ce este, de fapt, un algoritm.