Documente Academic
Documente Profesional
Documente Cultură
Limbaj Asamblare
Limbaj Asamblare
20
16
30h
0
0
;
;
;
;
;
20 =
16 =
48 =
aici
aici
14h
10h
30h
vom pune a+b
vom pune a+b+c
_TEXT segment
assume cs:_TEXT
assume ds:_DATA
start:
; de aici incepe executia programului
mov ax, _DATA ; incarcam in ds adresa de segment a segmentului
mov ds, ax
;
de date. Nu putem face direct (mov ds,
_DATA
;
nu are operanzi compatibili (vom vedea
mai
;
tarziu de ce.
; de aici incepe programul propriu-zis
mov
add
mov
add
mov
al, a
al, b
s_ab, al
al, c
s_abc, al
; al=s_ab=a+b
; al=s_abc=a+b+c
; terminam executia programului
==============
Pentru "compilare" veti da comenzile
tasm /zi
nume
urmata de
tlink /v
nume
Important!
1. Numele programului se va da fara extensie.
2. Executabilele tasm si tlink se gasesc in acelasi loc cu mediul Turbo Pascal sau
Borland C++
Rezultatul celor doua comenzi de mai sus este un program executabil (.exe).
Depanarea programelor scrise in asamblare (si pentru inceput, chiar urmarirea executiei
lor) se face cu ajutorul programului Turbo Debugger. Comanda este:
nume
td
Urmarirea programului cu Turbo Debugger se va face in fereastra CPU (se deschide din
meniul View|CPU). Aici avem
Putem pozitiona zona vizibila din program, zona de date si stiva folosind comanda Go to
din meniul local al ferestrei (meniul activat cu Alt-F10).
De asemenea, putem afla sau modifica valoarea unei variabile, folosind fereastra de
dialog Evaluate/Modify (deschisa cu Ctrl-F4)
Exercitii
1. Generati program executabil din sursa prezentata in aceasta pagina
2. Urmariti pas cu pas executia programului (in Turbo Debugger). Urmariti continutul
registrelor ax si ip in acest timp.
400
100000
65530
0
; aici vom pune a+b
0
; aici vom pune a+b+c
_TEXT segment
start:
mov bx, _DATA
mov ds, bx
_DATA
mai
mov
add
add
mov
mov
cx, word
cx, word
bx, word
word ptr
word ptr
mov
cwd
add
adc
mov
mov
ax, c
tarziu de ce.
cx, ax
bx, dx
word ptr s_abc, bx ; bx:cx=s_abc=a+b+c
word ptr s_abc+2, cx
end start
266 (010Ah).
Adunari si scaderi
Putem folosi oricare dintre registrii numiti mai sus, precum si variabile auxiliare.
Exemplu: sa se evalueze expresia r=(a+b)-(c+d)-(e+20) unde toate veriabilele sunt
reprezentate pe 16 biti cu semn.
Rezolvare
Date:
a
b
c
d
e
r
dw
dw
dw
dw
dw
dw
1000
500
20
300
-300
?
Cod:
mov
add
mov
add
sub
ax,
ax,
si,
si,
ax,
a
b ; ax = a+b
c
d ; si = c+d
si ; ax = (a+b) - (c+d)
mov
add
sub
mov
si, e
si, 20 ; si = e+20
ax, si ; ax = (a+b) - (c+d) -(e+20)
r, ax
Aritmetica pe 32 de biti
Daca avem de adunat/scazut numere reprezentate pe 32 de biti (sau mai multi), nu avem
instructiune de adunare/scadere corespunzatoare. In scopul efectuarii operatiei, vom
aduna cate o "felie" de 16 biti o data. Astfel, vom aduna cei 16 biti mai putin
semnificativi din cei doi operanzi, apoi vom aduna cei 16 biti mai semnificativi din cei
doi operanzi impreuna cu transportul de la "felia" anterioara.
O a doua problema ce apare este faptul ca nu putem transfera 32 de biti o data.
Fie urmatorul exemplu: sa se calculeze r=a+b, unde r, a si b sunt reprezentate pe 32 de
biti.
Rezolvare
Date:
a dd 1000000
b dd 500000
r dd ?
Cod:
mov
mov
add
adc
mov
mov
ax, word
dx, word
ax, word
dx, word
word ptr
word ptr
ptr a
ptr a +2
ptr b
ptr b+2
r, ax
r+2, dx
Constructii folosite:
adresa
componenta lui a.
word ptr a+2 desemneaza un obiect din memorie, tot de 2 octeti (word) de la
adresa egala cu adresa lui a plus 2 (ptr a +2). Acestia sunt octetii al treilea si al
patrulea din componenta lui a, adica cei mai semnificativi 16 biti.
instructiunea add are ca efect retinerea transportului in bistabilul CF (carry flag).
instructiunea adc aduna oeranzii plus valoarea lui CF. De asemenea, noul
transport generat in urma adunarii este scris in CF.
Exercitii
Conversii de lungime
Daca operanzii pentru adunare si scadere nu au lungimile egale este necesara modificarea
lungimii reprezentarii cel putin pentru unul dintre ei.
Lungirea reprezentarii pentru intregii cu semn se face cu ajutorul instructiunilor cbw si
cwd. Lungirea reprezentarilor pentru numere fara semn se face prin completare cu
zerouri.
Exemple
1. r=a-b, r si a fiind reprezentate pe 16 de biti cu semn, iar b pe 8 biti cu semn
Rezolvare
Date:
a dw 2000
b db -4
r dw ?
Cod:
mov
cbw
mov
sub
mov
al, b
; ax = b
si, a
si, ax ; si = a-b
r, si
Cod:
mov
mov
add
mov
al, b
ah, 0 ; ax = b
ax, b ; ax = a+b
r, ax
Exercitii
1. Calculati r=a+b-c, unde r si b sunt pe 32 de biti cu semn, a este pe 16 biti cu
semn, iar c este pe 8 biti cu semn.
2. Ca la exercitiul precedent, dar numerele sunt reprezentate fara semn.
Inmultiri si impartiri
Trebuie avute in vedere restrictiile de lungime, registrii specifici pentru unii operanzi,
precum si diferenta intre instructiunile pentru numere reprezentate cu semn (imul si
idiv) si fara semn (mul si div).
Exemplu
Sa se evalueze r=(a-b*c)/d, unde a, b, c, d, r vor fi reprezentate pe 16 biti cu semn.
Rezolvare
Date
a
b
c
d
r
dw
dw
dw
dw
dw
1000
-500
30000
10000
?
Cod
mov ax, b
imul c ; dx:ax = b*c
mov bx, dx
mov cx, ax ; bx:cx = b*c , avem nevoie de dx:ax pt. conversia lui a
mov ax, a
cwd ; dx:ax = a
sub ax, cx
sbb dx, bx ; dx:ax = a-b*c
idiv d ; ax = (a-b*c)/d
mov r, ax
Instructiuni conditionale
In limbajul de asamblare nu avem instructiuni conditionale sau bucle structurate. Acestea
trebuie deci simulate folosind instructiuni gen goto sau if ... goto.
Saltul neconditionat se face prin instructiunea jmp. Sintaxa este jmp eticheta. Efectul este
ca urmatoarea instructiune executata este cea care urmeaza punctului marcat prin
eticheta. Eticheta are sintaxa: eticheta: (numele urmat de caracterul doua-puncte).
mov al, 0
mov dep, 0
jmp final
depasire:
mov al, 1
mov dep, al
final:
Tablouri
Declararea tablourilor
Variabilele se declara prin sintaxa:
[nume] db|dw|dd valoare [, valoare ...]
Numele este optional. Daca dam o singura valoare, variabila este simpla. Daca dam mai
multe valori, variabila este de fapt de tip tablou. Asta inseamna ca:
asamblorul rezerva cate 1, 2 sau 4 octeti (in functie de declarare, db, dw, respectiv
dd) pentru fiecare valoare data. Acestia sunt rezervati unul dupa altul, fara spatii.
acestia sunt initializati cu valorile date
numele, daca este prezent, desemneaza intotdeauna adresa de inceput a zonei de
memorie. Prin urmare, prin acel nume se poate referi direct doar primul element.
Pentru restul este necesar sa calculam adresa de inceput a elementului dorit.
Variabilele de tip db pot fi initializate cu un caracter sau sir de caractere date intre
caractere apostrof. Variabilele de orice tip pot fi initializate cu constructia
numar dup (valoare)
aceasta fiind echivalenta cu un sir de lungime numar de valori identice cu valoare. Aceste
constructii pot fi combinate.
Exemple
a dw 10, 13, 16, 3000 ; tablou de 4 cuvinte (8 octeti) cu
; valorile initiale date
b db 'Text', 10, 13 ; tablou de 6 octeti
c db 84, 101, 120, 116, 10, 13 ; tablou de 6 octeti, avand acelasi
; continut ca si b
d dd 100 dup (1) ; tablou de 100 dublu-cuvinte (400 octeti) de
noualea
In toate cazurile, numele dat variabilelor este de fapt o eticheta asociata adresei de
inceput a variabilei.
Folosirea tablourilor
In toate instructiunile in care putem da ca operand o locatie de memorie putem pune si un
element dintr-un tablou. De fapt, operandul este locatia de memorie de la adresa data in
instructiune (daca operandul este o variabila simpla, adresa este de obicei o constanta;
daca operandul este un element dintr-un tablou, adresa se calculeaza ca adresa de inceput
plus indexul inmultit cu dimensiunea elementului (indexul fiind considerat de la 0).
Adresa poate fi data ca:
o constanta
valoarea unuia din regisrtii si, di, bx, bp, plus eventual o constanta
suma dintre: si sau di, bx sau bp, si eventual o constanta
Operatii pe biti
Uneori avem nevoie sa testam sau sa modificam doar valoarea unui singur bit din cadrul
unui octet, sau in general sa efectuam anumite operatii doar asupra unora dintre bitii unui
octet.
In acest scop avem urmatoarele operatii:
Exemple
1. Se cere obtinerea aceluiasi efect ca cel al operatiei cbw.
Rezolvare
0
2.
jz pozitiv
; daca ajungem aici, numarul este negativ
mov ah, 0FFh
jmp final
pozitiv:
mov ah,0
final:
Se da o variabila, a, de tip word. Se cere sa se numere
bitii de 1.
Rezolvare 1
Vom scoate unul cate unul bitii din ax
mov ax, a
mov dx, 0 ;
mov cx, 0 ;
bucla:
shr ax, 1 ;
adc dx, 0 ;
add cx, 1
cmp cx, 16
jb bucla
Rezolvare 2
Codul:
mov ax, bcd-sir_cifre
mov dx, 0
mov bx, 2
div bx
mov cx, ax ; cx=nr. de perechi de cifre
mov si, offset sir_cifre ; si = adresa cifrei curente
mov di, offset bcd ; di=adresa perechii curente
cmp dx, 0
je par
; daca nr. de cifre zecimale este impar, prima o tratam special
mov al, byte ptr [si]
sub al, '0'
mov byte ptr [di], al
inc si
inc di
par:
cmp cx, 0
je final
mov ah, byte ptr [si]
inc si
mov al, byte ptr [si]
inc si
sub ah, '0'
sub al, '0'
; avem acum cifrele in ah si al. Trebuie aduse ambele in al, cea
din
; ah va ocupa primii 4 biti din al
shl ah, 4
or al, ah
mov byte ptr [di], al
inc di
dec cx
jmp par
final:
Observatii
1. O metoda de a pune valoarea 0 intr-un registru este sa se faca xor cu el insusi
(exemplu xor ax, ax pune 0 in ax).
2. shl si shr pot fi folosite pentru inmultirea, repspectiv impartirea la 2. De
exemplu, shl ax, 1 inmulteste cu 2 valoarea din ax. Cum se imparte la 2 un
numar reprezentat cu semn?
3. Spunem ca izolam anumiti bitii dintr-un operand daca punem o vaoare fixata (de
obicei 0) in toti ceilalti biti. Aceasta se face prin and intre operand si o vaoare,
numita masca, ce are 1 pe pozitiile de izoat si 0 in rest.
Exercitii
1. Sa se verifice daca un numar reprezenat pe 16 biti cu semn poate fi reprezentat pe
8 biti cu semn
2. Fie doua variabile, a si b, de tip word. Sa se inlocuiasca bitii 2..5 din a cu bitii 0..3
din b
3. Se da un numar in eprezentare BCD, Sa se calculeze reprezentarea binara
(obsnuita)
=======