Documente noi - cercetari, esee, comentariu, compunere, document
Documente categorii

Moduri de adresare si secventa programului masina

Moduri de adresare si secventa programului masina

Acest capitol va trata modul in care sunt executate programele intr-un computer. Se vor prezenta modurile in care secventele de instructiuni sunt aduse si executate din memorie in procesor pentru a realiza un anumit scop. Majoritatea instructiunilor specifica operatii care trebuie executate asupra datelor localizate fie in memorie, fie in registri generali ai procesorului. Ne vom referii la astfel de date, fie ca sunt de tip numeric sau caracter, ca si operanzi ai acestor instructiuni.

Tehnicile care se folosesc in mod normal pentru adresarea memoriei principale si a registrilor procesorului se vor discuta in general, folosind insa adresarea ce este implementata in calculatoarele IBM-PC. Acest computer este folosit si pentru a ilustra formatul instructiunilor, rularea programului, intrarile si iesirile din subrutine, ca si manipularea stivei. Se vor descrie mai multe programe la nivel de limbaj de asamblare pentru a ilustra principiile de baza exemplificate.




1 Locatii de memorie, adrese, si codificarea informatiei.

Memoria principala consta dintr-un numar foarte mare de celule de memorare, fiecare celula putand stoca un singur bit ce poate avea valoarea 0 sau 1. Deoarece 1 bit reprezinta o cantitate foarte mica de informatie, bitii sunt tratati foarte rar in mod individual.



Cea mai folosita metoda este cea in care biti sunt tratati in grupuri de dimensiune fixa. In acest scop memoria este organizata in asa fel incat un grup de n biti pot fi scrisi sau cititi printr-o singura operatie de baza. Fiecare grup de n biti este referit ca un cuvant de informatie, iar n este numit lungimea cuvantului.

Pentru a accesa memoria in scopul citirii sau scrierii unui singur cuvant de informatie, este necesar sa existe nume distincte (adrese) pentru fiecare locatie de cuvant. Se obisnuieste sa se foloseasca numere de la 0 la M-1 ca si adrese ale locatiilor succesive dintr-o memorie ce contine M cuvinte, asa cum este prezentat in figura 1.

Continutul locatiilor de memorie reprezinta fie instructiuni fie operanzi. Acestia din urma pot fi numere sau caractere. Figura 2a ilustreaza cel mai direct mod in care un numar intreg de 16 biti poate fi reprezentat intr-o locatie de memorie.



Bitul cel mai din stanga, b15, este numit bit de semn. El este 0 pentru numere pozitive si 1 pentru numere negative. Magnitudinea numarului este determinata de bitii b14 pana la b0 cu ajutorul formulei:

magnitudinea = b14 * 214+.+b1*21+b0*20

Cea mai mare magnitudine in acest mod de reprezentare este 215-1=32767.

Aceasta reprezentare poarta numele de reprezentarea cu semn si magnitudine. Mai exista si alte doua reprezentari binare ale numerelor care se utilizeaza frecvent. Acestea sunt reprezentarea in complement fata de 1 si in complement fata de In amandoua din aceste moduri, reprezentarea numerele pozitive este aceeasi cu cea prezentata anterior. Diferenta dintre cele trei metode este in modul in care sunt reprezentate numerele negative. Cu toate acestea, in toate cele trei scheme, bitul cel mai din stanga, in cazul de fata b15, este bitul de semn, si interpretarea lui este aceeasi: 0 pentru numerele pozitive si 1 pentru cele negative.

Alegerea modului de reprezentare are o influenta directa asupra facilitatii implementarii operatiilor aritmetice de catre circuitele logice din interiorul procesorului. Ca si observatie, complementul fata de 2 este implementarea cea mai apropiata de facilitatile hardware.

In acest capitol, se va folosi reprezentarea zecimala cu semn si magnitudine pentru exemplele numerice. Desigur ca, in calculator aceste valori sunt reprezentate in modele binare bazate pe una dintre cele trei scheme prezentate mai sus. Singurul detaliu tehnic legat de reprezentarea binara de care este nevoie in acest capitol este faptul ca bitul de semn este intotdeauna cel mai din stanga bit. Acest lucru este valabil pentru orice lungime a cuvantului calculatorului.

