Tutorial Limbaj de Asamblare (Assembler) Intel 8086 – Partea 3 – Moduri de adresare

No comments -

Pentru a intelege modul in care datele si variabilele programului sunt utilizate (citite sau modificate), in aceasta parte a tutorialului assembler se analizeaza:

  • Modul de adresare directa in limbaj de asamblare
  • Modul de adresare indirecta in limbaj de asamblare
    • Adresare indexata
    • Adresare bazata
    • Adresare indexata si bazata

Pentru a intelege mai bine conceptele teoretice descrise, in acest tutorial sunt prezentate si exemple care pun in practica modurile de adresare pentru:

  • Citirea unui caracter de la tastatura cu ecou intr-un program scris in limbaj de asamblare (assembler)
  • Afisarea unui caracter pe ecran intr-un program scris in limbaj de asamblare (assembler)
  • Citirea unui sir de la tastatura intr-un program scris in limbaj de asamblare (assembler)
  • Afisarea unui sir pe ecran intr-un program scris in limbaj de asamblare (assembler)



Adresare directa in limbaj de asamblare

  • Registrele sunt initializate cu valori constante

Exemplu:

mov AX, 1234h
  • Numele variabilei este utilizat ca operand in instructiune.

Exemplu:

vector dw 10 dup(5)     ; definire vector cu 10 elemente initializate cu valoarea 5mov  AX, vector          ;copiaza valoarea primului element de tip cuvant din vector in AX
 
mov BX, vector[3]      ;copiaza valoarea cuvantului care incepe de la offset-ul al treilea

ATENTIE, in exemplul anterior cum elementele vectorului incep de la offset cu valoare multiplu de 2, rezulta ca in BX se copiaza valoarea 0500h.

Vectorul numit vector se gaseste in segmentul de date memorat astfel:

DS:0000 05 00 05 00 05 00 05 00 05 00

DS:0008 05 00 00 00 00 00 00 00 00 00

iar instructiunea mov BX,vector[3] copiaza in BX 2 octeti (deoarece vector contine elemente de tip word) insa incepand de la offset-ul 0003 din DS. Deci BX va contine valoarea 0500h.

  • Valoarea offset-ului este utilizata pentru a citi date direct din segmentul DS.

Exemplu:

vector dw 10 dup(5)    ; definire vector cu 10 elemente initializate cu valoarea 5
 
…
 
mov  AX, DS:[00h]    ;copiaza valoarea primului element de tip cuvant din vector in AX
 
mov BX,DS:[08h]    ;copiaza valoarea cuvantului care incepe de la offset-ul 08h

Cand se specifica offset-ul este absolut necesar sa se utilizeze expresia DS:[valoare_offset] pentru ca, daca se scrie instructiunea:

mov AX,[08h]

se copiaza in AX doar valoarea 8h (Veti primi si un WARNING – [Constant] assumed to mean immediate constant.)

Adresare indirecta in limbaj de asamblare


Se utilizeaza unul dintre registrele index SI, DI, BP sau registrul de baza BX. Atentie: utilizarea altor registre va genera eroare: Illegal indexing mode.

Se utilizeaza in general pentru parcurgerea masivelor si pentru a accesa elemente din structuri de date de tip articol.

Utilizarea registrului index SI sau DI pentru adresare indirecta indexata

  • registrul SI este utilizat pentru a retine offset-ul elementului pe care dorim sa-l accesam;
vector dw 1234h,1235h,3222h,4343h,5455h
 
…
 
mov SI, offset vector    ;incarca in SI offset-ul de inceput al vectorului
 
mov AX, [SI]        ;copiaza in AX valoarea primului element, adica 1234h
 
mov CX, [SI+2]    ;copiaza in CX valoarea elementului al doilea, adica 1235h
mov DX,[SI+3]    ;copiaza in DX valoarea 2212h (octetul inferior din 3222h si octetul superior din 1235h)

acelasi lucru se scrie si:

mov SI, offset vector
 
mov AX, [SI]
 
mov CX, [SI][2]
mov DX,[SI][3]
  • registrul SI sau DI este utilizat asemenea unui indice in parcurgerea masivului;
vector db 1,2,3,4,5,6
 
…
 
XOR SI,SI        ; ne asiguram ca SI are valoarea 0
 
mov AL, vector[SI]    ;copiaza in AL valoarea primului element din vector
 
inc SI
 
mov AH, vector[SI]    ;copiaza in AH valoarea elementului secund din vector
 
mov CL,vector[SI+1]    ;copiaza in CL valoarea celui de al treilea element
mov AL,vector[SI][2]    ;copiaza in AL valoarea celui de al patrulea element deoarece SI contine valoarea 1

