44 1 716KB
UNIVERSITATEA TEHNICĂ A MOLDOVEI
BAZELE LIMBAJULUI ASSEMBLER
Îndrumar de laborator
Chişinău U.T.M. - 2007
UNIVERSITATEA TEHNICĂ A MOLDOVEI
Facultatea Calculatoare, Informatică şi Microelectronică
Catedra Automatică şi Tehnologii Informaţionale
BAZELE LIMBAJULUI ASSEMBLER
Îndrumar de laborator
Chişinău U.T.M. 2007
1
Acest indrumar de laborator este destinat pentru studentii cu specializarea 2152 „Tehnologii Informaţionale”, la disciplina „Unitati Centrale”. Lucrarea data este dedicată studiului individual şi se adresează studenţilor U.T.M., dar şi pentru toti doritorii de a studia limbajul ASSEMBLER. Alcătuitori:
lector superior Colesnic Victor Magistru T.I. Vladimir Cucu Magistru T.I. Liliana Cucu
Redactor responsabil: conf. univ. dr. Victor Beşliu Recenzent: conf. univ. dr.
Bun de tipar Coli de tipar Tirajul 150 ex.
Formatul hartiei 60x84 1/16 Tipar RISO Hirtie ofset. Comanda nr.
U.T.M., 2007, Chisinau, bd. Ştefan cel Mare şi Sfânt, 168 Secţia de redactare şi Editare a U.T.M. 2068, Chişinău, str. Studenţilor, 9/9.
2
U.T.M., 2007
Cuprins Introducere ..................................................................................... 4 Lucrare de laborator nr. 1 ............................................................ 6 Lucrare de laborator nr. 2 .......................................................... 19 Lucrare de laborator nr. 3 .......................................................... 49 Lucrare de laborator nr. 4 .......................................................... 81 Lucrare de laborator nr. 5 ........................................................ 103 Lucrare de laborator nr. 6 ........................................................ 116 Bibliografie ................................................................................. 134
3
Introducere
Limbajele de asamblare sint singurele care ofera utilizatorului posibilitatea cunoasterii aprofundate a calculatorului împreuna cu sistemul de operare. Din acest motiv, ele sint destinate în special programatorilor de sistem, care lucreaza la proiectarea şi implementarea sistemelor de operare şi programare. Fiind o reflectare directa a limbajului masina şi prin aceasta avand acces direct la functiile sistemului de calcul, limbajul de asamblare permite exploatarea tuturor posibilitatilor oferite de sistem. De asemenea, sistemele moderne de programare au facilitatea interfatarii cu limbajul de asamblare, creîndu-se astfel posibilitatea dezvoltarii de programe eficiente în limbaj de nivel inalt, "modulele critice" fiind implementate în limbaj de asamblare. Autorii prezentei lucrari considera ca pentru exploatarea cu maxim de eficienta a unui sistem de calcul este absolut necesara cunoasterea limbajului de asamblare. în anumite situatii, cum este cazul sistemelor dedicate de tipul microcalculatoarelor utilizate în conducerea proceselor industriale, utilizarea limbajului de asamblare reprezinta unica modalitate de dezvoltare de aplicatii dedicate pentru sistemele respective. De asemenea, pentru exploatarea eficienta a facilitatilor oferite de limbajul de asamblare, cunoasterea limbajului propriu-zis trebuie dublata de cunostinte de hardware, privind arhitectura interna a procesorului, a modurilor de adresare a memoriei interne, a modului în care sint secventiate instructiunile sub forma de cicli masina, etc.
4
Avand în vedere tehnicile specifice de dezvoltare a programelor în limbaj de asamblare, de tipul: programare dirijata de tabele, tehnici de codificare eficienta şi de optimizare a codului, etc., se poate spune ca limbajele de asamblare au facut din munca de programare o adevarata "arta". In acest context se inscrie şi prezentul indrumar de laborator în care se prezintă lucrari legate de limbajul de asamblare Intel 8086/8088, destinat microcalculatoarelor din familia IBM PC. Lucrarea este destinată în primul rînd studenţilor secţiilor de T.I şi calculatoare, dar poate fi folosită de toţi cei care doresc să se iniţieze în munca de programare într-un limbaj de asamblare. În consecinta, problematica prezentata în lucrarile de laborator are ca scop initierea în munca de programare în limbaj de asamblare. Autorii tin de asemenea sa precizeze ca orice sugestii şi propuneri din partea cititorilor sint bine venite. Lucrarea de fata se doreste a fi o lucrare deschisa, problematica prezentata putind fi în mod evident largita în cadrul unei aparitii viitoare.
5
Lucrare de laborator nr. 1 Descrierea pachetului de programe Turbo-Assembler 1.1 Scopul lucrării: Lucrarea urmareste familiarizarea studentilor cu mediul de dezvoltare a programelor scrise în limbaj de asamblare pus la dispozitie de catre produsul Turbo-Assembler al firmei Borland. Se prezinta pe scurt componentele pachetului de programe şi procedura generala de lucru cu exemplificare pe doua clase diferite de programe: în format EXE şi în format COM. 1.2 Modul de lucru: Se vor efectua toate aplicaţiile din lucrare în programul TASM. Se vor preda darile de seama cu rezultatele obţinute. 1.3 Noţiuni teoretice Pachetul de programe Turbo-Assembler pune la dispozitia utilizatorului toate instrumentele necesare pentru dezvoltarea programelor în limbaj de asamblare. Macroasamblorul TASM produce module obiect relocabile din fisiere sursa în limbaj de asamblare. Pentru aceste module obiect se pot edita legaturile cu programul TLINK în scopul crearii de programe executabile sub sistemul de operare DOS. Pachetul cuprinde: 1. macroasamblorul TASM; 2. editorul de legaturi TLINK; 3. bibliotecarul TLIB; 4. depanatorul simbolic TD. 1.3.1 Alegerea tipului de fisier executabil Sint posibile urmatoarele formate de fisiere executabile: EXE - este formatul uzual pentru fisiere executabile sub sistemul de operare DOS. Programele executabile pastrate în acest format pot avea segmente multiple. Este formatul recomandat pentru programe de dimensiuni mari. Extensia lor implicita este .EXE;
6
COM - programele în acest format sint limitate pentru un singur segment, din acest motiv ele nedepasind 64Ko (exceptind cazurile cind nu se specifica segmente). Se recomanda pentru programe mici. Un dezavantaj important este acela ca nu contin informatii despre sursa şi simbolice pentru depanatorul simbolic TD. 1.3.2 Dezvoltarea programelor în limbaj de asamblare Procedura generala de lucru este urmatoarea: 1. Se foloseste un editor de texte pentru crearea sau modificarea modulelor sursa. Prin conventie acestea au extensia implicita .ASM. Ele se pot organiza în diverse moduri. Spre exemplu toate procedurile se pot plasa intr-un modul mai mare sau se pot scinda pe mai multe module; 2. Se utilizeaza programul TASM pentru asamblarea fiecarui modul de program. Se pot utiliza optional fisiere de includere (fisiere ce sint incluse în modulul asamblat doar pe durata asamblarii). Daca apar erori dupa executarea acestui pas se revine la pasul anterior. Pentru fiecare fisier sursa .ASM se creaza în urma asamblarii: a) un fisier obiect cu extensia implicta .OBJ; b) un fisier listing cu extensia implicita .LST (optional); c) un fisier de referinte incrucisate cu extensia implicita .REF (optional). Daca se doreste legarea de module scrise în asamblare cu module scrise intr-un limbaj de nivel inalt, acestea se vor compila în fisiere obiect. 3. Optional se foloseste TLIB pentru plasarea mai multor fisiere obiect intr-un singur fisier biblioteca cu extensia implicita .LIB. Acest lucru se intimpla cind se doreste legarea unor fisiere obiect standard la mai multe programe. De asemenea TLIB poate crea un fisier optional de listare a continutului bibliotecii; 4. Se foloseste TLINK pentru a combina toate fisierele obiect şi modulele biblioteca ce formeaza un program în cadrul unui singur fisier executabil care are implicit extensia .EXE. Optional se poate crea şi o harta de alocare a memoriei, cu extensia implicita .MAP;
7
5. Se poate realiza editarea legaturilor cu optiunea /l pentru crearea (daca este necesara) unui fisier executabil în format binar. Aceasta operatie este necesara pentru programele scrise în format COM (care vor avea extensia .COM) sau pentru fisierele binare. 6. Se depaneaza programul pentru depistarea erorilor de logica. Dintre tehnicile utilizate se amintesc: a) studiul raspunsului programului la diferite seturi de date de intrare; b) studiul fisierelor sursa şi listing; c) utilizarea fisierului listing cu referinte incrucisate; d) utilizarea depanatorului simbolic TD pentru depanare dinamica. 1.3.3 Exemplu de program în format exe
mesaj lmesaj start:
TITLE salut_exe .MODEL SMALL .STACK 100h .DATA DB "Salut!",13,10 EQU $-mesaj .CODE mov ax,@data mov ds,ax mov bx,1 mov cx,lmesaj mov dx,OFFSET mesaj mov ah,40h int 21h mov ax,4C00h int 21h END start
Se remarca urmatoarele: a) Directiva .MODEL este folosita pentru initializarea modelului de memorie. Efectul cumulat al celor doua directive este definirea segmentelor implicite pentru programe de model mic generindu-se directivele ASSUME şi GROUP utilizate de programele de model mic; b) Directiva .STACK defineste o stiva de 256 octeti, suficienta pentru programe mici; 8
c) Directiva .DATA marcheaza inceputul segmentului de date. în cazul nostru acest segment contine o variabila şir de caractere şi lungimea acestuia; d) Eticheta primei instrucţiuni ce urmează directivei .CODE marcheaza inceputul portiunii executabile a programului. Aceeasi eticheta este utilizata dupa directiva END ea definind astfel punctul de unde va incepe executia programului (numit şi punctul de intrare în program); e) Primele doua instructiuni initializeaza registrul ds. Simbolul @data reprezinta numele segmentului creat cu directiva .DATA. Registrul ds va fi intotdeauna initializat pentru fisiere sursa în format EXE; f) Continutul variabilei de tip şir de caractere definita în program se afiseaza pe ecran utilizind functia DOS cu codul 40h. Fisierul "handle" 1 (driver predefinit pentru iesirea standard) este specificat pentru afisarea pe ecran. Sirurile pot fi de asemenea afisate pe ecran cu functia DOS cu codul 09h; g) Functia DOS cu codul 4Ch este utilizata pentru terminarea programului şi iesirea la sistem. Exista şi alte tehnici de iesire la sistem dar aceasta este cea recomandata. 1.3.4 Exemplu de program în format com TITLE salut_com SEGMENT ASSUME cs:_TEXT,ds:_TEXT,ss:_TEXT ORG 100h start: jmp inceput mesaj DB "Salut!",13,10 lmesaj EQU $-mesaj inceput: mov bx,1 mov cx,lmesaj mov dx,OFFSET mesaj mov ah,40h int 21h mov ax,4C00h int 21h _TEXT ENDS END start _TEXT
9
Programele COM difera de programele EXE în urmatoarele puncte: 1) Directiva .MODEL nu poate fi folosita la definirea segmentelor implicite pentru fisiere COM. Totusi definirea segmentelor nu este dificila intrucit este utilizat numai un singur segment. Nu este necesar să se specifice tipurile de combinare, aliniere şi clasa (vezi lucrarea 4) intrucit ele pot avea valorile implicite pentru fisierele COM; 2) Toate registrele segment sint asignate unui acelasi segment prin utilizarea directivei ASSUME. Aceasta indica asmblorului segmentul pe care sa-l asocieze cu fiecare registru segment; 3) Directiva ORG se utilizeaza pentru a indica pornirea asamblarii de la octetul 256 (100h). Astfel se creaza spatiu pentru prefixul segmentului de program (PSP) care este automat incarcat în memorie în momentul executiei; 4) Desi datele programului trebuie incluse în segmentul unic ele nu vor fi executate. Se poate "sari" peste ele cu o instructiune jmp (ca în exemplu) sau se pot plasa datele la sfirsit, dupa punctul în care programul revine la sistem. 1.4 Comenzi necesare dezvoltarii unui program Pentru aflarea liniilor de comanda ale programelor TASM şi TLINK se lanseaza în executie aceste programe fara nici un parametru în linia de comanda. Efectul este afisarea sintaxei liniei de comanda impreuna cu optiunile disponibile. Comenzile uzuale sint: a) pentru asamblarea unui program: TASM nume unde nume este numele fisierului ce contine programul sursa, implicitt cu extensia .ASM; b) pentru asamblarea unui program cu obtinerea fisierului listing: TASM /la nume unde nume este numele fisierului ce contine programul sursa, implicitt cu extensia .ASM; c) pentru asamblarea unui program cu depunerea de informatii simbolice în fisierul obiect rezultat, informatii necesare depanatorului simbolic TD: 10
TASM /zi nume unde nume este numele fisierului ce contine programul sursa, implicit cu extensia .ASM; d) pentru editarea legaturilor unui program: TLINK nume unde nume este numele fisierului obiect rezultat în urma asamblarii, implicit cu extensia .OBJ. Implicit se genereaza şi harta de alocare a memoriei; e) pentru editarea legaturilor unui program cu depunerea de informatii simbolice în fisierul executabil rezultat necesare depanatorului simbolic TD: TLINK /v nume unde nume este numele fisierului obiect rezultat în urma asamblarii cu optiunea /zi, implicit cu extensia .OBJ. Implicit se genereaza şi harta de alocare a memoriei; f) pentru editarea legaturilor unui program în vederea obtinerii unui fisier executabil în format COM: TLINK /t nume unde nume este numele fisierului obiect rezultat în urma asamblarii unui program sursa în format COM; implicit are extensia .OBJ; g) pentru depanarea programului executabil obtinut: TD nume unde nume este numele fisierului executabil rezultat în urma editarii legaturilor, implicit cu extensia .EXE sau .COM. Depanarea cu TD poate fi obisnuita sau simbolica. Depanarea obisnuita presupune ca în momentul depanarii să se cunoasca adresele variabilelor din program impreuna cu segmentele în care se afla aceste variabile. Depanarea simbolica presupune ca în momentul executiei programul depanator sa aiba acces la numele simbolice ale variabilelor din program, depanarea fiind în acest caz mai usor de realizat. Pentru depanarea obisnuita se parcurg urmatorii pasi: a) se asambleaza şi linkediteaza programul; b) se lanseaza TD în executie cu comanda mentionata mai sus. Efectul este aparitia pe ecran a unei ferestre impartita în 5 11
subferestre: subfereastra cu programul, subfereastra de registre, subfereastra de flaguri, subfereastra de stiva şi subfereastra de date. Trecerea dintr-o subfereastra în alta se face apasind tasta TAB; c) se identifica deplasamentele şi adresele de segment ale variabilelor din program pe baza examinarii fisierelui listing si/sau a subferstrei cu programul; d) se vizualizeaza valorile initiale ale variabilelor prin activarea subferestrei de date, apasarea tastelor CTRL-G şi introducerea în casuta de dialog a adresei variabilei ce se vrea examinata sub forma segment:offset; e) se activeaza subfereastra cu programul şi se executa apoi programul pas cu pas (instructiune cu instructiune) apasind tastele F7 sau F8 şi simultan examinind celelalte subferestre; f) la terminarea depanarii se paraseste programul depanator cu Alt-X. Pentru depanarea simbolica se parcurg urmatorii pasi: a) se asambleaza şi se linkediteaza programul cu optiunile de depanare simbolica prezentate mai sus; b) se lanseaza TD în executie cu comanda indicata. Pe ecran apare o fereastra ce contine programul asa cum a fost introdus în fisierul sursa; c) se introduc în fereastra Watches variabilele al caror continut se doreste a fi urmarit în timpul executiei prin apasarea tastelor Ctrl-F7 şi introducerea în casuta de dialog ce apare a numelui acestor variabile; d) eventual se deschide fereastra de registre cu comanda Alt-V R; e) se executa apoi programul pas cu pas (instructiune cu instructiune) apsind tastele F7 sau F8 urmarind fereastra Watches şi fereastra de registre; f) la terminarea depanarii se paraseste programul depanator cu Alt-X. Daca se doreste depanarea programului cu depanatorul DEBUG, se va proceda astfel: a) se lanseaza DEBUG în executie prin tastarea la linia de 12
comanda a numelui acestuia; b) se introduce numele programului care se doreste depanat, ca parametru al comenzii n a depanatorului; c) se incarca programul specificat la punctul anterior cu comanda l a depanatorului; d) se ruleaza apoi programul depanat sub controlul DEBUG vizualizindu-se rezultatele partiale şi valorile curente ale registrelor de lucru în punctele critice ale programului. Pentru comenzile DEBUG impreuna cu un exemplu de depanare vezi anexa 1. 1.5 Citirea fisierelor de listare a asamblarii TASM va crea un fisier de listare a asamblarii fisierului sursa ori de cite ori se da un nume de fisier de listare a asamblarii pe linia de comanda TASM sau se foloseste optiunea de asamblare /l. Fisierul de listare a asamblarii contine atit instructiunile din fisierul sursa cit şi codul obiect (daca exista) generat pentru fiecare instructiune. Listarea prezinta, de asemenea, numele şi valorile tuturor etichetelor, variabilelor şi simbolurilor din fisierul sursa. Asamblorul creeaza tabele pentru macrodefinitii, structuri, inregistrari, segmente, grupuri şi alte simboluri. Aceste tabele sint plasate la sfirsitul fisierului de listare a asamblarii (exceptind cazul în care ele sint suprimate cu optiunea /n). TASM listeaza numai tipurile de simboluri intilnite în program. De exemplu, daca programul nu contine macrodefinitii, în tabloul de simboluri nu va exista o sectiune de macrodefinitii. Toate numele de simboluri vor fi prezentate cu litere mari, exceptind cazul în care sint utilizate optiunile /ml sau /mx pentru a specifica nume ce contin şi litere mici. Asamblorul listeaza codul generat de instructiunile unui fisier sursa. Fiecare linie are sintaxa ce urmeaza: numarlinie deplasament cod instructiune unde: numarlinie - este numarul liniei din listing. Numararea incepe de la prima instructiune din fisierul de listare a asamblarii. Numerele liniilor sint generate numai atunci cind se cere un fisier de referinte 13
incrucisate. Numerele liniilor dintr-un listing nu corespund intotdeauna liniilor din fisierul sursa; deplasament - reprezinta deplasarea de la inceputul segmentului curent pina la codul corespunzator liniei respective; cod - indica valoarea numerica în hexazecimal a codului generat daca acesta valoare este cunoscuta în timpul asamblarii. Daca valoarea este calculata în timpul executiei, TASM indica actiunea necesara pentru calcularea valorii; instructiune - este instructiunea sursa prezentata exact asa cum apare în fisierul sursa, sau asa cum este expandata în urma unei macrosubstitutii. Daca apar erori în timpul asamblarii, fiecare mesaj de eroare va apare chiar sub instructiunea în care a aparut eroarea. în continuare este prezentat un exemplu de linie ce contine o eroare şi mesajul de eroare corespunzator. 11 0005 A1 0000 mov ax,aa **Error** adun.ASM(11) Undefined symbol: AA
Numarul 11 din mesajul de eroare reprezinta linia sursa în care a aparut eroarea. Listingul model prezentat în continuare este realizat prin asamblarea programului din fisierul adun.asm, prezentat mai jos. DATA SEGMENT a DW 8 b DW -3 sum DW ? dif DW ? DATA ENDS CODE SEGMENT ASSUME ds:DATA,cs:CODE start: mov ax,data mov ds,ax mov ax,a add ax,b mov sum,ax mov ax,a sub ax,b mov dif,ax mov ax,4c00h int 21h CODE ENDS
14
END
start
Linia de comanda este urmatoarea: TASM /la/zi adun.asm Listingul rezultat, plasat în fisierul adun.lst, este prezentat în continuare. Turbo Assembler adun.asm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0000 0000 0002 0004 0006 0008 0000 0000 0003 0005 0008 000C 000F 0012 0016 0019 001C 001E
Version 2.5
0008 0003 ???? ????
B8 8E A1 03 A3 A1 2B A3 B8 CD
0000s D8 0000r 06 0002r 0004r 0000r 06 0002r 0006r 4C00 21
Turbo Assembler Symbol Table
11/09/07 13:18:12 Page1
DATA SEGMENT a DW 8 b DW 3 sum DW ? dif DW ? DATA ENDS CODE SEGMENT ASSUME ds:DATA,cs:CODE start: mov ax,data mov ds,ax mov ax,a add ax,b mov sum,ax mov ax,a sub ax,b mov dif,ax mov ax,4c00h int 21h CODE ENDS END start
Version 2.5
11/09/07 13:24:21
Symbol Name
Type
??DATE ??FILENAME ??TIME ??VERSION @CPU @CURSEG @FILENAME @WORDSIZE A B DIF START SUM
Text "11/09/07" Text "adun " Text "13:24:21" Number 0205 Text 0101H Text CODE Text ADUN Text 2 Word DATA:0000 Word DATA:0002 Word DATA:0006 Near CODE:0000 Word DATA:0004
Groups & Segments
Value
Bit Size Align 15
Page2
Combine Class
CODE DATA
16 16
001E Para 0008 Para
none none
Segmentele şi grupurile utilizate (vezi lucrarea 4 pentru informatii referitoare la segmente şi grupuri) în fisierul sursa sint listate la sfirsitul programului, indicindu-se dimensiunea lor, tipul de aliniere, de combinare şi clasa. Daca în fisierul sursa au fost utilizate directive de segment simplificate, numele reale de segmente generate de TASM vor fi listate în tabela. Pentru exemplificare prezentam tabela de segmente şi grupuri corespunzatoare listingului anterior: Groups & Segments
Bit Size Align
CODE DATA
16 16
001E Para 0008 Para
Combine Class none none
Prima coloana indica numele tuturor segmentelor şi grupurilor din modulul sursa. Numele de segmente şi grupuri sint date în ordine alfabetica, exceptind cazul în care numele de segmente ce apartin unui grup sint plasate sub numele grupului în ordinea în care au fost adaugate grupului. Coloana Bit indica numarul de biti ai cuvintului segmentului respectiv. Coloana Size indica dimensiunea în numar de octeti (in hexazecimal) a fiecarui segment. Nu este prezentata dimensiunea grupurilor. Coloana Align indica tipul de aliniere al segmentului, implicit fiind Para, adica aliniere la paragraf (multiplu de 16). Coloana Combine indica tipul de combinare al segmentului. Daca nu este definit un tip de combinare explicit pentru segment, se asociaza implicit none, care este un tip de combinare special. Coloana Class indica numele clasei segmentului. Toate simbolurile (cu exceptia numelor pentru macrodefinitii, structuri, inregistrari şi segmente) sint prezentate în tabela de simboluri aflata la sfirsitul listingului. Pentru exemplificare consideram tabela de simboluri corespunzatoare listingului anterior: 16
Symbol Name
Type
Value
??DATE ??FILENAME ??TIME ??VERSION @CPU @CURSEG @FILENAME @WORDSIZE A B DIF START SUM
Text "11/09/07" Text "adun " Text "13:24:21" Number 0205 Text 0101H Text CODE Text ADUN Text 2 Word DATA:0000 Word DATA:0002 Word DATA:0006 Near CODE:0000 Word DATA:0004
Coloana Symbol Name prezinta numele simbolurilor în ordine alfabetica. Coloana Type prezinta fiecare tip de simbol. Un tip este specificat ca fiind unul dintre urmatoarele: Tip Near Far Number Alias Text Byte Word Dword Fword Qword Tbyte
Semnificatie Eticheta cu referinta apropiata Eticheta cu referinta indepartata Eticheta absoluta Simbol definit cu directiva EQU Echivalare de text Un octet Un cuvint (doi octeti) Dublu cuvint (patru octeti) Cuvint de lungime sase octeti Cuvint de lungime opt octeti Zece octeti
Tipul unei variabile generata cu operatorul de multiplicare DUP, cum ar fi un tablou sau un sir, este tipul unui singur element. Coloana Value indica valoarile simbolurilor din program. Valoarea unui simbol depinde de tipul simbolului. Spre exemplu, daca simbolul reprezinta o variabila, o eticheta sau o procedura, coloana Value contine deplasamentul simbolului în hexazecimal fata 17
de inceputul segmentului în care este definit, impreuna cu numele segmentului respectiv. Echivalarile de text de la inceputul tabelei sint cele definite automat de asamblor. 1.6 Lucrul individual 1. Se vor asambla şi rula programele prezentate obtinindu-se atit fisiere .EXE cît şi .COM; 2. Se vor obtine şi se vor analiza fisierele listing şi de referinte incrucisate; 3. Se vor testa cit mai multe dintre optiunile de lucru ale macroasamblorului TASM; 4. Se va rula sub DEBUG sau TD cel putin unul dintre programele prezentate.
18
Lucrare de laborator nr. 2 Noţiuni de bază 2.1 Scopul lucrării: Se prezinta problemele principale legate de conversii de date, reprezentarea datelor intregi, reprezentarea intregilor în format BCD, reprezentarea caracterelor şi a sirurilor de caractere, reprezentarea valorilor reale, elemente de memorie, registrele procesorului, tipuri de date utilizate şi modurile de adresare a operanzilor. 2.2 Modul de lucru: Se vor efectua toate aplicaţiile din lucrare în programul TASM. Se vor preda darile de seama cu rezultatele obţinute. 2.3 Noţiuni teoretice 2.3.1 Reprezentarea datelor Programele scrise în limbaje de asamblare, la fel ca şi cele scrise în limbaje de nivel superior prelucreaza date pentru a obtine rezultate. Pentru a fi prelucrate, datele în final sint convertite în binar. Conversiile ce se realizeaza sint specifice tipului de date, de exemplu: intregul 15 este convertit în binar altfel decit valoarea reala 15.0 sau de sirul de caractere '15'. Astfel: a) intregul 15, reprezentat în binar, pe un octet se reprezinta astfel: 0000 1111 sau 0fh b) intregul 15, reprezentat în format BCD impachetat este: 0001 0101 sau 15h c) sirurile de caractere '15' se reprezinta, pe octeti, astfel: 0100 0001 0100 0101 sau 4145h d) valoarea reala 15.0, în simpla precizie-virgula mobila, se reprezinta astfel: 0100 0001 1110 0000 0000 0000 0000 0000 sau 41e0 0000h Desi calculatorul opereaza asupra datelor reprezentate în binar, pentru depanarea şi vizualizarea datelor se prefera reprezentarea lor 19
externa în hexazecimal. Folosirea sistemului hexazecimal de reprezentare a datelor se bazeaza pe: a) codurile binare sint relativ lungi şi dificil de lucrat cu ele. Codurile hexazecimale, asemanatoare celor zecimale, sint mai usor de citit. b) exista metode directe de trecere din binar în hexazecimal şi invers. c) informatia din calculator este organizata sub forma unor multipli de 16 (cuvint, dublu cuvint, double word, quad word, ten bytes) sau submultipli de 16 (octet, tetrada). Conversia dintr-o baza în alta
Pentru a converti un numar din baza p în baza q se poate aplica una din metodele generale de conversie: - conversia cu calcul în baza initiala; - conversia cu calcul în baza finala; - conversia cu calcul în baza intermediara. Pentru numere reale conversia din baza 10 intr-o alta baza se face separat conversia pentru partea intreaga, respectiv pentru partea fractionara. Pentru conversia parti intregi a unui numar real, care acopera şi numerele intregi, se procedeaza astfel: - se imparte numarul, respectiv caturile, la baza şi se retin resturile partiale pana catul devine zero; - se i-au resturile obtinute în ordine inversa calculului şi se formeaza numarul în noua baza. Pentru conversia partii fractionare se inmulteste aceasta cu baza şi se retine partea intreaga ca fiind cifra a numarului în noua baza iar partea fractionara se inmulteste din nou cu baza s.a.m.d. pana se obtine partea fractionara zero s-au nunarul de cifre a partii fractionare în noua baza dorit. Pentru exemplificare folosind prima metoda se va converti numarul zecimal 348.6785 în baza 16. Cifrele bazei 16 sunt: 0, 1, 2,3, 4, 5, 6, 7, 8, 9, 0, a, b, c, d,e, f. Incepem cu partea intreaga: 348:16 = 21 rest 12, adica „c” 20
21:16 = 1 rest 5 1:16 = 0 rest 1 deci 34810 = 15C16. Convertim partea fractionara: 0.6785*16=10.856 prima cifra a partii fractionare este 10 adica A 0.856*16=13.696 urmatoarea cifra a partii fractionare este 13 adica D 0.696*16=11.136 urmatoarea cifra a partii fractionare este 11 adica B 0.136*16= 2.176 urmatoarea cifra a partii fractionare este 2
deci 0.678510=0.ADB216 . Conversia dintr-o alta baza în baza 10 se face cu calcul în baza finala, de exemplu: 2a75.bdb316=2*163+a*162+7*161+5*160+b*16-1+d*16-2+b*16-3+3*16-4= 2*163+10*162+7*161+5*160+11*16-1+13*16-2+11*16-3+3*16-4 = 10869.741470336914110
Conversia binar – hexazecimala directa Numerele reprezentate în binar se grupeaza în grupe de cite 4 biti, de la dreapta la stanga. Fiecare grupa se inlocuieste cu cifra hexazecimala corespunzatoare. De exemplu:
daca e cazul tetrada cea mai din stinga se completeaza cu zerouri, deci vom avea:
In capul unui numar binar, care are şi parte subunitara, se fac grupe de 4 biti de la virgula spre dreapta, respectiv spre stanga. Ultimele grupe, daca nu sint complete, se completeaza cu zerouri. Exemplu:
21
deci: 1011010110.1101012 = 2d6.d416 Conversia hexazecimal – binar directa Se realizeaza invers, fiecare cifra hexazecimala se inlocuieste cu echivalentul binar format din 4 cifre binare. Exemplu: 5B2C10 va fi în binar:
Deci: 5B2C16 = 01011011001011002 sau: 2C3.64C16 = 001011000011.0110010011002 2.1.1 Reprezentarea numerelor intregi în binar In cazul numerelor binare cu semn se foloseste conventia prin care primul bit este bitul de semn, daca are valoarea 0 numarul este pozitiv, iar daca are valoarea 1 numarul este negativ. Exista 3 metode de reprezentare a numerelor binare intregi cu semn: - directa ( în reprezentare apare semnul şi valoarea absoluta) - complement fata de unu - complement fata de doi sau complement adevarat. Metoda directa In acest caz numarul cu semn se reprezinta prin semn şi valoarea sa absoluta. De exemplu: intregul 30 se reprezinta pe octet astfel: pe ultimi 7 biti se reprezinta valoarea absoluta a numarului iar bitul 7 cel mai semnificativ este bitul de semn (1-minus şi 0-plus): 00011110 iar - 30 se reprezinta: 10011110 22
Complement fata de unu In complement fata de unu, numarele pozitive se reprezinta la fel ca în cazul metodei directe, adica dupa bitul de semn care este 0 urmeaza valoarea absoluta a numarului. Daca numarul este negativ se reprezinta numarul în binar ca un numar pozitiv dupa care se face complementul fata de 1, adica se inlocuieste fiecare bit 0 cu 1, respectiv fiecare bit 1 cu 0. De exemplu numarul – 30 se reprezinta pe octet astfel: - se reprezinta pe octet 30 (valoarea absoluta) 000111102 - se face complementul fata de 1, adica 11100001 deci: -3010=11100012=0e116 în complement fata de 1 pe octet. Daca dorim sa reprezentam –30 pe cuvant, parcurgem pasii: - reprezentam valoarea absoluta 30 pe cuvant: 0000000000011110 - facem complementul fata de unu a intregului cuvant 1111111111100001 si avem: –3010 =1111 1111 1110 00012 =0ffe116 în complement fata de 1 pe cuvant. Complement fata de doi De obicei în calculatoare pentru reprezentarea numerelor cu semn se foloseste complementul fata de doi. Reprezentarea în complement fata de doi se realizeaza astfel: - daca numarul este pozitiv, complement fata de doi este identic cu complement fata de unu - daca numarul este negativ la reprezentarea în complement fata de unu se aduna 1 De exemplu –3010 reprezentat în complement fata de doi pe octet se face astfel: - se reprezinta în binar pe octet valoarea absoluta a numarului 00011110
- se calculeaza complement fata de unu, adica: 11100001
23
- la valoarea calculata se aduna 1, deorece numarul este negativ şi avem
deci –3010 în complement fata de doi este 111000102 = 0e216 pe octet. Acelasi numar reprezentat în complement fata de doi pe cuvant va fi: 3010 = 1111 1111 1110 00102 = 0ff e216 2.1.2 Reprezentarea numerelor intregi în BCD(Binary Coded Decimal) In acest sistem o cifra zecimala se reprezinta pe o tetrada (4 biti), deci doua cifre BCD pe octet. Deoarece cu 4 biti se pot codifica 16 valori distincte şi sistemul BCD foloseste doar 10 dintre acestea, ramin 6 valori ce nu pot fi folosite. De exemplu: numarul zecimal 675 se va reprezenta pe 2 octeti astfel: 0000 0110 0111 0101. Procesoarele dispun de instructiuni ce opereaza cu numere reprezentate în BCD şi de instructiuni care realizeaza corectii ce trebuie facute dupa, sau inaintea, operatiilor în BCD. Acest format de reprezentare se mai numeste şi BCD impachetat, pentru al deosebi de formatul BCD despachetat, conform caruia o cifra BCD se reprezinta pe un octet. în acest caz numarul 675 va fi reprezentat pe 3 octeti. Tetrada superioara a fiecarui octet din reprezentarea BCD despachetat se cere de catre procesor sa aibe valoarea 0 (zero). 2.1.3 Reprezentarea caracterelor şi a sirurilor de caractere In categoria datelor alfanumerice intra caracterele alfabetice, caracterele numerice, semnele de punctuatie şi caracterele de control.
24
Codificarea acestora se face conform codului standard ASCII (American Standard Code for Information Interchange). Codul ASCII standard este un cod pe 7 biti (128 combinatii distincte). Ca atare un caracter ASCII se reprezinta pe un octet în care bitul cel mai semnificativ este zero. Domeniul de valori este de la 0 la 127 (in hexazecimal de la 00h la 07fh). Exemplu: Caracterul 'a' are codul 61h, 'A' are codul 41h, '5' are codul 35h, '+' are codul 0B2h. Sirurile de caractere sint reprezentate prin succesiuni de octeti ce cuprind codurile caracterelor respective. De exemplu sirul de caractere “Aa4+b” se reprezinta pe 5 octeti ce vor contine 41 61 34 62 42h. 2.1.4 Reprezentarea numerelor în virgula mobila Valorile reale (fractionare) se reprezinta de obicei în virgula mobila, adica sub forma: (-1)s * m * be unde: - s este numit bit de semn şi este 1 pentru numere negative şi 0 pentru numere pozitive; - m este numita mantisa şi este un numar pozitiv subunitar reprezentat în baza b - b este baza de reprezentare a numarului, de obicei 2 sau 16; - e este exponentul şi este un numar intreg cu semn. In binar mantisa este normalizata daca partea intreaga a numarului are o singura cifra şi aceasta este 1. Intrucat în calculator numerele sunt reprezentate în binar b=2, sub forma normalizata prima cifra a mantisei normalizate este 1. Deci numarul 0.00101101 normalizat este 1.01101 *2-3 Daca primul bit al mantisei în reprezentarea normalizata este intotdeauna 1, el poate fi subinteles, deci nu se mai reprezinta, castigandu-se astfel un bit în spatiul de memorare al mantisei. Acest bit se mai numeste bit ascuns (hidden bit). 25
Exponentul fiind un numar intreg cu semn va trebui sa fie reprezentat semnul şi valoarea acetuia. Pentru a evita reprezentarea separata a semnului exponentului, acesta se reprezinta sub forma unei caracteristici, adica sub forma unei constante c=k+e astfel ca valoarea c sa fie intotdeauna o valoare pozitiva. Deobicei numerele reale sunt reprezentate în calculator în simpla precizie (pe 32 biti) sau în dubla precizie (pe 64 biti). în cazul reprezentarii în simpla precizie, constanta k este 127 şi avem:
unde: - s - bitul de semn al numarului (mantisei) : 0 -pozitiv, 1 - negativ - caracteristica c = k + e, ( k = 12710 = 011111112 ) se reprezinta pe 8 biti fiind compusa intre 0 şi 255. Domeniul de reprezentare al exponentului va fi de la – 127 la 128; - mantiSă se reprezinta fizic pe 23 biti, deci o mantisa de 24 biti (23 + 1 bit ascuns) Exemple: 1) Fie numarul real 0.0390625. Se cere reprezentarea lui în simpla precizie. Pe pasi trebuie facute urmatoarele operatii: - se converteste numarul dat în binar, adica: 0.039062510 = 0.00001012 - se normalizeaza numarul binar, adica: 0.00001012 = 1.01 x 2-5 - se calculeaza semnul, caracteristica şi mantisa: s = 0, numarul este pozitiv c = 127 – 5 = 12210 = 011110102 mantisa m= 1.01, eliminand bitul ascuns şi reprezentat pe cei 23 biti avem: .01000000000000000000000 in final numarul real 0.039062510 în simpla precizie va fi 26
0
01111011 0100. . . . .
0000000
sau 3d20 0000h 2) Să se reprezinte în simpla precizie numarul: - 23.0390625 23.0390625 = 10111.00001012 10111.00001012 = 1.01110000101 *24 si avem s=1 c = 127 + 4 = 12310 = 100000112 mantisa m pe 23 biti va fi: m = .01110000101000000000000 In final reprezentarea numarului în binar este : 1 10000011 01110000101000000000000 sau în hexazecimal: c1b85000 3) Ce numar real este reprezentat în virgula mobila bef4000016 = 1011 1110 1111 0100 0000 0000 0000 00002 ? Se vor extrage elementele constitutive: -semnul s = 1, numarul este negativ -caracteristica 011111012 = 12510, deci expoentul e = c – 127=125 – 127 = -2 - la mantisa 111 0100 0000 0000 0000 0000 - se adauga bitul ascuns şi avem 1.111 0100 0000 0000 0000 0000 care ne da: 0.1111012 = 1.20+1.2-1+1.2-2+1.2-3 +1.2-4 +0.2-5+1.2-6 = 1.95312510 - inmultindu-l cu 2-2 se obtine: 0,4883562510 sau m = 1.111101 de unde valoarea obtinuta a numarului este 1.111101 x 2-2 = 0.01111012 = 0.4883562510 Adaugand semnul, numarul real este: - 0. 48835625 10 4) Ce numar real este reprezentat în virgula mobila prin: 0100 0011 0101 1010 0000 0000 0000 0000 = 435a 000016 ? Extragem elementele constitutive: 27
- s = 0, numar pozitiv: - caracteristica c = 100001102 = 134 de unde exponentul e = 134 – 127 = 7 - adaugam bitul ascuns la 10110100. . . . 0 şi obtinem mantisa m = 1. 110110100 . . .0 - valoarea absoluta a numarului este: 1.1101101 x 27 = 11101101.0 = 23710 Numarul real este 237,00. 2.2 Elemente de memorie Bitul Cel mai mic element de memorare a unei informatii este bitul, în care se poate memora o cifra binara, 0 sau 1. De obicei informatia de prelucrat se reprezinta pe segmente contigue de biti denumite tetrade, octeti, cuvinte, dublu cuvinte, quadwords şi tenbytes. Tetrada Tetrada este o secventa de 4 biti, numerotati 0,1,2,3 de la dreapta la stinga, bitul 0 fiind cel mai putin semnificativ, iar bitul 3 cel mai semnificativ:
Octetul (Byte) Octetul sau byte este un element de numerotare, ce cuprinde o secventa de 8 biti. Octetul este unul dintre cele mai importante elemente (celule ) de memorare adresabile. Cei 8 biti ai unui octet sint numerotati cu 0,1,2,...7 de la dreapta la stinga:
Octetul este format din 2 tetrade, tetrada inferioara (din dreapta) contine bitii 0, 1, 2, 3, iar cea superioara (din stinga) contine bitii 4, 5, 6, 7 ai octetului. 28
Cuvantul(Word) Cuvantul este o secventa de 2 octeti, respectiv 16 biti, numerotati de la dreapta spre stanga, astfel 0, 1, 2 ......14, 15. Bitul cel mai semnificativ este bitul 15. Primul octet(inferior) din cuvant contine bitii 0, 1, 2, 3, 4, 5, 6, 7, iar al doilea octet(superior), bitii 7, 8, 9, 10, 11, 12, 13, 14, 15. 1
1
1
0
0
0
15
14
13
12
11
10
0
1
1
0
0
1
1
0
0
1
9
8
7
6
5
4
3
2
1
0
Cuvantul poate fi reprezentat printr-un registru de 16 biti sau în doi octeti de memorie. în memorie, octetul inferior (bitii 0-7) este memorat la adresa mai mica, iar octetul superior (bitii 8-15) la adresa cea mai mare. De exemplu cuvantul 4567h se reprezinta intr-un registru de 16 biti sub forma 4567h, iar în memorie la adresa 1000 sub forma 6745 (octetul 67 la adresa 1000, iar octetul 45 la adresa 1001). Dublu cuvant (Double Word) O succesiune de 2 cuvinte (4 octeti, 32 biti), reprezinta un dublu cuvant. Cei 32 de biti ai unui dublu cuvant sunt numerotati de la dreapta la stanga prin 0, 1, 2, ......30, 31. Bitul cel mai semnificativ este bitul 31, octetul cel mai putin semnificativ contine bitii 0-7, iar cel mai semnificativ octet (octetul 4) contine bitii 2331. Un dublu cuvint poate fi reprezentat intr-un registru de 32 biti sau pe 4 octeti consecutivi de memorie. în memorie, octetul 1-cel mai putin semnificativ este memorat la adresa cea mai mica, iar octetul 4-cel mai semnificativ la adresa cea mai mare. De exemplu dublul cuvant 12 34 56 78h, aflat la adresa 2000, va fi memorat astfel 78 56 34 12, cu octetul 78h la adresa 2000, iar octetul 12h la adresa 2003. Quardword Quardword (qword) este format din 2 dublu cuvinte(4 cuvinte, respectiv 8 octeti succesivi de memorie). Cei 64 biti ai unui qword sunt numerotati de la dreapta la stanga astfel: 0, 1, 2, ......62, 63. 29
Bitul cel mai semnificativ este bitul 63. în memorie octetul 1 se reprezinta la adresa cea mai mica, iar octetul 8 la adresa cea mai mare. Tenbyte (10 cuvinte) O succesiune de 10 octeti formeaza un tenbyte(tbyte). Cei 80 de biti ai elementului sint numerotati de la dreapta la stinga cu 0, 1, 2,..., 78, 79. în memorie octetul cel mai putin semnificativ (bitii 07) se reprezinta la adresa cea mai mica, iar octetul 10( bitii 73-80) la adresa cea mai mare. 2.3 Tipuri de date In limbajele de asamblare 80x86 se poate opera cu anumite tipuri de date, recunoscute de procesor, acesta dispunind de directive (pseudoinstructiuni) specifice pentru definirea lor. a) Byte(octet) Acest tip de date ocupa 8 biti, adica un octet(byte). Informatia dintr-un octet poate fi: un intreg fara semn cuprins intre 0 şi 225, un intreg cu semn cuprins intre –128 şi 127, sau un caracter ASCII. Definirea datelor de tip byte se face cu ajutorul directivei DB(Define Byte) care are sintaxa: [variabila] DB lista – expresii unde - variabila, optionala, este un identificator asociat adresei efective a primului octet de memorie generat, corespunzator primei expresii din lista de expresii - lista-expresii cuprinde expresii constante(calculabile în momentul asamblarii) şi separate prin virgula. b) WORD(cuvant) Un cuvant ocupa doi octeti (16 biti) şi poate fi reprezentat intrun registru de 16 biti sau în 2 octeti consecutivi de memorie. Numerotarea bitilor în cadrul unui cuvant se face de la 0 la 15 (bitul 15 e bitul cel mai semnificativ al cuvintului, iar bitul 0 este bitul cel mai putin semnificativ), numerotarea se face de la dreapta la stanga: 30
Informatia memorata intr-un cuvant poate fi : - un intreg pe 16 biti cu semn (bitul 15 este bitul de semn), cuprins intre -215 şi 215 –1, - un intreg pe 16 biti fara semn, cuprins intre 0 şi 216 - sau o adresa de memorie de 16 biti. Reprezentarea celor 2 octeti ai cuvintului în memorie se face astfel incat octetul cel mai putin semnificativ este memorat la adresa cea mai mica. De exemplu: daca valoarea 2345h este memorata la adresa 2000h, atunci octetul 45h se va afla la adresa 2000h, iar octetul 23h la adresa 2001h. Generarea datelor de tip cuvint se poate face folosind directiva de tip DW(Define Word), a carei sintaxa este : [variabila] DW
lista de expresii
unde: - variabila, optionala, este un identificator asociat adresei efective a primului cuvant de memorie generat, corespunzator primei expresii din lista de expresii. - lista de expresii este o lista de expresii constante separate prin virgula. c) Double WORD(dublu cuvant) Un dublu cuvant ocupa 2 cuvinte sau 4 octeti( 32 biti ) şi poate fi reprezentat în memorie pe 4 octeti consecutivi, intr-o pereche de registre de 16 biti sau intr-un registru de 32 biti (la procesoarele de 32 biti). Informatia memorata intr-un dublu cuvant poate fi: - un intreg pe 32 biti, cu sau fara semn; - un numar real în simpla precizie; - sau o adresa fizica de memorie de 32 biti. Generarea datelor de tip dublu cuvant se poate face folosind directiva DD(Define Double Word), a carei sintaxa este: [variabila] DD lista – expresii unde:
31
- variabila, optionala, este un identificator asociat adresei efective primului dublu cuvant de memorie generat corespunzator primei expresii din lista de expresii; - lista de expresii este o lista de expresii constante separate prin virgula. Reprezentarea celor doua cuvinte a unui dublu cuvant de memorie se face astfel incat cuvantul cel mai putin semnificativ este memorat la adresa cea mai mica. De exemplu dublul cuvant 12345678 h, aflat la adresa 2000h se memoreaza astfel: cuvantul 5678h se memoreaza la adresa 2000h, iar cuvantul 1234h la adresa 2002h, adica adresa de segment este memorata la adrese mari, iar deplasamentul (offsetul) la adrese mici. d) QUAD – WORD (8 octeti) Tipul Quad – word (qword) ocupa 8 octeti şi este reprezentat în memorie pe 64 biti sau intr-o pereche de registre de 32 biti (in cazul procesoarelor de 32 biti). Informatia stocata intr-un qword poate fi: un intreg cu sau fara semn pe 64 biti, sau un numar real în dubla precizie. Generarea unor date de tip qword se face cu ajutorul directivei DQ(Define Quad – word), a carei sintaxa este: [variabila] DQ lista de expresii unde: - variabila, optionala, este un identificator asociat adresei efective primului qword de memorie generat corespunzator primei expresii din lista de expresii; - lista de expresii este o lista de expresii constante separate prin virgula. Reprezentarea în memorie a celor 8 octeti ai unui qword se face astfel incit octetul cel mai putin semnificativ este memorat la adresa cea mai mica. e) Ten Bytes Valorile Ten – byte (tbyte) ocupa 10 octeti consecutivi de 32
memorie, sau unul din registrele coprocesorului matematic. Informatia stocata intr-un tbyte poate fi: un numar intreg reprezentat ca o secventa de cifre BCD (format impachetat) cu semn sau un numar real în precizie extinsa. Generarea unor date de tip tbyte se face cu directiva DT( Define Ten Bytes)a carei format este: [variabila] DT lista de expresii unde: - variabila, optionala, este un identificator asociat adresei efective primului tbyte de memorie generat corespunzator primei expresii din lista de expresii; - lista de expresii este o lista de expresii constante separate prin virgula. In format BCD impachetat fiecare cifra zecimala se reprezinta pe o tetrada (4 biti), deci 2 cifre BCD pe octet. Un intreg BCD se poate reprezenta cu maxim 19 cifre zecimale, care ar ocupa 76 biti. Ultima tetrada aflata la adresa cea mai mare este destinata memorari semnului. Semnul se memoreaza doar în bitul cel mai semnificativ al numarului, deci urmatorii 3 biti ai tetradei ce contine semnul pot fi biti ai numarului. Astfel intregii BCD pot fi cuprinsi intre: -79999 99999 99999 99999 si +79999 99999 99999 99999 cifra cea mai semnificativa fiind reprezentata doar pe 3 biti. Pentru exemplificarea utilizarii directivelor de generare de date, consideram urmatorul program: .model small .stack 100h data segment alfa db 40+25,72h,75o,11011b,15+22h db 0ach,-65,'a','abc' beta dw 4567h,0bc4ah,1110111011b,2476o dw -7683,7683,'ab' gama dd 12345678h,1,-1 33
dd 1.0,-1.0,-.23828125,0.0390625 gama1 dd gama qw dq 2,-2,2.5,-2.5 t1 dt 8888888888777777777,-5555555555555555555 tb dt 45671234567890123456,-45671234567890123456 f dt 3345,-3345,1.0,-1.0 data ends cod segment assume cs:cod, ds:data start: mov ax,data mov ds,ax cod ends end start
Fisierul listing obtinut (.lst) dupa asamblare arata astfel: Turbo Assembler Page 1 tipur.ASM
Version 2.5
11/09/07 14:42:50
1 0000 .model small 2 0000 .stack 100h 3 0000 data segment 4 0000 41 72 3D 1B 31 alfa db 40+25, 72h, 75o, 11011b,15+22h 5 0005 AC BF 61 61 62 63 db 0ach,-65,'a','abc' 6 000B 4567 BC4A 03BB 053E beta dw 4567h,0bc4ah,1110111011b,2476o 7 0013 E1FD 1E03 6162 dw -7683,7683,'ab' 8 0019 12345678 00000001 + gama dd 12345678h,1,-1 9 FFFFFFFF 10 0025 3F800000 BF800000 + dd 1.0,-1.0,.23828125,0.0390625 11 BE740000 3D200000 12 0035 00000019sr gama1 dd gama 13 0039 0000000000000002 + qw dq 2,-2,2.5,-2.5 14 FFFFFFFFFFFFFFFE + 15 4004000000000000 + 16 C004000000000000 17 0059 08888888888777777777+ t1 dt 8888888888777777777,-5555555555555555555 18 85555555555555555555 19 006D 45671234567890123456+ tb dt 45671234567890123456,-45671234567890123456 20 C5671234567890123456 21 0081 00000000000000003345+ f dt 3345,-3345,1.0,-1.0 22 80000000000000003345+ 23 3FFF8000000000000000+ 24 BFFF8000000000000000
34
25 26 27 28 29 30 31 32
00A9 0000 0000 0000 0003 0005
data ends cod segment assume cs:cod, ds:data start: mov ax,data mov ds,ax cod ends end start
B8 0000s 8E D8
Prima coloana reprezinta numarul liniei din fisierul .lst. Coloana urmatoare reprezinta adresa relativa la continutul registrului ds, adresa exprimata în hexazecimal pe 4 cifre hexa. Urmeaza apoi continutul campului de date corespunzator unei linii. Daca se continua pe linia urmatoare va apare semnul +. Valorile intregi, negative se reprezinta în complement fata de doi, iar cele reale sunt reprezentate în virgula mobila. Prezenta caracterelor r şi s în aceasta zona indica faptul ca este vorba despre o adresa de segment 0000h şi deplasamentul 0015h, adica adresa relativa a variabilei gama. La intregii BCD de la variabilele t1, tb se poate observa semnul (bitul de semn). In fisierul .lst nu apare pozitia fizica a octetilor în memorie. Zona de memorie corespunzatoare modulului de date de mai sus arata astfel: ds:0000 ds:0008 ds:0010 ds:0018 ds:0020 ds:0028 ds:0030 ds:0038 ds:0040 ds:0048 ds:0050 ds:0058 ds:0060 ds:0068 ds:0070 ds:0078 ds:0080
41 61 03 61 00 3F BE 5A 00 FF 40 C0 88 55 90 34 C5
72 62 3E 78 FF 00 00 02 FF 00 00 77 88 55 78 12 45
3D 63 05 56 FF 00 00 00 FF 00 00 77 08 55 56 90 33
1B 67 FD 34 FF 80 20 00 FF 00 00 77 55 55 34 78 00
31 45 E1 12 FF BF 3D 00 FF 00 00 77 55 85 12 56 00
AC 4A 03 01 00 00 19 00 FF 00 00 77 55 56 67 34 00
BF BC 1E 00 00 00 00 00 FF 00 00 87 55 34 45 12 00 35
61 BB 62 00 80 74 B0 00 FF 04 04 85 55 12 56 67 00
ds:0088 ds:0090 ds:0098 ds:00A0 ds:00A8
00 00 00 00 BF
00 00 00 00 00
00 00 00 00 00
45 00 00 00 00
33 80 80 00 00
00 00 FF 00 00
00 00 3F 80 00
00 00 00 FF 00
Prima coloana reprezinta adresa fizica de memorie sub forma ds:xxxx unde ds este registrul segment de date, iar xxxxh reprezinta ofsetul, adresa relativa din segmentul continut în ds. în continuare pe fiecare linie apar 8 octeti de memorie. Valoarea intreaga alfa = 65 = 40+25=4116 reprezentata pe un octet prin 41h se afla la adresa ds: 0000, iar 75o la adresa ds: 0002 sau alfa +2. Cuvantul 4567h, aflat la adresa simbolica beta ocupa doi octeti de la adresa ds: 000A astfel 6745. Dublul cuvant 0.0390625 se afla la adresa ds: 0025. Adresa variabilei gama din declaratia gama1 dd gama apare aici în forma 5AB0:0019 unde 5AB0 este adresa de segment continuta în ds, iar 0019 este offsetul lui gama. 2.4 Registrele procesorului 2.4.1 Procesoarele de 16 biti Procesoarele de 16 biti din familia Intel şi compatibile Intel, dispun de 14 registre, fiecare avand lungimea de 16 biti. Cei 16 biti ai unui registru sunt numerotati de la 0 la 15 de la dreapta la stanga.
15
14
3
Aceste registre sunt impartite în 5 grupe distincte: 1. patru registre segment 2. patru registre de date 3. doua registre pointer şi doua registre index 4. un registru instructiune 5. un registru de stare program Registre segment
36
2
1
0
Aceste procesoare pentru un program scris în limbaje de asamblare aloca patru zone de lucru în memorie: o zona pentru date, o zona pentru instructiuni, o zona speciala pentru stiva şi o zona suplimentara pentru date. Fiecare din aceste zone pot avea pana la 64K octeti şi poarta denumirea de segment. Astfel exista segmentul de date (Data Segment), segmentul de instructiuni (Code Segment), segmentul de stiva (Stack Segment) şi segmentul suplimentar de date (Extra Segment). Este posibil ca cele 4 zone sa fie suprapuse total sau partial. Adresele de inceput ale acestor zone sunt numerotate în cele 4 registre segment: - DS contine adresa de inceput a zonei de date curente; - CS contine adresa de inceput a zonei de instructiuni; - SS contine adresa de inceput a zonei de stiva; - ES contine adresa de inceput a zonei desuplimentare. Daca segmentul de date incepe de la locatia de memorie 1234h atunci DS va contine valoarea 1234h. Exista instructiuni pentru incarcarea adreselor de memorie în registrele segment. Registrele de date Cele 4 registre de date, fiecare de 16 biti sunt: - registrul acumulator AX(Accumulator register) - registrul de baza BX(Base register) - registrul numerelor CX(Count register) - registrul de date DX(Data register) Fiecare din aceste registre pot fi folosite ca doua subregistre de cate 8 biti. Bitii 0 ÷ 7 ai fiecarui registru formeaza subregistrul inferior (low), iar bitii 8 ÷ 15 formeaza subregistrul superior(high), de exemplu pentru registrul AX avem subregisrele AL şi AH. AX AH AL 15........8 7...........0 BX BH BL CX CH CL DX 37
DH
DL
Aceste registre pot fi accesate la nivel de cuvant (16 biti) sau la nivel de octet (8 biti). De exemplu: mov ax,12h; transfera în registrul ax valoarea 12h, adica ax | 0000 | 0000 | 0001 | 0010 | iar mov al,12h; transfera în registrul ah valoarea 12 h, registrul Al ramane nemodificat, adica: ax | 0001 | 0010 | ???? | ???? | Toate cele 4 registre de date pot fi folosite pentru memorarea datelor, insa unele din acestea sunt folosite special pentru alte scopuri. De exemplu registrul CX este folosit în instructiunea LOOP de ciclare, care il modifica implicit si-i testeaza valoarea, registrul DX este folosit în instructiunile de impartire şi inmultire, iar registrul BX este folosit pentru adresarea datelor (operanzilor). Registrele pointer şi index Registrele pointer se folosesc pentru calculul offsetului (distantei fata de inceputul unui segment) din cadrul segmentului. Cei doi registri pointer sunt: pointerul de stiva SP (Stack Pointer) şi pointerul de baza (Base Pointer). SP şi BP sunt registre de 16 biti. Registrul SP retine adresa efectiva (offsetul) a varfului stivei. Adresa fizica a varfului stivei SS: SP este data de perechea de registri SS şi SP, registrul SS contine adresa de inceput al segmentului de stiva iar Sp contine offsetul din acest registru (adica distanta în octeti de la inceputul registrului de stiva): stiva
Registrul BP este folosit la calculul offsetului din interiorul unui segment. De exemplu poate fi folosit ca pointer al unei stive
38
proprii, dar nu a procesorului. Este folosit în principal pentru adresarea bazata indexata a datelor. Registrele de index, de 16 biti sunt: şi (Source Index) şi DI (Destination Index). Registrele de index sunt folosite pentru accesul la elementele unui tablou sau a unei tabele, asemanator cu utilizarea indexilor în limbajele de nivel superior. Aceste registre sunt folosite indeosebi în prelucrarea sirurilor de caractere. Registrul de instructiuni Registrul de instructiuni (Instruction Pointer) contine offsetul curent în segmentul de cod, adica adresa efectiva a urmatoarei instructiuni de executat din segmentul de cod curent. Dupa executarea instructiunii curente CPU preia din IP adresa urmatoarei instructiuni de executat şi incrementeaza corespunzator valoarea lui IP, cu numaul de octeti ai codului instructiuni ce va fi executata. Uneori acest registru se numeste numarator de program. Adresa fizica a urmatoarei instructiuni de executat este data de figura:
Registrul cu indicatori (FLAGS) Registrul cu indicatori (flag register) numit şi registru de stare program (PSW) contine informatii despre ultima instructiune executata. Din cei 16 biti ai registrului nu sunt folositi decat 9 biti: 0, 2, 4, 6 – 11. Acesti biti se mai numesc biti de stare şi contin informatii despre ultima instructiune executat. Aproape toate instructiunile limbajului de asamblare afecteaza bitii de stare. Cei 9 biti de stare sunt:
39
1. CF(carry flag) - setat (pus pe 1) indica un transport sau un imprumut. Daca în urma unor operatii aritmetice obtinerea rezultatului implica un transport/imprumut de la /la bitul cel mai semnificativ bitul CF este setat. 2. PF(parity flag) – setat indica faptul ca ultimul octet al rezultatul în binar are un numar par de biti egali cu 1. Verificarea paritatii unei date inainte şi dupa o operatie hard poate fi folosita pentru determinarea unei erori de transmitere. 3. AF(auxiliary carry flag) – setat indica faptul ca în urma unei operatii aritmetice a aparut un imprumut sau imprumut inspre/ dinspre bitul 3. Acest bit este folosit pentru corectii în cazul aritmeticii BCD. 4. ZG(zero flag) – setat indica un rezultat zero. 5. SF(sign flag) – setat indica un rezultat negativ. 6. TF(trap flag) – setat permite executia pas cu pas a programului. 7. IF(Intrerrupt enable flag) – setat permite detectarea de catre procesor a unei intreruperi. 8. DF(direction flag) – determina incrementarea sau decrementarea automata a registrului de index în timpul instructiunilor pe siruri de caractere. 9. OF(overflow flag) – setat indica un rezultat care dapaseste (nu intra in) unitatea de memorie (octet, cuvant). Indicatorii CF, PF, ZF, AF, SF şi OF sunt numiti indicatori de conditie, iar TF, DF şi IF indicatori de control. Dispunerea flagurilor (indicatorilor) în registrul FLAGS este:
2.4.2 Procesoare de 32 biti Procesoarele de 32 biti sunt compatibile ca arhitectura cu cele de 16 biti, prin aceea ca registrele de 16 biti se regasesc ca subregistre ale registrelor de 32 de biti. Registrele generale ax, bx, cx, dx, si, di, bp şi sp de 16 biti fac parte din registrele generale de 32 biti ai 40
procesoarelor de 32 biti extinse: eax, ebx, ecx, edx, esi, edi, ebp şi esp. Primii 16 biti din aceste registre sunt registri generali ai procesoarelor de 16 biti. Analog registrele IP şi FLAGS de 16 biti sunt extinse la 32 biti în cazul registrelor EIP şi ELAGS de 32 biti. Registrul FLAGS se regaseste în primii 16 biti ai registrului EFLAGS. Registrele segment au fost pastrate de 16 biti, dar s-au adaugat doua noi registre FS şi GS. 31
16 EAX EBX CBX DBX ESI EDI EBS ESP
15 AX BX CX DX SI DI BP SP
0
15
0 CS
SS DS ES FS GS
IP FLAGS
Pe langa aceste registre, procesoarele de 32 de biti dispun de alte registre de control, de gestionare a adresei, de depanare şi de test, care difera de la un tip de procesor la altul fiind folosite în principal de programele de sistem. Semnificatia registrelor segment în cazul procesoarelor de 32 biti a fost modoficata, ele sunt folosite ca selectoare de segment. în acest caz ele nu indica o adresa de segment, ci un descriptor de segment care precizeaza adresa de baza a segementului, dimensiunea acestuia şi drepturile de acces asociate acestuia. Astfel adresa de baza poate fi specificata pe 32 biti iar dimensiunea unui segment ssa fie de pana la 4 GB. 2.5 Moduri de adresare Modurile de adresare specifica modul în care se calculeaza adresa operatorului aflat în memorie. Adresa fizica a unui operand este formata din adresa de segment şi adresa efectiva (offsetul). 41
Adresa de segment este furnizata de unul din cele 4 registre de segment şi indica inceputul segmentului în care se gaseste operandul. Adresa efectiva calculata pe baza modurilor de adresare, dau offsetul (deplasamentul) operatorului în cadrul segmentului respectiv. în cazul instructiunilor cu 2 operanzi, obligatoriu unul din operanzi este continut intr-un registru general. a) Modurile de adresare la procesoarele de 16 biti 1) Adresare imediata. Operatorul este o constanta şi apare în formatul instructiunii. De exemplu: mov bx,55h; transfera în bx valoarea hexazecimala 55 add bx,10011b; aduna la Bx valoarea binara 10011 2) Adresare directa. Adresa efectiva a operandului este data de un deplasament în segmentul curent. Deplasamentul este parte componenta a instructiunii. Exemplu: alfa db 167o
........................... mov al,alfa ; transfera în al continutul variabilei alfa mov dx,[135]; transfera în cx continutul adresei 135
Acest mod de adresare foloseste registrul DS implicit ca registru de segment. 3) Adresare indirecta Adresa efectiva a operandului este data de continutul registrelor: bp, bx, şi sau di. Registrul segment implicit este DS. mov al,[si] ; transfera în al continutul octetului de la adresa continuta de registrul si mov [bx],ax ; transfera continutul lui ax în locatia a carei adreSă se afla în bx. sub byte ptr[si],56h ; scade 56h din octetul aflat la adresa data de si 4) Adresare bazata sau indexata Adresa efectiva se obtine adunand la unul din registrele de baza bx sau bp, sau la unul din registrele de index şi sau DI un 42
deplasament pe 8 sau 16 biti. Registrul segment implicit este DS (daca se folosesc registrele BX, şi sau DI) şi registrul SS(daca se foloseste BP). In scrierea operanzilor adresati sub aceasta forma, se pot folosi diverse modalitati, echivalente din punct de vedere al mecanismului de adresare. Exemplu: a)
alfa dw 0a4bh,35,64,157o. mov bx,100 mov ax,alfa[bx] mov ax,bx[alfa] mov ax,[bx + alfa] mov ax,[bx].alfa
b)
şir db 20 dup(?) .............. xor si,si .................. add al,sir[si] ;echivalent cu si[sir] sau [sir+si] etc. inc si
5) Adresare bazata şi indexata Adresa efectiva este formata prin adunarea unuia din registrele de baza (BX sau BP) cu unul din registrele index (SI şi DI) şi cu un deplasament de 8 sau 16 biti. Registrele segment implicite sint DS (daca se foloseste BX cu şi sau cu DI) sau SS (daca se foloseste BP cu şi sau DI). Deplasamentul poate fi şi nul. Registrele BX, BP, şi si DI sint incluse intre paranteze drepte [ ]. Exemplu: mov mov add adc
ax,alfa[bx][si] ax,[bx + şi + 8] ax,[bx + di].88h ax,[bp][di][79]
Folosirea prefixelor de segment permite asignarea unui alt registru segment decit cel implicit. Prefixul de segment este un octet care apare inaintea codului instructiunii şi care identifica explicit registrul de segment folosit. în textul surSă se scrie un registru de segment, urmat de doua puncte inaintea operandului 43
aflat în memorie. Exemplu: mov ax,ds:[bp][si] adc ax,cs:alfa[di][bx + 55h] mov bx,ss:[bp]
Tabelul urmator sintetizeaza modurile de adresare şi registrul segment implicit: Modul de adresare imediat direct registru indirect bazat indexat bazat indexat
Formatul operandului constanta variabila BX BP SI DI variabila[BX] variabila[BP] Variabila[SI] variabila[DI] Variabila[BX][SI] variabila[BX+DI] variabila[BP+SI] variabila[BP+DI]
Registrul segment implicit ----DS DS SS DS DS DS SS DS DS DS DS SS SS
b) Moduri de adresare pe 32 de biti Posibilitatile de specificare ale operanzilor în cazul procesoarelor pe 32 biti sint mult mai multe. în acest caz deplasamentul este o valoare imediata pe 8 sau 32 de biti, registrul de baza este orice registru general de 32 biti, registru de index poate fi orice registru generat de 32 biti, cu exceptia registrului EPS. în modurile de adresare pe 32 biti apare notiunea de factor de scala, care este un intreg ce poate avea valoarea 1,2,4 sau 8, valoare cu care poate fi inmultit indexul. Cele 9 moduri de adresare sint: Adresare directa – adresa efectiva a operandului face parte din instructiune, putind fi reprezentata pe 8, 16, sau 32 biti.
44
Exemplu: dec dword ptr[1265h] adc eax,alfa
Adresare indirecta prin registre – adresa efectiva a operandului este continuta intr-unul din registrele generale. Exemplu: mov [edi], sub [edi],
eax ebx
Adresare bazata – adresa efectiva a operandului este formata din continutul unui registru de baza la care se poate adauga un deplasament. Exemplu: add ecx,[eax + 0a4h]
Adresare indexata – adresa efectiva a operandului este formata din continutul unui registru de index la care se poate aduga un deplasament. Exemplu: inc word ptr alfa[edi]
Adresare indexata cu factor de scala – adresa efectiva a operandului se obtine din continutul unui registru de index, inmultit cu un factor de scala la care se poate aduna un deplasament. Exemplu: mul byte ptr sir[edi*4][126h]
Adresare bazata indexata – adresa efectiva a operandului se formeaza prin adunarea continutului unui registru de baza la continutul unui registru de indexare. Exemplu: add eax,[esi][ebx]
Adresare bazata indexata cu factor de scala – adresa efectiva a operandului este formata din continutul unui registru de baza la care se adauga continutul unui registru de index inmultit cu un factor de scala. Exemplu: sub eax,[ecx][edx*8]
Adresare bazata, indexata cu deplasament – adresa efectiva a 45
operandului se obtine prin adunarea continutului unui registru de baza cu continutul unui registru de indexare şi a unui deplasament. Exemplu: adc edx,[esi][ebp+2163h]
Adresare bazata indexata cu factor de scala şi depasament – adresa efectiva a operandului se obtine prin adunarea continutului unui registru de baza la continutul unui registru de index multiplicat cu un factor de scala şi a unui deplasament. Exemplu: mov alfa[esi*8][edp+0a3bh] , eax
Factorul de scala este util la preluarea tablourilor de date, permitind ca indicele tabloului sa coincida cu continutul unui registru de indexare. De ex. instructiunea în C: long int şir [25] ; for ( i = 0 ; i < 25 ; i + + ) sir [i] + = 65 h ;
se poate scrie în asamblare: mov cx,25 xor esi,esi reia: add sir[esi*4],65h inc esi loop reia
Registrul esi are aceeasi semnificatie ca şi indicele programul_C.
i din
3 Desfasurarea lucrarii de laborator 3.1 Să se editeze, asambleze, vizualizeze şi comenteze programul: .model small .stack 20h .data alfa DW 3 DUP(?) .code begin: mov ax,@data mov ds,ax ;incarca adresa de segment de date mov ax,17 ; adresare indirecta a operandului sursa mov ax,10101 b ; mov ax,11 b ; mov ax,21 o ; mov alfa,ax ; Adresare directa a operandului destinatie 46
mov cx,ax ; Interschimba registrele ax şi bx mov ax,bx ; Folosind registrul cx mov ax, cx ; xchg ax,bx ; Interschimba direct cele 2 registre. mov si, 2 mov alfa[si],ax ; Adresare relativa cu registrul şi mov si, 2 mov bx, offset alfa ; Adresare imediata a
;operandului sursa lea mov mov mov mov mov mov mov mov mov
bx,alfa ; Acelasi efect cx,[bx][si] ; Adresare bazata indexata a sursei cx,alfa.2 ;Adresare directa a sursei, acelasi efect cx,alfa[2] ;Acelasi efect cx,[alfa+2] ;Acelasi efect di,4 byte ptr[bx][di],55h si, 2 bx, 3 alfa[bx][si], 33h ;Adresare bazata indexata
mov mov mov mov mov int end
alfa[bx+si],33h ;Notatii echivalente [alfa+bx+si],33h [bx][si].alfa,33h [bx][si]+alfa,33h ax,4c00h 21h begin
;relativa a destinatiei
3.2 Fie n şi p numarul de litere al numelui şi prenumelui dumneavoastra, se cere: a) Să se reprezinte în binar, octal şi hexazecimal numerele: - intregii npn şi – npn pe octet şi cuvant; - intregii BCD : npnp şi - npnp; - valorile reale : npnp . npnp şi - npnp . npnp; - pointerul npnp np - sirul de caractere ce formeaza numele şi prenumele dumneavoastra. b) Să se scrie programul care genereaza aceste date; c) Să se asambleze şi să se interpreteze rezultatele. 4 Probleme propuse 47
1. Se considera trei valori consecutive reprezentate pe octet/cuvant. Să se permute circular cu o pozitie la stinga/dreapta cele trei valori. 2. Să se incarce intr-o variabila pointer valoarea propriei adrese. 3. Se considera trei cuvinte de memorie. Să se introduca valoarea 0aah în octeti superiori/inferiori ai celor trei cuvinte. 4. Se considera un şir de 25 de cuvinte incepind de la adresa sir. Să se genereze la adresa adr – şir adresa completa a sirului sub forma de offset şi segment, şi să se încarce în elementul al 25 – lea al şirului, valoarea 0abch. 5 Continutul referatului Referatul va contine pentru 3.1, 3.2 şi una din problemele propuse: - enuntul problemei; - proiectarea programului (schema logica şi programul realizat); - listingul comentat.
48
Lucrare de laborator nr. 3 Programe liniare 3.1 Scopul lucrării: Lucrarea prezinta instructiunile pentru transferuri de date, instructiuni în aritmetica binara şi în aritmetica BCD. 3.2 Modul de lucru: Se vor efectua toate aplicaţiile din lucrare în programul TASM. Se vor preda darile de seama cu rezultatele obţinute. 3.3 Noţiuni teoretice Instructiunile de transfer permit copierea unui octet sau cuvant de la sursa la destinatie. Destinatia poate fi un registru, locatie de memorie sau un port de iesire, iar sursa poate fi un registru, o locatie de memorie, constante sau port de intrare. Ca regula generala destinatia şi sursa nu pot fi ambele locatii de memorie. în specificarea sursei şi destinatiei se vor folosi notatiile: a) segment: offset pentru adrese fizice; b) (x) paranteze rotunde pentru a desemna “continutul lui x”. OBS. Instructiunea de transfer nu modifica indicatori de conditie (flagurile) cu exceptia instructiunilor SAHF şi POPF.
3.3.1 Instructiuni de transfer Instructiunea MOV (Move Data) Forma generala a instructiunii Mov este: mov dest, scr ; (dest) ← (sursa) realizeaza transferul informatiei de la adresa efectiva data de sursa la dest. Exemplu: mov ax, alfa; transfera continutul adresei alfa în ax mov bx, offset alfa; transfera adresa efectiva alfa în bx mov al, 75h; transfera 75h în al mov cx; [100]; transfera continutul adresei 100 în cx 49
mov [di],bx; transfera continutul lui bx la adresa continuta în di mov byte ptr alfa,[bx]; pune continutul octetului de la adresa data de bx la adresa alfa
Instructiunea XCHG ( Exchange Data ) Interschimba sursa cu destinatia. Forma generala: XCHG dest, sursa Restrictii: - registrele de segment nu pot aparea ca operanzi; - cel putin un operand trebuie sa fie un registru general. Exemple: xchg xchg xchg xchg
al,ah alfa,ax sir[si],bx cs:[bx][si],ax
Interschimbarea continutului a doi operanzi din memorie op1 şi op2 se poate face prin secventa de instructiuni: mov xchg mov
reg, op1 reg, op2 op2, reg
Instructiunea XLAT (Translate) Forma generala: XLAT Instructiunea nu are operanzi, semnificatia fiind: (al)← ds: ((bx)+(al))
adica se transfera în al continutul octetului de la adresa efectiva: (bx)+(al).
Instructiunea se foloseste la conversia unor tipuri de date, folosind tabele de conversie, adresa acestor tabele se introduce în bx, iar în al se introduce pozitia elementului din tabel. De exemplu: conversia unei valori numerice cuprinsa intre 0 şi 15 în cifrele hexazecimale corespunzatoare, se poate face prin: Tabel DB '0123456789abcdef'' . . . . . . . . . . lea bx, tabel
50
mov al,11 xlat
In al se va depune cifra hexazecimala b. Instructiunea în (Input Data) Executa o citire de la portul de intrare specificat 8 sau 16 biti, dupa cum se specifica registrul al sau ax sau alte registre generale, pentru noile procesoare. Forma generala: IN dest, port unde: - dest este registrul al sau ax (noile procesoare accepta şi alte registre în locul lui al, respectiv ax); - port este o constanta cuprinsa intre 0 şi 255, sau registrul dx. Instructiunea OUT (Output Data) Executa o scriere la portul de iesire specificat de 8 sau 16 biti, dupa cum se specifica registrul al sau ax. Forma generala : OUT dest, port unde: - destinatie este registrul al sau ax; - port este o constanta cuprinsa intre 0 şi 255 sau registrul dx. Instructiunea LEA (LOAD Effective Address) Are ca efect incarcarea adresei efective (offsetul) intr-un registru general. Forma generala: LEA reg, sursa unde: - sursa -este un operand aflat în memorie, specificat printr-un mod de adresare ; - reg- este un registru general.
51
Exemplu: lea lea
bx,alfa si,alfa [bx][si]
Acelasi efect se obtine folosind operandul OFFSET în instructiunea MOV: mov mov
bx,offset alfa si,offset alfa [bx][si]
Instructiunea LSD (Load Data Segment) Forma generala: LSD reg, sursa unde: - reg -este un registru general de 16 biti; - sursa -este un operand de tip double – word aflat în memorie, care contine o adresa completa de 32 biti. Are ca efect transferul unei adrese complete în perechea de registre ds şi reg specificat în instructiune, adica: (reg) (ds)
← ←
((sursa)) ((sursa) + 2)
Exemplu: alfa db 25 adr_alfa dd alfa ..................... lds si, adr-alfa mov byte ptr [si], 75 ......................
Instructiunea LES (Load Extra Segment) Forma generala : LES seg, sursa unde: - seg - este un registru general; - sursa - este un operand de tip dd. Efectul instructiunii este urmatorul: în registru se incarca offsetul operandului sursa iar în registrul es se incarca segmentul (adresa de segment) aflat la adresa sursa + 2, adica: 52
(reg) (es)
← ←
((sursa)) ((sursa) + 2)
Exemplu: b dw 3467h adr_b dw b .................. les di, adr – b mov word ptr es: [di] , 75
Instructiunile LDS şi LES pot fi folosite la exploatarea tabelelor de adrese. Fie tabela de adrese: tab_adr dd R1, R2, R3, R4, R5 si dorim sa incarcam în ax continutul adresei Ri, a carei indice este dat de registrul cx. Secventa de instructiuni: mov mov mov lds mov
bx,cx bx,bx ; se dubleaza indicele 2 cx bx,bx ; se dubleaza valoarea lui bx, adica 4 cx si,tab_adr[bx] ; incarca în şi adresa Ri ax,ds:[si]; incarca indirect valoarea continuta în Ri
................. incarca în ax continutul adresei Ri. O adresa fizica ocupa 4 octeti, ca atare valoarea continuta în cx trebuie inmultita cu 4, operatie realizata prin doua instructiuni add bx, bx Instructiunea LAHF (Load AH with FLAGS) Instructiunea incarca în registrul AH octetul dat de partea cea mai putin semnificativa a registrului FLAGS, ce contine indicatorii. Instructiunea nu are operanzi. AH ← FLAGS 0÷7 Instructiunea SAHF (Store AH into Flogs) Instructiunea incarca în registrul FLAGS, în octetul cel mai putin semnificativ continutul registrului AH, adica:
53
FLAGS ← (AH) 0÷7 Instructiunea nu are operanzi. 3.3.2 Aritmetica binara Aceste instructiuni modifica continutul registrului FLAGS. Instructiunea ADD (Add) Forma generala: ADD dest, sursa ; (dest) ← (dest) + (sursa) unde: - dest poate fi un registru general sau o locatie de memorie; - sursa poate fi un registru general, o locatie de memorie sau o constanta. Cei doi operanzi nu pot fi simultan locatii de memorie. Operatia de poate efectua pe octet sau pe cuvant. Cei doi operanzi trebuie sa aibe aceeasi dimensiune( acelasi tp). în caz de ambiguitate se va folosi operatorul PTR. Indicatorii afectati sunt: AF, CF, PF, SF,, ZF şi OF Exemple: add add add add add add add add
ax, 5 bl, 5 ax, bx word ptr [Bx], 75 alfa, ax alfa, 5 byte ptr [si], 75 byte ptr alfa, 75
Instructiunea ADC (Add with Carry) Forma generala: ADC dest, sursa ; (dest) ← (dest) + (sursa) + (CF) unde dest şi sursa au aceeasi semnificatie ca la instructiunea ADD, iar CF este Carry Flag. Instructiunea aduna continutul dest cu continutul sursei şi cu bitul de transport CF. Indicatorii afectati sunt aceeasi de la instructiunea ADD. 54
Operatia ADC se foloseste la adunari de operanzi pe mai multe cuvinte, operatie în care poate apare transport de care trebuie Să se tina seama. Exemplu: Să se adune doua numere op1, op2 în dubla precizie (pe 2 cuvinte). op1 dd 12345678h op2 dd 0abcdefgh reg dd ? ................................... mov ax, word ptr op1 add ax, word ptr op2 mov word ptr rez, ax mov ax, word ptr op1+2 adc ax, word ptr op2+2 ; se considera eventualul transport mov word ptr+2 rez, ax
Instructiunea SUB (Substrat) Forma generala: SUB dest, sursa ; (dest) ← (dest) – (sursa) unde dest şi sursa au aceeasi semnificatie ca la instructiunea ADD. Indicatorii afectati sunt cei specificati la ADD. Instructiunea SBB (Substrat with Borrow) Forma generala: SBB dest, sursa ; (det) ← (dest) – (sursa) – (CF) unde semnificatia dest, sursa şi CF sunt cele prezentate la ADC. Instructiunea SBB ia în considerare eventualul imprumut. Exemplu: op1 op2 rez . . mov sub mov mov sbb
dd 12345678h dd 0abcdefgh90h dd ? . . . . . . . . . . . ax, word ptr op1 ax, word ptr op2 word ptr rez, ax ax, word ptr op1 + 2 ax, word ptr op2 + 2 ; se considera eventualul
imprumut 55
mov word ptr rez + 2,ax
Instructiunea INC (Increment) Forma generala: INC dest ; (dest) ← (dest) + 1 unde dest este un registru general, un operand din memorie de tip octet sau cuvant. Semnificatia fiind operandul dest este incrementat cu unu. Indicatorii afectati sunt AF, PF, SF, ZF, OF. Exemple: inc inc uic
alfa bl word ptr [Bx] [Si]
Instructiunea DEC (decrement) Forma generala: DEC dest ; (dest) ← (dest) – 1 unde dest are aceeasi semnificatie ca dest de la instructiunea INC. Aceeasi indicatori ca la INC sunt afectati. Instructiunea NEG (Negate) Forma generala: NEG dest : (dest) ← 0 – (dest) schimbare de semn unde dest este un operand pe 8 sau 16 biti ce poate fi un registru general sau o locatie de memorie. Instructiunea afecteaxa indicatorii AF, CF, PF, SF, OF şi ZF. Exemplu: alfa db 75 . . . . . . . . . . . . mov al,alfa neg al mov alfa,al ; la adresa alfa avem -75 sau neg alfa
Instructiunea CMP (Compare) Forma generala: 56
CMP dest, sursa ; (dest) – (sursa) Instructiunea realizeaza o operatie de scadere intre cei doi opranzi, fara a modifica operandul dest sau sursa cu pozitionarea indicatorilor de conditie. Indicatorii afectati sunt: AF, CF, PF, SF, ZF şi OF. Aceasta instructiune se foloseste impreuna cu instructiunea de salt conditionat. Exemple: cmp cmp
ax, alfa[Bx][Si] [Si], 0
Instructiunea CBW (Convert Byte to Word) Are ca efect extinderea bitului de semn (AL7) din AL la intreg registru AH, adica: daca Al7 = 0 atunci (ah) ← 0 altfel (ah) ← 1
Instructiunea nu are operanzi şi nu afecteaza indicatorii de conditie. Exemplu: Se cere să se adune un numar intreg cu semn reprezentat pe octet cu un numar intreg cu semn pe cuvant. a db -75 b dw 188 c dw ? . . . . . . . . . mov al, a cbw ; converteste octetul la cuvant add ax, b mov c, ax . . . . . . . . . .
Instructiunea CWD (Convert Word to Double Word) Are ca efect extinderea bitului de semn din AX (AX15) la intreg registrul DX, obtinandu-se astfel AX pe 32 de biti, adica: daca (AX15) = 0 atunci
57
(dx) ← 0 altfel (dx) ← 1 Instructiunea nu are operanzi şi nu afecteaza indicatorii de conditie. Exemplu. Se cere diferenta dintre un operand reprezentat pe 2 cuvinte (DP) şi unul reprezentat pe cuvant (SP) dp dd 12345678h sp dw 0abcdh rez dd ? . . . . . . . . . . . . . . . . mov ax SP cwd ax ; operandul SP reprezentat în DX : AX mov bx, ax ; salveaza ax în bx mov ax, word ptr DP sub ax, bx mov word ptr rez,ax mov ax, word ptr DP + 2 sbb ax, dx ; ia în considerare eventualul transport mov word ptr REZ + 2
Instructiunea MUL (Multiply) Forma generala: MUL sursa unde sursa poate fi un registru sau o locatie de memorie de 8 sau 16 biti. Rezultatul se obtine pe un numar dublu de biti (16 sau 32). Operatia realizata este produsul intre acumulator şi sursa cu depunerea rezultatului în acumulatorul extins (ax pe octet sau dx:ax pe cuvant). Cei doi operanzi se considera numere fara semn. Daca sursa este pe octet avem: (AX) ← (AL) * (sursa) iar daca sursa este pe cuvant avem: (DX : AX) ← (AX )* (sursa) Afecteaza indicatorii CF şi OF, ceilalti sunt nedefiniti. Exemplu.
58
a db 10h b dw 100h c dw ? d dd ? ........................... mov al, 20h mul a ; (ax)←(al)*a mov c, ax ; depune rezultatul pe cuvant mov ax, 10h mul b ; (dx:ax) ←(ax)*b mov word ptr d, ax ; depune rezultatul pe dublu cuvant mov word ptr d+2, dx ..........................................
Instructiunea IMUL (Integer Multiply) Forma generala: IMUL sursa Instructiunea este similara cu MUL, deosebirea constand în faptul ca cei doi operanzi se considera numere cu semn. Afecteaza indicatorii CF şi OF, restul sunt nedefiniti. Exemplu: alfa db – 93 beta dw 143 rez dd ? ...................................... mov al, alfa cbw ; extensia de semn în ah mul beta (dx:ax) ←(ax)*(beta) mov word ptr rez, ax mov word ptr rez+2, dx
Intructiunea DIV (Divide) Forma generala: DIV sursa unde sursa este un registru sau o locatie de memorie, reprezentata pe octet sau cuvant.
59
Instructiunea realizeaza impartirea fara semn intre deimpartit şi impartitor. Daca impartitorul (sursa) este reprezentat pe octet atunci deimpartitul este AX şi rezultatul este: catul în al iar restul în ah, adica: DIV sursa
; (al) ←(ax)/(sursa) ; (ah) ←restul impartirii (ax)/(sursa)
Daca impartitorul (sursa) este reprezentat pe cuvant atunci deimpartitul este considerat în DX şi AX, catul se obtine în AX iar restul în DX, adica DIV sursa ; (ax) ←catul impartirii (dx:ax)/(sursa) ; (dx) ←restul impartirii (dx:ax)/(sursa) Toti indicatorii nu sunt definiti. Operatia de impartire poate conduce la depasiri, daca catul depaseste valoarea maxima reprezentabila pe 8, respectiv pe 16 biti sau daca impartitorul este 0. Instructiunea IDIV (Integer Divide) Forma generala IDIV sursa Semnificatia instructiuni şi a operandului sursa este aceeasi ca la instructiunea DIV, cu diferenta ca operanzii sunt considerati numere cu semn, deci impartirea se face cu semn. Indicatorii sunt nedefiniti. Operatia poate conduce la depasiri. 3.3.3 Aritmetica BCD Instructiunea AAA(ASCII Adjust for Addition) Instructiunea nu are operanzi şi executa corectia acumulatorului AX, dupa operatii de adunare cu numere în format BCD despachetati. Semnificatia este: daca (AL0:3) > 9 sau (AF) = 1, atunci { (AL) ← (AL) + 6 (AH) ← (AH)+1
60
(AF) ←1 (CF) ←1 (AL) ← (AL) AND 0FH } Indicatorii afectati : AF, CF, restul nedefiniti. Exemplu: mov ax, 408h mov dx, 209h add ax, dx AAS ;
; (ax)=040dh (ax)=0503h
Instructiunea AAS(ASCII Adjust for Subtraction) Instructiunea nu are operanzi şi executa corectia acumulatorului AX, dupa operatii de scadere cu numere în format BCD despachetati. Semnificatia este: daca (AL0:3) > 9 sau (AF) = 1, atunci { (AL) ← (AL) - 6 (AH) ← (AH) - 1 (AF) ←1 (CF) ←1 (AL) ← (AL) AND 0FH } Indicatorii afectati : AF, CF, restul nedefiniti. Exemplu: mov ax, 408h mov dx, 209h add ax, dx ; (ax)=04ffh AAA ; (ax)=0109h
Instructiunea DAS (Decimal Adjust for Substraction) Instructiunea nu are operanzi şi executa corectia zecimala a acumulatorului AL, dupa operatii de scadere cu numere în format BCD impachetat. Semnificatia este: daca (AL0:3) > 9 sau (AF) = 1, atunci { (AL) ← (AL) - 6
61
(AF) ← 1 } daca acum (AL4:7) > 9 sau CF = 1, atunci { (AL) ← (AL) - 60H (CF) ← 1 } Indicatorii afectati : AF, CF, PF, SF, ZF. Indicatorul OF este nedefinit. De exemplu, ia urma secventei: MOV SUB DAS
AL, 52H AL, 24H ; AL = 2EH ; AL = 28H
se obtine în AL rezultatul corect 28H. Instructiunea AAM(ASCII Adjunct for Multiply) Instructiunea nu are operanzi şi efectueaza o corectie a acumulatorului AX, dupa o inmultire pe 8 biti cu operanzi în format BCD despachetati. Semnificatia este urmatoarea: (AH) ← (AL) / 10 (AL) ← (AL) MOD 10 Indicatori afectati: PF, SF, ZF, restul nedefinite. De exemplu mov al, 7 mov bl, 9 mul bl ; 0036h AAM ; 0504h Instructiunea AAD(ASCII Adjunct for Division) Instructiunea nu are operanzi şi efectueaza o corectie a acumulatorului AX, inaintea unei impartiri a doi operanzi în format BCD despachetati. Semnificatia este urmatoarea: (AL) ← (AH) * 10 + (AL) 62
(AH) ← 0 Indicatori afectati: PF, SF, ZF, restul nedefinite. De exemplu mov ax, 305h mov bl, 2 AAD ; (ax)=23h div bl ; (al)=11h
(ah)=1
3.4 Exemple rezolvate şi comentate Exemplul 1. Acest exemplu prezinta citeva tehnici de adresare specifice procesoarelor din familia 8086/88: TITLE exemplul_1 .MODEL SMALL .STACK 10h .DATA alfa DW 3 DUP(?) .CODE begin: mov ax,@DATA mov ds,ax mov ax,17 ; Adresare imediata a operandului
; sursa care este o constanta zecimala mov ax,10001b ; Sursa este o constanta binara mov ax,11h ; Sursa este o constanta hexa mov alfa,ax ; Adresare directa a operandului ; destinatie mov cx,ax ; Interschimba continuturile mov ax,bx ; registrelor ax şi bx mov bx,cx xchg ax,bx ; Acelasi efect cu secventa anterioara mov si,2 mov alfa[si],ax ; Adresare relativa cu registrul si
; a operandului destinatie mov si,2 mov bx,OFFSET alfa;
Adresare imediata a ; operandului sursa (adresa variabilei alfa) ; datorita operatorului OFFSET lea bx,alfa ; Aceasta instructiune are acelasi 63
; efect cu cea anterioara cu toate ca sursa este adresata direct mov cx,[bx][si] ; Adresare bazata indexata a sursei mov cx,alfa+2 ; Aceasta instructiune are acelasi ; efect cu cea anterioara, sursa ; fiind insa adresata direct mov cx,alfa[2] ; Notatii echivalente pentru mov cx,[alfa+2] ; instructiunea anterioara mov di,4 mov [bx][di],55h
; Se va semnala eroare deoarece nu ; s-a precizat tipul destinatiei care este o variabila anonima mov BYTE PTR [bx][di],55h; Se va folosi aceasta ; varianta cind se doreste o adresare la nivel de octet mov BYTE PTR alfa+4,55h ; Aceasta instructiune are ; acelasi efect cu cea anterioara, destinatia fiind insa adresata ; direct. Desi alfa este definit cu DW, operatia este ; realizata la nivel de octet mov si,2 mov bx,3 mov alfa[bx][si],33h
; Adresare bazata indexata ; relativa a operandului destinatie mov alfa[bx+si],33h ; Notatii echivalente pentru mov [alpha+bx+si],33h ; instructiunea anterioara mov [bx][si].alfa,33h mov [bx][si]+alfa,33h END begin
Pentru exemplificari s-a folosit instructiunea mov în diferite variante de adresare: registru la registru, din memorie în registru şi din registru în memorie. Exemplul 2. Se considera un vector de trei componente, fiecare componenta avind dimensiunea de un cuvint. Să se permute circular elementele vectorului cu o pozitie la stinga: TITLE DOSSEG .MODEL .STACK .DATA vect DW
exemplul_2 SMALL 10h 100h,200h,300h 64
.CODE start: mov ax,@DATA ; mov ds,ax ; mov dx,vect ; mov mov mov mov mov END
Initializarea registrului de segment ds Salvare în dx a primei ; componente a vectorului ax,vect+2 ; Transfera a doua vect,ax ; componenta în prima ax,vect+4 ; Transfera a treia vect+2,ax ; componenta în a doua vect+4,dx ; Transfera prima ; componenta în ultima
start
Exemplul 3. Să se incarce intr-o variabila pointer valoarea propriei adrese, sub forma de offset şi segment. TITLE exemplul_3 .MODEL SMALL .STACK 10h .DATA var_ptr DD ?
; Directiva DD are ca efect generarea sau ; rezervarea unor entitati pe 32 de biti .CODE begin: mov mov mov mov
ax,@DATA ds,ax ax,OFFSET var_ptr WORD PTR var_ptr,ax
; Operatorul OFFSET selecteaza componenta de ; offset a adresei unei variabile mov ax,SEG var_ptr mov WORD PTR var_ptr+2,ax
; Operatorul SEG selecteaza componenta de ; segment a adresei unei variabile END begin
Exemplul 4. Se considera un vector de trei componente cuvinte. Să se introduca valoarea 55h în octetii superiori ai elementelor vectorului. TITLE
exemplul_4 65
.MODEL SMALL .STACK 10h .DATA val EQU 55h vect DW 111h,222h,333h .CODE start: mov ax,@DATA mov ds,ax ; Se incarca valoarea mov al,val
; dorita în registrul al mov BYTE PTR vect[1],al ; Se transfera mov BYTE PTR vect[3],al ; valoarea in mov BYTE PTR vect[5],al ; octetii
; superiori ai elementelor vectorului END start
Exemplul 5. Se considera un şir de 50 de cuvinte incepind de la adresa sir. Să se genereze la adresa adr_str adresa completa a sirului sub forma de offset şi segment şi să se incarce în elementul al 25-lea al sirului valoarea 100h. TITLE .MODEL .STACK .DATA nr_elem şir adr_str
exemplul_5 SMALL 10h EQU 25 DW 50 DUP(?) DD sir
; La adresa adr_str se genereaza adresa completa a ; variabilei şir sub forma de offset şi segment, offset-ul ; fiind memorat la adresa cea mai mica .CODE begin: mov ax,@DATA mov ds,ax lds bx,adr_str
; Se incarca în registrul bx ;adresa de offset a variabilei şir şi în registrul de segment ds ; adresa de segment a variabilei sir mov si,(nr_elem-1)*(TYPE sir)
; Operatorul TYPE intoarce numarul de octeti ; ai unei componente a sirului sir. Expresia 66
; indicata determina adresa primului octet al ; componentei care se vrea accesata mov WORD PTR [bx][si],100h END begin
Exemplu: Să se adune doua numere folosind diferite moduri de adresare. Data a b c
segment dw 75h dw ? dw ?
; primul operand ; al doilea operand ; rezultatul
data ends cod segment assume cs:cod,ds:data start: mov ax,data
mov ds,ax ; incarca în ds adresa de segment de date data mov b,0a3bh ; transfera la adresa b valoarea 0a3bh
; operandul sursa este adresat imediat ; operandul destinatie este adresat direct la memorie mov bx,offset a ; incarca în bx adresa variabilei a ; operandul destinatie este adresat direct la registru mov ax,[bx]; incarca în ax continurul adresei aflate în bx, adica ; valoarea variabilei a ; operandul sursa adresat indirect add ax, b ; aduna la ax valoarea variabilei b mov di, offset c ; incarca în di adresa lui c mov [di], ax ; transfera la adresa lui di, adica în c ; continutul lui ax mov ax,4c00h ; incarca în ah valoarea 4c, functia... int 21h ; intrerupere cod ends end start
Exemplul 6. Să se evalueze expresia x+2*y-70, depunind rezultatul la adresa z, unde x, y, z sint intregi reprezentati pe cite un cuvint. TITLE .MODEL
exemplul_6 SMALL
67
.STACK 10H .DATA x DW 100 y DW -10 z DW ? .CODE begin: mov ax,@DATA mov ds,ax ; mov ax,x
Se foloseste ax ca ; acumulator
add add sub mov END begin
ax,y ax,y ax,70 z,ax
Exemplul 7. Să se efectueze operatia: dp2