In paralel cu numere, computerele mai trebuie sa se poata descurca si cu caractere. Caracterele sunt folosite pentru a reprezenta literele alfabetului, digiti zecimali, semne de punctuatie, etc. Ele sunt reprezentate prin coduri lungi de 6 pana la 8 biti. Figura 2b indica cum pot fi stocate doua caractere ASCII sau EBCDIC intr-un cuvant de 16 biti.

Un cuvant de memorie poate sa contina si codul unei instructiuni. In acest caz o parte a cuvantului specifica operatia care trebuie realizata, iar alta parte specifica adresa operandului. Se obisnuieste sa se foloseasca numele de camp pentru aceste parti. Un exemplu al unui format al unei instructiuni pe 16 biti este prezentat in figura 2c. Campul operatiei fiind pe 4 biti poate sa codifice 24=16 instructiuni distincte, iar campul de adresa de 12 biti poate codifica adrese de la 0 pana la 212-1=4095.

In general nu se poate determina daca o locatie de memorie contine o instructiune sau un operand doar prin simpla examinare a continutului ei, deoarece o anume configuratie de biti poate fi interpretata ca oricare din cele trei configuratii prezentate in figura Informatia aditionala necesara se afla in interiorul procesorului. Interpretarea unui anumit cuvant depinde de starea sau modul operatiei procesorului la momentul accesarii cuvantului din memorie. S-a mentionat in capitolul 1 existenta unui registru numit PC in interiorul procesorului. Toate cuvintele din memorie care sunt indicate de catre PC sunt interpretate ca si instructiuni. Cuvintele de memorie a caror adresa este specificata de catre instructiuni sunt interpretate ca si operanzi. Faptul ca un operand este caracter sau numar este determinat de catre campul operatiei din cadrul unei instructiuni.


1.2  Operatii in memoria principala.

Pentru a executa o instructiune, este necesar ca circuitele de control din procesor sa genereze transferul instructiunii din memorie in procesor. Mai este de asemenea necesar, sa se faca schimbul de operanzi si rezultate intre memorie si procesor. Astfel, in concluzie sunt necesare doua operatii de baza in lucrul cu memoria: Citirea (Read) si Scrierea (Write). Operatia de citire transfera continutul unei locatii specifice de memorie in procesor. Continutul locatiei de memorie ramane neschimbat in urma unei astfel de operatii. Pentru a initia o operatie de citire, procesorul trebuie sa trimita adresa locatiei dorite catre memorie.

Operatia de scriere transfera un cuvant de informatie de la procesor intr-o locatie de memorie. La fel ca si la operatia de citire, procesorul trebuie sa trimita adresa locatiei dorite catre memorie.


3 Formatul instructiunilor si secventa lor.

Un program tipic implica un anumit numar de pasi diferiti din punct de vedere functional ce trebuie parcursi. Este evident faptul ca trebuie sa existe diferite clase de instructiuni disponibile. O prima clasificare grosiera a instructiunilor este urmatoarea:

Transfer de date intre memorie si registri procesorului



Operatii aritmetice si logice asupra datelor

Secventa si controlul programului

Transfere de tip I/O

Se va incepe prezentarea posibilelor formate pentru instructiunile din primele doua clase. Operatia de adunarea doua numere este una din operatiile fundamentale ale oricarui calculator. Se va folosi o instructiune Add pentru a se ilustra unele variante de formate de instructiune. Din punctul de vedere al programatorului, cea mai simpla forma de adunare este C A + B, unde A, B si C sunt numele a trei variabile. Se va presupune ca aceste trei variabile se afla in locatii diferite de memorie. Se va asocia numele variabilelor A, B, C cu adresele acestor locatii. Expresia anterioara va primi acum urmatoarea semnificatie: operanzii din locatiile de memorie A si B sunt cititi din memorie si transferati in registri procesorului unde vor fi adunati de catre ALU, dupa care rezultatul sumei va fi memorat in locatia C.