in cazul in care vectorul are elemente de tip word parcurgerea acestuia se face marind SI cu valoarea 2 de fiecare data:

vector dw 1243,2342,3342,44324,53242,63432
 
…
 
XOR SI,SI        ; ne asiguram ca SI are valoarea 0
 
mov AX, vector[SI]    ;copiaza in AX valoarea primului element din vector
 
inc SI
 
inc SI
 
mov AX, vector[SI]    ;copiaza in AX valoarea elementului secund din vector
 
mov CX,vector[SI+2]    ;copiaza in CX valoarea celui de al treilea element
mov AX,vector[SI][4]    ;copiaza in AX valoarea celui de al patrulea element deoarece SI contine valoarea 2

Utilizarea registrului baza BX pentru adresare indirecta bazata si indexata

  • registrul BX este utilizat pentru adresare indirecta bazata;
vector db 1,2,3,4,5,6
 
…
 
XOR SI,SI        ; ne asiguram ca SI are valoarea 0
 
mov BX, offset vector    ;incarcam in registrul de baza offset-ul de start al vectorului
 
mov AL, [BX][SI]    ;copiaza in AL valoarea primului element din vector
 
inc SI
 
add AL, [BX+SI]    ;aduna in AL valoarea elementului secund din vector
 
add AL, [BX+SI+1]    ;aduna in AL valoarea celui de al treilea element
add AL,[BX][SI][2]    ;aduna in AL valoarea celui de al patrulea element deoarece SI contine valoarea 1

In exemplele anterioare, SI poate fi inlocuit de DI.

Registrul BX este utilizat si pentru a transmite offset-ul unui articol sau masiv ce reprezinta parametru de intrare intr-o procedura. Caracterul de generalitate al unei proceduri impune lucrul in interiorul ei cu offset-ul parametrilor de intrare si nu cu numele lor.

Cand se utilizeaza registrul BX ca registru de baza in adresarile indirecte pentru a memora offset-ul primului octet al structurii respective, adresa segmentului este data de registrul DS. Deci, fiecare element identificat prin [BX] se afla memorat la adresa DS:BX (segment:offset).

In cazul in care se utilizeaza registrul BP pentru adresari indirecte, adresa segmentului este data de registrul SS. Deci BP este utilizat pentru a accesa indirect locatii de memorie din stiva. Din acest motiv, instructiunea

mov CX,[BP]

copiaza in CX, valoarea din stiva aflata la offset-ul dat de BP, adica SS:BP.

Pentru a forta citirea din segmentul DS la offset-ul dat de BP, instructiunea devine

mov CX,DS:[BP]

Alte instructiuni din limbajul de asamblare pentru Intel 8086:

Instructiunea LOOP

  • forma analitica a instructiunii este:

LOOP nume_eticheta

  • decrementeaza registrul CX si sare la eticheta nume_eticheta cu conditia ca valoarea din CX sa fie mai mare decat zero;
  • nu afecteaza nici un flag;
  • instructiunea memoreaza intr-un octet offset-ul etichetei fata de pozitia sa in segmentul de cod; deci, eticheta trebuie sa se gaseasca la o distanta de maxim128 de octeti in interiorul segmentului de cod fata de pozitia instructiunii LOOP;
  • utilizata de obicei pentru a implementa instructiuni de control repetitive;

Exemplu: determinarea sumei elementelor unui vector.

.model small
 
.286
 
.stack 100h
 
.data
 
vector db 1,2,3,4,5,6,7
 
n db 7                ;dimensiunea vectorului
 
suma db 0            ;suma elementelor
 
.code
 
mov AX,@data
 
mov DS,AX
 
xor SI,SI
 
xor CX,CX            ;ne asiguram ca CX are valoarea 0
 
mov CL,n            ;copiem in CL dimensiunea vectorului
 
repeat:                    ;definim eticheta
 
mov AL,vector[SI]
 
add suma,AL
inc SI                ;marim valoarea din SI cu 1 pentru a trece la
;elementul urmator
loop repeat            ;salt la eticheta cat timp CX diferit de 0
 
mov AX,4c00h
 
int 21h
 
end

Instructiunea LEA

  • forma analitica a instructiunii este:

LEA registru, operand

  • incarca in registrul specificat offset-ul operandului;
  • registrul nu poate fi unul dintre registrele de segment;
  • exemplu:
.data
 
vb dw 1234h,1235h
 
.code
 
…
 
mov SI,offset vb    ;incarca registrul SI cu valoarea offest-ului variabilei vb
 
