Documente Academic
Documente Profesional
Documente Cultură
Intro ASM
Intro ASM
Regitrii microprocesorului
Regitrii (sau registrele) microprocesorului reprezint locaii de memorie
speciale aflate direct pe cip; din aceast cauz reprezint cel mai rapid tip de
memorie. Alt lucru deosebit legat de regitri este faptul c fiecare dintre acetia au un
scop bine precizat, oferind anumite funcionaliti speciale, unice. Exist patru mari
MOV BX, 2
MOV DX, 3
ADD BX, DX
ncarc valoarea 2 n registrul BX, valoarea 3 n registrul DX, adun cele dou
valori iar rezultatul (5) este memorat n registrul BX. n exemplul anterior putem
utiliza oricare dintre regitrii de uz general n locul regitrilor BX i DX. n afara
proprietii de a stoca valori i de a folosi drept operanzi surs sau destinaie pentru
instruciunile de manipulare a datelor, fiecare dintre cei 8 regitri de uz general au
propria personalitate. Vom vedea n continuare care sunt caracteristicile specifice
fiecruia dintre regitrii de uz general.
Registrul AX (EAX)
Registrul AX (EAX) este denumit i registrul acumulator, fiind principalul
registru de uz general utilizat pentru operaii aritmetice, logice i de deplasare de
date. Totdeauna operaiile de nmulire i mprire presupun implicarea registrului
AX. Unele dintre instruciuni sunt optimizate pentru a se executa mai rapid atunci
cnd este folosit AX. n plus, registrul AX este folosit i pentru toate transferurile de
date de la/ctre porturile de Intrare/Ieire. Poate fi accesat pe poriuni de 8, 16 sau
32 de bii, fiind referit drept AL (cei mai puin semnificativi 8 bii din AX), AH (cei
mai semnificativi 8 bii din AX), AX (16 bii) sau EAX (32 de bii). Prezentm n
continuare alte cteva exemple de instruciuni ce utilizeaz registrul AX. De remarcat
este faptul c transferurile de date se fac pentru instruciunile (denumite i mnemonice)
Intel de la dreapta spre stnga, exact invers dect la Motorola (vom vedea i alt
exemplu asemntor la scrierea datelor n memorie sub format diferit la Motorola
fa de Intel), unde transferul se face de la stnga la dreapta.
Instruciunea: MOV AX, 1234H ncarc valoarea 1234H (4660 n zecimal) n
registrul acumulator AX. Dup cum spuneam, cei mai puini semnificativi 8 bii ai
registrului AX sunt identificai de AL (A-Low) iar cei mai semnificativi 8 bii ai
aceluiai registru sunt identificai ca fiind AH (A-High). Acest lucru este utilizat
pentru a lucra cu date pe un octet, permind ca registrul AX s fie folosit pe postul a
doi regitri separai (AH i AL). Aceeai regul este valabil i pentru regitrii de uz
general BX, CX, DX. Urmtoarele trei instruciuni seteaz registrul AH cu valoarea
1, incrementeaz cu 1 aceast valoare i apoi o copiaz n registrul AL:
MOV AH, 1
INC AH
MOV AL, AH
Valoarea final a registrului AX va fi 22 (AH = AL = 2).
Registrul BX (EBX)
Registrul BX (Base), sau registrul de baz poate stoca adrese pentru a face
referire la diverse structuri de date, cum ar fi vectorii stocai n memorie. O valoare
reprezentat pe 16 bii stocat n registrul BX poate fi utilizat ca fiind o poriune din
adresa unei locaii de memorie ce va fi accesat. Spre exemplu, urmtoarele
instruciuni ncarc registrul AH cu valoarea din memorie de la adresa 21.
MOV
MOV
MOV
MOV
AX, 0
DS, AX
BX, 21
AH, [ BX ]
SUB CX, 1
JNZ start
Deoarece valoarea iniial a lui CX este 5, instruciunile cuprinse ntre eticheta
start i instruciunea JNZ se vor executa de 5 ori (pn cnd registrul CX devine 0).
Instruciunea SUB CX, 1 decrementeaz registrul CX cu valoarea 1 iar instruciunea
JNZ start determin saltul napoi la eticheta start dac CX nu are valoarea 0. n
limbajul microprocesorului exist i o instruciune special legat de ciclare. Aceasta
este instruciunea LOOP, care este folosit n combinaie cu registrul CX. Liniile de
cod urmtoare sunt echivalente cu cele anterioare, dar aici se utilizeaz instruxiunea
LOOP:
MOV CX, 5
start:
LOOP start
Se observ c instruciunea LOOP este folosit n locul celor dou instruciuni
SUB i JNZ anterioare; LOOP decrementeaz automat registrul CX cu 1 i execut
saltul la eticheta specificat (start) dac CX este diferit de zero, totul ntr-o singur
instruciune.
Registrul DX (EDX)
Registrul de uz general DX (Data register), denumit i registrul de date, poate
fi folosit n cazul transferurilor de date Intrare/Ieire sau atunci cnd are loc o
operaie de nmulire sau de mprire. Instruciunea IN AL, DX copiaz o valoare
de tip Byte dintr-un port de intrare, a crui adres se afl n registrul DX.
Urmtoarele instruciuni determin scrierea valorii 101 n portul I/O 1002:
...
MOV AL, 101
MOV DX, 1002
OUT DX, AL
AX, 0
DS, AX
SI, 33
AL, [ SI ]
AX, 0
DS, AX
DI, 1000
BL, [ DI ]
fi stocate i accesate pe principul LIFO (Last In First Out), drept urmare ultima
valoare stocat n stiv este prima ce va fi citit din stiv. De regul, stiva este
utilizat la apelul unei proceduri sau la ntoarcerea dintr-un apel de procedur
(principalele instruciuni folosite sunt CALL i RET).
RET
Trei_Factorial ENDP
END
Numele Valoare_Factorial i Factorial sunt utilizate pentru definirea a dou
variabile de tip word (pe 16 bii), Trei_Factorial identific numele procedurii
(subrutinei) ce conine codul pentru calculul factorialului, permind apelul su din
alt parte a programului. Ciclare reprezint un nume de etichet, identificnd adresa
instruciunii MOV ax, [Valoare_Factorial], astfel nct instruciunea LOOP folosit
mai jos s poat face un salt napoi la aceast instruciune. Numele de variabile pot
conine urmtoarele caractere: literele a-z i A-Z, cifrele de la 0-9 precum i
caracterele speciale _ (underscore liniu de subliniere), @ (at n englez citit i a
rond sau coad de maimu), $ i ?. Se poate folosi si caracterul punct (.) drept
prim caracter al numelui unei etichete. Cifrele 0-9 nu pot fi utilizate pe prima poziie
a numelui; de asemenea, nu pot fi folosite nume care s conin un singur caracter $
sau ?. Fiecare nume poate fi definit o singur dat (numele sunt unice) i pot fi utilizate
ca operanzi de oricte ori se dorete ntr-un program. Un nume poate s apar ntrun program singur pe o linie (linia respectiv nu mai conine alt instruciune sau
directiv). n acest caz, valoarea numelui este dat de adresa instruciunii sau
directivei de pe linia urmtoare din program. De exemplu, n secvena urmtoare:
...
JMP scadere
...
scadere:
SUB AX, CX
...
urmtoarea instruciune care va fi executat dup instruciunea JMP scadere
va fi instruciunea SUB AX, CX. Exemplul anterior este echivalent cu secvena:
...
JMP scadere
...
scadere: SUB AX, CX
...
Exist unele avantaje atunci cnd scriem instruciunile pe linii separate. n
primul rnd, atunci cnd scriem un nume de etichet pe o singur linie, este mai uor
s folosim nume lungi de etichete fr a strica forma programului scris n limbaj de
asamblare. n al doilea rnd, este mai uor s adugm ulterior o nou instruciune n
dreptul etichetei dac aceasta nu este scris pe aceeai linie cu instruciunea.
Numele variabilelor sau etichetelor folosite ntr-un program nu trebuie s se
confunde cu numele rezervate de asamblor, cum ar fi numele de directive i
instruciuni, numele regitrilor, etc. De exemplu, o declaraie de genul:
...
ax DW 0
BYTE:
...
nu poate fi acceptat, deoarece AX este numele registrului acumulator, AX, iar
BYTE reprezint un cuvnt cheie rezervat.
Orice nume de etichet ce apare pe o linie fr instruciuni sau apare pe o linie
cu instruciuni trebuie s aib semnul : dup numele ei. Tototdat, se ncearc s se
dea un nume sugestiv etichetelor din program. Fie urmtorul exemplu:
...
CMP AL, a
JB Nu_este_litera_mica
CMP AL, z
JA Nu_este_litera_mica
SUB AL, 20H
; se transforma in litera mare
Nu_este_litera_mica:
comparativ cu:
...
CMP AL, a
JB x5
CMP AL, z
JA x5
SUB AL, 20H
x5:
Observaie:
Explicaii:
1. Se pot introduce comentarii ntr-un program ASM prin folosirea ";". Tot ce
urmeaz dup ";" i pn la sfritul liniei este considerat comentariu.
2. Nu are importan dac programul este scris folosind litere mari sau mici
(nu este "case sensitive").
3. Fr cele dou instruciuni care seteaz registrul DS ctre segmentul definit
de .DATA, funcia de afiare a string-ului nu ar fi funcionat cum trebuie. Variabila
DataString se afl n segmentul .DATA i nu poate fi accesat dac DS nu este
poziionat ctre acest segment. Acest lucru se explic n modul urmtor: atunci cnd
facem apelul DOS de afiare a unui string, trebuie s parcurgem ntreaga adres de
tipul segment:offset a string-ului n DS:DX. De aceea, de abia dup ce am ncrcat
DS cu segmentul .DATA i DX cu adresa (offset-ul) lui DataString avem o referin
complet segment:offset ctre DataString.
Observaii.
Nu trebuie s ncrcm n mod explicit registrul de segment CS deoarece
DOS face acest lucru automat n momentul cnd rulm un program. Astfel, dac CS
nu ar fi deja setat la momentul execuiei primei instruciuni din program, procesorul
nu ar ti unde s gseasc instruciunea i programul nu ar rula niciodat. n mod
asemntor, registrul de segment SS este setat de DOS nainte de execuia
programului i de regul rmne nemodificat pe perioada execuiei programului.
Cu registrul de segment DS lucrurile stau altfel. n timp ce registrul CS se
refer la intruciuni (cod), SS se refer ("pointeaz") la stiv, DS "pointeaz" la date.
Programele nu manipuleaz direct instruciuni sau stive dar au de-a face n mod
direct cu date. De asemenea, programele vor acces la date situate n segmente diferite
n orice moment. Se poate dori ncrcarea n DS a unui segment, accesarea datelor
din acel segment i apoi ncrcarea lui DS cu un alt segment pentru a accesa un bloc
diferit de date. n programe mici sau medii nu vom avea nevoie de mai mult de un
segment de date dar programe mai complexe folosesc deseori segmente de date
multiple.
Urmtorul program va afia un caracter pe ecran, folosind ncrcarea
registrului ES n locul lui DS.
;Program p02.asm
.MODEL small
.STACK 200H
.DATA
OutputChar DB 'B'
.CODE
ProgramStart:
mov dx, @data
mov es, dx
mov
mov
mov
int
mov
int
END
; setarea
; DS=CS
segmentului de date
; AX <- var2
; == mov ax,[2]
mov si,var2
catre
mov ax,[si]
mov si, 1
; Foloseste SI cu rol de index
inc byte [mesajsco2+SI] ; == inc byte [SI + 8]
; == inc byte [9]
; Memoria poate fi adresata folosindu-se 4 registri:
; SI -> Implica DS
; DI -> Implica DS
; BX -> Implica DS
; BP -> Implica SS ! (nu este foarte des utilizat)
;
;Exemple:
mov
mov
mov
mov
mov
ax,[bx]
al,[bx]
ax,[si]
ah,[si]
cx,[di]
mov ax,[bp]
;
;
;
;
;
ax
al
ax
ah
di
<<<<<-
word
byte
word
byte
word
in memorie
in memorie
referit de
referit de
referit de
referit de BX
referit de BX
SI
SI
DI
ax,[23h]
ah,[bx+5]
ax,[bx+si+107]
ax,[bx+di+47]
;
;
;
;
ax
ah
ax
ax
<<<<-
word
byte
word
word
in
in
la
la
memorie DS:0023
memorie [DS:BX+5]
adresa [DS:BX+SI+107]
adresa [DS:BX+DI+47]
;Ilegal
;Ilegal
NOT:
AND:
OR:
XOR:
TEST:
A =~A
A &= B
A |= B
A ^= B
A&B
astfel de masc logic are efect asupra anumitor bii, n timp ce pe alii i las
neschimbai. Exemple:
Instruciunea AND CL, 0Fh face ca cei mai semnificativi 4 bii s ia
valoarea 0, n timp ce biii mai puin semnificativi sunt lsai neschimbai;
astfel, dac registrul CL are valoarea iniial 1001 1101, dup execuia
instruciunii AND CL, 0Fh va avea valoarea 0000 1101.
Instruciunea OR CL, 0Fh face ca cei mai puin semnificativi 4 bii
s ia valoarea 1, n timp ce biii mai semnificativi s rmn nemodificai. Dac
registrul CL are valoarea iniial 1001 1101, dup execuia instruciunii OR CL,
0Fh va avea valoarea 1001 1111.
<operand> , <contor>
ax, 1
; AX ori 2
mov bx, ax
shl ax, 3
add ax, bx
; salvm 2*AX
; 2*AX(original) ori 8 = 16*AX(original)
; 2*AX + 16*AX = 18*AX
; Valori iniiale
MOV bx,5
OR ax,9
AND ax,10101010b
XOR ax,0FFh
NEG ax
; ax <- (-ax)
NOT ax
; ax <- (~ax)
OR ax,1
SHL ax,1
SHR ax,1
ROR ax,1
ROL ax,1
; rotaie dr (MSB=LSB)
MOV cl,3
SHR ax,cl
; mprim AX la 8
MOV cl,3
SHL bx,cl
; nmulim BX cu 8
CL = 0000 0011
Instruciuni aritmetice
Instruciunea ADD (ADDition)
Instruciunea ADD are formatul general:
ADD <destinatie> <sursa>
Unde <destinatie> poate fi un registru general sau o locaie de memorie, iar
<sursa> poate fi registru general, locaie de memorie sau o valoare imediat. Cei doi
operanzi nu pot fi ns n acelai timp locaii de memorie. Rezultatul operaiei este
.code
pstart:
mov ax,@data
mov ds,ax
mov ah,09
mov dx,offset mesaj
int 21h
mov ah,01h ; se citeste un caracter de la tastatura
; codul ASCII al caracterului introdus va fi in AL
int 21h
mov bx,2
div bx ; se imparte AX la BX, catul va fi in AX, restul in DX
cmp dx,0
jnz impar
mov ah,09
mov dx,offset mesg_par
int 21h
jmp sfarsit
impar: mov ah,09
mov dx,offset mesg_impar
int 21h
sfarsit:
mov ah,4ch
int 21h ; sfarsitul programului
END pstart
2. Program care calculeaz ptratul unui numr introdus de la tastatur.
; Programul calculeaza patratul unui numar (<=256) introdus de la tastatura
; Valoarea patratului se calculeaza in registrul AX (valoare maxima 2^16 =
65536)
dosseg
.model small
.stack
.data
nr DB 10,10 dup(0)
r DB 10, 10 dup(0)
cmp ax,0
jne cifra
mov ah,9
mov dx, offset patrat
int 21h
caracter:
dec si
mov ah,02 ;apelarea functiei 02 pentru afisarea unui caracter
mov dl,r[si] ;al carui cod ASCII este in DL
int 21h
cmp si,0
jne caracter
jmp sfarsit
mov ah,9
mov dx,offset patrat
int 21h
sfarsit:
mov ah,4ch
int 21h ; stop program
END pstart
3. Program care calculeaz valoarea unui numr ridicat la o putere. Att
numrul ct i exponentul (puterea) sunt introduse de la tastatur.
; Programul calculeaza un numar ridicat la o putere
; Observatie. Deoarece rezultatul se calculeaza in registrul AX care este un
; registru pe 16 biti, valoarea maxima calculata corect este 2^16= 65536
.model small
.stack
.data
mesaj1 db 13,10,'Introduceti numarul:(<=9)$'
mesaj2 db 13,10,'Introduceti puterea:(<=9)$'
mul bx
loop inmultire
xor si,si
mov bx,10
cifra:
div bx
add dl,30h
mov r[si],dl
inc si
xor dx,dx
cmp ax,0
jne cifra
mov ah,9
mov dx, offset mesaj_final
int 21h
caracter:
dec si
mov ah,02 ;apelarea functiei 02 pentru afisarea unui caracter
mov dl,r[si] ;al carui cod ASCII este in DL
int 21h
cmp si,0
jne caracter
sfarsit:
mov ah,4ch
int 21h ; sfarsitul programului
END pstart
4. Program care verific dac un numr este palindrom (un numr se numete
palindrom dac scris de la dreapta la stnga sau invers are aceeai valoare).
; Programul verifica daca un numar sau sir de caractere este palindrom
dosseg
.model small
.stack
.data
nr DB 10,10 dup(0)
mesaj db 13,10,'Introduceti numarul:$'
mesaj_nu db 13,10,'Numarul nu este palindrom!$'
mesaj_da db 13,10,'Numarul este palindrom!$'
.code
pstart:
mov ax,@data
mov ds,ax
mov ah,09
mov dx,offset mesaj
int 21h
mov ah,0ah
mov dx,offset nr
int 21h
mov si,1
mov cl,nr[si] ; incarc in CL numarul de cifre al numarului introdus
and cx,00FFh
mov ax,cx
mov bl,2
div bl
; in AL este catul impartirii lui AX la 2
and ax,00FFh
inc ax
inc cx
mov di,cx
urmatorul_caracter:
inc si
; SI creste de la inceputul sirului spre mijloc
mov bl,nr[di]
cmp nr[si],bl
jne nu_este
dec di
; DI scade de la sfarsitul sirului spre mijloc
cmp si,ax
; in sir se va merge pana la pozitia cl+1
jne urmatorul_caracter
mov ah,9
mov ah,0ah
mov dx,offset nr
int 21h
mov si,1
mov cl,nr[si] ; incarc in CL numarul de cifre al numarului introdus
and cx,00FFh
inc cx
; CX stocheaza acum ultima pozitie din sirul de cifre
xor ax,ax
; stocam rezultatul in AX, pe care il initializam cu zero
urmatorul_caracter:
inc si
; SI creste de la inceputul sirului spre sfarsit
add al,nr[si]
sub al,30h
cmp si,cx
; in sir se va merge pana la pozitia cl+1
jne urmatorul_caracter
xor si,si
jne caracter
mov ah,4ch
int 21h
END pstart
; terminarea programului