Daca intregul proces trebuie specificat de catre o singura instructiune, va fi nevoie de trei campuri de adrese, care sa specifice pe A, B, C, impreuna cu campul operatiei care sa indice faptul ca avem de-a face cu o adunare. Aceasta instructiune cu trei adrese se poate reprezenta in mod simbolic in felul urmator:

Add             C,B,A

Problema care apare in cazul acestei reprezentari este faptul ca necesita includerea a trei campuri de adresa in cadrul instructiunii ceea ce inseamna un numar foarte mare de biti pe cuvant. Daca A, B, C sunt adrese arbitrare in spatiul de memorie de la 0 la 2m-1, atunci sunt necesari m biti pentru a specifica fiecare adresa. Astfel, instructiunea trebuie sa contina 3m biti in scopuri de adresare, in plus fata de bitii necesari pentru a specifica tipul operatiei ce trebuie executata.

O alta metoda de a realiza calculul este folosirea unui camp de adresa implicit. Pentru aceasta se folosesc doar doua adrese. Daca ele se folosesc intr-o instructiune Add pentru a specifica doi operanzi A si B, va trebui sa existe o adresa implicita la care sa se puna rezultatul sumei. Multe calculatoare au instructiuni Add cu doua adrese care intorc rezultatul la adresa unuia dintre cei doi operanzi., astfel ca acel operand va fi distrus. Instructiunea:

Add                    B,A

realizeaza urmatoarea operatie B A + B. O singura instructiune Add cu doua adrese nu poate sa rezolve problema pusa , adica aceea de a aduna continutul locatiilor A si B si de a pune rezultatul in locatia C. Totusi, problema poate fi rezolvata cu folosind o alta instructiune cu doua adrese care sa mute continutul unei locatii de memorie in alta. Aceasta instructiune este:

Move                 C,B

si realizeaza operatia C B. Astfel, operatia C A + B poate fi efectuata prin executia urmatoarelor doua instructiuni:

Move                 C,B

Add                    C,A

Urmatoarea posibilitate ce se poate lua in considerare este folosirea unei instructiuni cu o singura adresa. Desigur ca, datorita faptului ca operatia de adunare implica doi operanzi, trebuie sa se faca o presupunere implicita asupra locului unde se afla unul dintre operanzi cat si asupra locului unde se va pune rezultatul. Un registru general al procesorului, numit de obicei acumulator, poate fi folosit in acest scop. Instructiunea:

Add                    A

semnifica adunarea locatiei de memorie A cu continutul acumulatorului si depunerea rezultatului in acumulator. Se mai introduc urmatoarele doua instructiuni cu o singura adresa:

Load                   A

Store    A

Executia instructiunii Load copiaza continutul locatiei de memorie A in acumulator, iar executia instructiunii Store copiaza continutul acumulatorului in locatia de memorie A. Operatia C A + B poate fi realizata prin executia urmatoarei secvente de instructiuni:

Load                   A

Add                    B

Store    C

Majoritatea calculatoarelor au un anumit numar de registri generali, fiecare putand fi folosit ca si acumulator. Daca exista 8 sau 16 registri, atunci 3 respectiv 4 biti vor fi necesari intr-un camp al unei instructiuni pentru a adresa registrul care sa faca parte din operatie. Acest numar de biti este considerabil mai mic decat cel necesar pentru a memora o adresa a unei locatii de memorie. Fie Ri un registru general al procesorului. Atunci instructiunile:

Load     Ri,A

Store    A,Ri

Add                    Ri,A

reprezinta generalizarea instructiunilor Load, Store si Add anterioare ale cazului cu un singur registru acumulator. In particular, executia instructiunii

Load     Ri,A

copiaza continutul locatiei A in registrul Ri. Executia instructiunii:

Store    A,Ri

copiaza continutul registrului Ri in locatia de memorie A, iar instructiunea:

Add                    Ri,A