lea DI,vb        ;incarca registrul DI cu valoarea offest-ului variabilei vb
 
…

Exemple – Citirea si afisarea pe ecran

Citirea unui caracter de la tastatura cu ecou intr-un program scris in limbaj de asamblare (assembler).

  • se realizeaza utilizand rutina DOS 21h;
  • registrul AH are valoarea 01h;
  • codul ASCII al caracterului citit este pus in registrul AL;
  • transformarea caracterului citit intr-un numar (cu conditia ca acesta sa reprezinte o cifra) cu valoarea cuprinsa intre 0 si 9 se face scazand din AL valoarea 30h, ce reprezinta codul ASCII al caracterului 0;
  • exemplu:
.data
 
nr db ?
 
.code
 
…
 
mov ah,01h    ;initializare AH cu codul functiei
 
int 21h        ;apel rutina
 
sub al,30h    ;transformare cod ASCII aferent cifrei in valoare intreaga
 
mov nr,al    ;copiere valoare numar
 
…

Afisarea unui caracter pe ecran intr-un program scris in limbaj de asamblare (assembler).

  • se realizeaza utilizand rutina DOS 21h;
  • registrul AH are valoarea 02h;
  • codul ASCII al caracterului citit este pus in registrul DL;
  • afisarea unei valori numerice implica transformarea cifrelor in echivalentul lor ASCII (se adauga la valoarea cifrei valoarea 30h, ce reprezinta codul ASCII al caracterului 0);
  • exemplu:
.data
 
nr db 5
 
caracter db 'g'
 
.code
 
…
 
mov DL,caracter
 
mov ah,02h    ;initializare AH cu codul functiei
 
int 21h        ;apel rutina si afisare caracter <em>g</em> pe ecran
 
mov DL,nr
 
mov ah,02h
 
int 21h        ;apel rutina si afisare pe ecran caracter cu codul ASCII egal cu 5
 
mov DL,nr
 
add, DL,30h    ;obtinere cod ASCII al cifrei din DL
 
mov ah,02h
 
int 21h        ;apel rutina si afisare pe ecran a caracterului <em>5</em>
 
…

Afisarea unei valori numerice mai mari decat 9 pe ecran implica prelucrari prin intermediul carora sa se obtina codul ASCII al tuturor cifrelor din numar.

Afisarea unui sir pe ecran intr-un program scris in limbaj de asamblare (assembler).

  • se realizeaza utilizand rutina DOS 21h;
  • registrul AH are valoarea 09h;
  • adresa de inceput a sirului de caractere trebuie sa se gaseasca in DX; acest lucru se realizeaza prin intermediul instructiunii LEA sau a instructiunilor LES / LDS (descrise in Seminar 1)
  • Important: ultimul caracter din sir trebuie sa fie $ (24h); functia afiseaza sirul pana intalneste primul caracter $
  • exemplu:

...
 
.data
 
mesaj   db "Afisare mesaj !!!","$"
 
.code
 
...
 
mov   AH,09
 
lea   DX,mesaj
 
int   21h
 
...


Citirea unui sir de la tastatura intr-un program scris in limbaj de asamblare (assembler).

  • se realizeaza utilizand rutina DOS 21h;
  • registrul AH are valoarea 0Ah;
  • adresa din segmentul de date (offset-ul) in care se face memorarea sirului citit trebuie scrisa in DX; sirul citit de la tastatura se scrie la adresa DS:DX
  • primul octet de la adresa DS:DX trebuie sa contina numarul maxim n de caractere al sirului (rutina permite citirea de la tastatura doar a n-1 caractere); neinitializarea primului octet cu valoarea n poate conduce la situatiile: acesta are valoarea 0 si nu se citesc caractere sau acesta are o valoarea reziduala mai mare / mica decat lungimea maxima dorita;
  • introducerea sirului la tastatura se incheie cu Enter (0Dh);
  • rutina va scrie in al doilea octet de la adresa DS:DX numarul de caractere efectiv citit de la tastatura;
  • ultimul octet din sir este codul ASCII al tastei Enter (0Dh)
  • exemplu:
.data
vb dw 1234h,1234h,1234h
sir db 5    ;valoare necesara pentru a indica numarul maxim de caractere de citit
.code
mov AX,@data
mov DS,AX
 
mov dx,0006h    ;incarc in DX offset-ul la care incepe scrierea sirului de caractere
mov ah,0ah
int 21h
 
mov AX,4c00h
int 21h
end

,


  1. No comments yet.
(will not be published)

  1. No trackbacks yet.