aduna continutul locatiei de memorie A la continutul registrului Ri si pune rezultatul in Ri. Acest tip de instructiune, in care o adresa se refera la o locatie de memorie, iar cealalta mai scurta se refera intotdeauna la un registru al procesorului, are un format intermediar intre cel al instructiunilor cu o singura adresa si cel al instructiunilor cu doua adrese, fiind deseori numit format cu o adresa si jumatate. Calculatoarele care au mai multi registri de procesor, permit de asemenea si operatii intre registri. Astfel:

Add                    Ri,Rj

aduna continutul lui Rj cu continutul lui Ri iar rezultatul este depus in Ri.

Si calculatoarele care folosesc instructiuni cu doua campuri de adrese contin un anumit numar de registri generali. De obicei, registri imbunatatesc eficienta programului reducand numarul de accese la memorie necesare in cazul particular in care un operand este folosit in mod repetat intr-un calcul. In computerele care au formatul instructiunilor cu doua campuri de adresa, exista de obicei un mod in care se poate specifica un registru in loc de o locatie de memorie in oricare din cele doua campuri de adresa. Astfel instructiunile:

Move                 Ri,A

Move                 A,Ri

realizeaza acelasi rezultat ca si instructiunile:

Load     Ri,A

Store    A,Ri

realizate in formatul cu un camp si jumatate discutat mai inainte.



S-a discutat pana acum despre instructiuni cu unul sau cu doua campuri de adresa. Este posibil sa se foloseasca instructiuni unde locatiile tuturor operanzilor sunt definite implicit. Ele depind de metoda folosita pentru stocarea operanzilor in ceea ce se numeste stiva. Astfel de instructiuni sunt uneori numite instructiuni cu zero adrese.


3.1 Executia unei instructiuni si secvente liniare de instructiuni.

In subcapitolul precedent s-a discutat formatul instructiunilor, exemplificandu-le pe adunarea C A + B. Un program posibil care sa realizeze aceasta functie, asa cum apare el in memoria unui calculator cu instructiuni in format cu doua adrese si care contine si un anumit numar de registri generali este prezentat in figura 3. Cele patru instructiuni ale programului se afla in locatii succesive de memorie, pornind de la locatia i in ordinea in care vor fi executate.

In continuare se va urmari modul de executie al acestui program. Procesorul contine registrul numit PC care va memoreaza adresa instructiunii care va fi executata. Pentru a incepe executia programului, adresa primei lui instructiuni ( i in cazul acesta ) trebuie incarcata in PC. Circuitele de control ale procesorului automat incep sa citeasca instructiunile si sa le execute, una cate una, si in ordinea crescatoare a adreselor. Pe masura ce fiecare instructiune este executata, PC-ul este actualizat sa indice urmatoarea instructiune. Acesta este numita secventa liniara de cod. Executia instructiunii Halt va opri citirea automata de instructiuni.

Executia unei anumite instructiuni consta dintr-o procedura cu doua faze. In prima faza, numita faza citirii instructiunii, instructiunea este adusa din memorie de la adresa care se afla in PC. Aceasta instructiune este plasata in registrul instructiunii IR aflat in procesor. La inceputul fazei a doua, numita faza executarii instructiunii, campul operatie al instructiunii din IR este decodificat pentru a se determina tipul operatiei ce trebuie executata, dupa care operatia specificata este executata de catre procesor. Acest lucru poate sa presupuna citirea de operanzi din memorie in procesor, efectuarea de operatii aritmetice si logice, si stocarea rezultatului in memorie. Undeva de-a lungul acestei proceduri in doua faze continutul PC-ului este actualizat pentru a indica instructiunea urmatoare ce va trebui executata. In cazul de mai sus continutul PC-ului este incrementat cu 1, astfel ca in momentul in care faza executarii unei instructiuni este terminata, PC-ul va contine adresa instructiunii urmatoare, si va urma o noua faza de citire a instructiunii.





3.2 Ramificatii.

Se va considera in continuare un program care sa adune o lista de n numere. Generalizand programul din figura 3 se va ajunge la programul din figura 4a .






Adresele locatiilor de memorie ce contin cele n numere sunt simbolic notate cu NUM1, NUM2, ., NUMn, iar suma rezultata este plasata in locatia de memorie notata cu SUM. In loc sa se utilizeze o lista lunga de instructiuni Add, este posibil sa se plaseze o singura instructiune Add intr-o bucla de program care sa se execute de un numar de ori dorit. Acest lucru este ilustrat in figura 4b.

Ideea fundamentala din buclele de program este executarea unei secvente liniare de program in mod repetat. Numarul de repetitii, care in mod evident depinde de natura problemei, trebuie controlat cu ajutorul unor instructiuni suplimentare. In exemplul de mai sus, registrul R1 este folosit ca si numarator. El este incarcat initial cu valoarea n din locatia de memorie N. Instructiunea

Decrement                    R1

decrementeaza continutul lui R1 cu o unitate de fiecare data cand se parcurge bucla.

Se introduce conceptul unei instructiuni de ramificare pentru a realiza un salt la prima instructiune a buclei:

Branch>0          LOOPSTART

Efectul unei astfel de instructiuni este urmatorul: ramificarea are loc catre locatia indicata de instructiune (in cazul acesta LOOPSTART) daca conditia specificata este indeplinita; altfel, se continua secventa liniara de instructiuni. Daca se determina faptul ca va avea loc o ramificare, PC-ul este incarcat cu adresa indicata de catre instructiune; altfel PC-ul este incrementat in modul obisnuit.

Conditiile de ramificare sunt de obicei legate de rezultatul unei operatii aritmetice sau logice. In exemplul prezentat, conditia dorita este faptul ca rezultatul celei mai recente operatii aritmetice executate este mai mare ca zero. Deoarece instructiunea de decrementare precede instructiunea de salt conditionat, aceasta inseamna ca un salt la adresa LOOPSTART va avea loc atata timp cat continutul lui R1 ramane mai mare decat zero. Dupa ce bucla a fost executata de n ori, R1 va fi decrement la zero, iar saltul la LOOPSTART nu va mai avea loc; in schimb, instructiunea urmatoare va copia rezultatul final continut in R0 in locatia de memorie SUM si executia programului se va opri datorita instructiunii Halt.

Capacitatea de a testa conditii, si de a alege in urma lor dintr-un set de alternative pentru a continua calculul, are mult mai multe aplicatii decat doar controlul unei bucle. Aceasta capacitate este reflectata in seturile de instructiuni ale tuturor calculatoarelor si reprezinta unul din conceptele fundamentale ale programarii.



Pana acum s-au luat in considerare doar instructiuni in care adresele operanzilor sunt date explicit in cadrul instructiunii. Acest mecanism simplu de adresare presupune ca campul de adresa al instructiunii Add sa fie modificat in cadrul blocului nespecificat din figura 4b. Este posibil sa se adune 1 la campul de adresa al instructiunii Add. Aceasta este necesar daca o singura instructiune Add trebuie sa faca referire la intrari succesive dintr-o lista de numere. Aceasta modificare directa a campului de adrese al instructiunii nu este o practica prea fericita in programare. Ea va genera dificultati in depanarea si initializarea programelor. Problema se rezolva prin introducerea de diferite scheme pentru specificarea adreselor operanzilor. Aceste scheme se numesc moduri de adresare. Aceste moduri de adresare au rolul de a flexibiliza modul de specificare a adresei operanzilor. Cu ajutorul lor este posibil ca o anumita instructiune sa se refere la operanzi diferiti cand este executata de un numar repetat de ori; instructiunea in sine ne fiind modificata.


2.4 Moduri de adresare.

In subcapitolul precedent s-a folosit doar un singur mod de adresare a operanzilor, numit modul absolut. Se va definii acest mod in felul urmator:

Modul absolut reprezinta modul in care adresa locatiei operandului este parte explicita a instructiunii.

S-au folosit doua versiuni ale acestui mod in exemplele prezentate. Acestea sunt modul absolut de memorie, in care operanzii se afla in memorie, si modul registru, in care operandul este unul din registri procesorului. Pe langa termenul de absolut se mai foloseste si termenul direct pentru acest mod de adresare.

In continuare se vor indica si alte moduri de adresare importante, si se va specifica modul lor de folosire in programul din figura 4b.

Modul imediat contine operandul in mod explicit in cadrul instructiunii. Acest mod este foarte folositor in cazul in care se doreste specificarea de date si adrese constante in cadrul unui program. De exemplu, instructiunea

Move                 R0,200(imediat)

incarca registrul R0 cu valoarea 200.

In acest subcapitol se vor afisa modurile de adresare diferite de cel absolut ca indici pentru o mai buna exemplificare a lor. Modul absolut va fi scris in continuare prin specificarea adresei operandului. Desigur ca, la nivelul codificarii instructiunii, informatia referitoare la modul de adresare va trebui specificata prin cateva pozitii de biti din cadrul instructiunii.

In definitia urmatoarelor doua moduri cat si in discutiile aferente se va face referire la adresa locatiei de memorie care contine operandul ca adresa efectiva.

Modul indirect presupune faptul ca adresa efectiva a operandului se afla in registrul sau in locatia de memorie a carei adresa apare in cadrul instructiunii. Figura 5 exemplifica adresarea indirecta.

Executia instructiunii Add din figura 5a incepe prin citirea continutului locatiei A din memorie. Aceasta valoare, B, este adresa efectiva, care este utilizata ulterior pentru citirea operandului dorit din memorie.







In final, operandul este adunat la continutul registrului R0. In mod similar, in figura 5b operandul este accesat indirect prin registrul Rj.         

Modul de adresare indirect poate fi folosit in accesarea succesiva a numerelor dintr-o lista, care sunt folosite ca si operanzi intr-o operatie de adunare, asa cum se arata in figura 5c. Registrul R2 este folosit ca si pointer (indicator) la numerele din lista, adica operanzii vor fi accesati indirect prin R Primele doua instructiuni din bucla implementeaza blocul nespecificat din figura 4b. Faza de initializare a programului reseteaza continutul lui R0 la 0, copiaza valoare numaratorului n in R1, si plaseaza valoarea adresei NUM1 in R2, folosind modul de adresare imediat. La prima trecere prin bucla, instructiunea Add citeste operandul de la locatia NUM1 si il aduna la R0. Instructiunea de incrementare aduna 1 la continutul pointerului din R2, care astfel va contine adresa NUM2 in momentul in care instructiunea Add se va executa in cel de-al doilea pas prin bucla.

Urmatorul mod de adresare asigura si el o metoda de adresare flexibila ce poate fi folosita in exemplul cu adunarea numerelor.

Modul indexat obtine adresa efectiva a operandului prin adunarea unei valori index la adresa data in instructiune. Valoarea de indexare, sau simplu indexul, se afla de obicei intr-un registru al procesorului. In anumite calculatoare exista un registru dedicat acestui scop, el numindu-se registrul index si este parte implicita la toate operatiile ce presupun indexarea. La procesoarele din familia Intel exista doi astfel de registri numiti SI si DI. Figura 6a prezinta generarea adresei efective folosind modul indexat. In majoritatea calculatoarelor oricare din registri generali poate contine indexul. Intr-un astfel de caz, registrul trebuie specificat explicit in cadrul instructiunii. In cadrul procesului de generare al adresei efective, nici registrul index si nici adresa din instructiune nu se vor modifica.

Figura 6b ilustreaza utilizarea adresarii indexate in bucla de adunare folosita anterior. Registrul R2 este folosit ca index, si este initializat cu valoarea 0. El va fi incrementat cu 1 dupa fiecare instructiune Add de fiecare data cand se parcurge bucla. Astfel, la prima parcurgere, adresa efectiva generata de instructiunea Add va fi NUM1. Pe parcursul pasilor urmatori, adresa efectiva va fi NUM1+1, NUM1+2, ., etc, deoarece R2 este incrementat cu 1 la fiecare executie a buclei. Marele avantaj al adresarii indexate este faptul ca indexul poate fi modificat arbitrar nu doar incrementat cu 1.

Modurile de adresare definite in acest capitol au fost exemplificate prin exemple simple, putand astfel introduce conceptele de baza fara a fi necesara intrarea in detalii specifice unui configuratii hardware anume.