Programul executa calcule si functie de rezultatele obtinute, se poate ramifica utilizând instructiunile de salt conditionat si neconditionat.
Dupa fiecare instructiune aritmetica sau logica, functie de valoarea rezultatului se pozitioneaza indicatorii de conditie, care pot fi testati de instructiunile de salt conditionat. Trebuie mentionat ca instructiunile de mutare si cele de salt nu modifica indicatorii.
Salt neconditionat JMP (Jump)
Saltul consta în memorarea adresei de destinatie a saltului în reg. IP (Instruction Pointer).
Exista 3 tipuri de salt neconditionat direct:
Short Jmp - salt scurt cu +127 pâna la -127 fata de IP (instructiunea curenta)
Cod instr |
Deplasament | |
EB |
Short Jmp deplasament pe 1 octet |
IP=IP-50
JMP short etich1
Near Jmp - salt în segmentul curent cu -32K pâna la +32K fata de IP
Cod instr |
Deplasament | |
E9 |
Near Jmp deplasament pe 2 octet |
IP=IP+25400
Far Jmp - salt în afara segmentului curent si trebuie modificat IP si reg. CS
JMP etich2
Cod |
Deplas. in segm |
Reg CS | |
EA |
Adresa segment |
Far Jmp deplasament pe 4 octeti |
IP=4200 CS=adresa segment
Saltul de tip far (îndepartat) se face între segmente si se modifica atât IP cât si registrul de segment CS în care se încarca adresa segmentului care contine eticheta destinatie.
S1 SEGMENT
EXTRN et5:FAR - definire et5 ca eticheta externa
......
JMP far ptr et5 - salt în segmentul S2 care contine eticheta et5
.....
S2 SEGMENT
PUBLIC et5 - definire eticheta et5 ca definitie externa
Et5 LABEL FAR - definire eticheta et5
Salturi indirecte prin registre
La salturile indirecte adresa la care se face saltul se specifica într-un registru. Adresa poate sa sa se refere la un tabel de adrese de salt care pot fi selectate prin modificarea dinamica a registrului folosind indexarea.
JMP BX - adresa de salt este continuta în BX
MOV BX,offset et6 - adresa etichetei et6 se încarca în BX
JMP BX - salt la eticheta et6 din segment (near)
JMP word ptr [BX] - BX contine adresa unei tabele de adrese de salt
JMP dword [BX] - tabela de adrese de salt este de tip FAR(CS:IP)
MOV BX,offset Tadr1 - încarca în BX adresa unei tabele de adrese de salt
ADD BX,SI - aduna pozitia adresei de salt dorite din tabel(* 2 )
JMP word ptr [BX] - salt la adresa et1, et2 sau et3 locale
MOV BX,offset Tadr2 - în BX adresa unei tabele de adrese de salt de tip FAR
ADD BX,4 - aduna pozitia adresei de salt dorite din tabel(*4)
JMP dword ptr [BX] - salt la adresa et6 din alt segment
Tadr1: DW et1 - tabel de etichete locale in segment pe 16 biti(near)
DW et2
DW et3
........
Tadr2: DD et5 - tabel de etichete de tip FAR pe 32 biti(near)
DD et6 ce contin si adresa segmentului
DD et1 - chiar daca este eticheta locala este pe 4 octeti
In exemplul de mai sus s-au generat 2 tabele cu adrese de salt. Tabela Tadr1 contine adrese locale în segment generate pe 16 biti (NEAR) ce vor fi încarcate în IP, iar Tadr2 contine adrese de tip FAR generate pe 4 octeti care contin adresa relativa în segment (deplasament) si adresa segmentului din care face parte eticheta si care va fi încarcata în registru CS. Eticheta et1 care este locala, în Tadr1 se genereaza pe 2 octeti iar în Tadr2 se genereaza pe 4 octeti fiindca face parte dintr-un tabel de adrese de tip FAR.
In registru BX s-a încarcat tabela de adrese locale pe 16 biti Tadr1 si în registrul SI adresa relativa a unei adrese de salt din tabela ca multiplu de 2. La JMP word ptr [BX] se sare la una din adresele et1,et2 sau et3. Prin word ptr se precizeaza ca adresele de salt sunt pe 2 octeti si valoare se încarca în registru IP. La JMP far ptr [BX] se apeleaza o adresa din tabela Tadr2 si primi 2 octeti se încarca în IP iar urmatorii 2 în CS.
Instructiunile de salt sunt de tip SHORT (+127 la -127) sau NEAR ( procesoa-rele pe 32 de biti) si pot referi etichete numai din segmentul curent. Ele nu pot referi etichete din alt segment. Forma generala a instructiunii este:
Jcond eticheta - daca conditia este îndeplinita salt la eticheta specificata
Instructiunile aritmetice si logice pozitioneaza indicatorii de conditie functie de valoarea rezultatului, care pot fi testati de instructiunile de salt conditionat. La instructiunile de comparare se va tine cont ca se face o scadere dest - sursa.
Rez < 0 S=1
Rez >0 S=0 si Z=0
Rez=0 Z=1
Transport C=1
Paritate para P=1 - numarul bitilor de 1 este par
Depasire O=1
Prezentam mai jos principalele mnemonice pentru instructiunile de salt conditionat:
Instructiunea |
Conditie testata |
Comentarii | |
JS sau JL |
S=1 |
Salt la Rez<0 |
Jump on Sign/Low |
JNS sau JGE |
S=0 |
Salt la Rez>=0 |
Jump No Sign/Greater or Equal |
JZ sau JE |
Z=1 |
Salt la Rez=0 |
Jump if Zero/Equal |
JNZ sau JNE |
Z=0 |
Salt Rez # 0 |
Jump if Not Zero/Equal |
JG |
S=0 si Z=o |
Salt la Rez>0 |
Jump Greater |
JLE |
S=1 or Z=1 |
Rez<=0 |
Jump if Low or Equal |
JC |
C=1 |
Salt la transport |
Jump on Carry |
JNC |
C=0 |
Salt la Nu transpot |
Jump if Not Carry |
JA |
C=0 si Z=0 |
Salt la mai mare |
Jump if Above (comp. fara semn) |
JAE |
C=0 |
Salt la mai mare/egal |
Jump if Above or Equal |
JB |
C=1 |
Salt la mai mic |
Jump if Below |
JBE |
C=1 or Z=1 |
Salt la mai mic/egal |
Jump if Below or Equal |
JP sau JPE |
P=1 |
Salt la paritate para |
Jump Parity Even |
JNP sau JPO |
P=0 |
Salt la paritate impara |
Jump Not Parity/ Parity Odd |
JO |
O=1 |
Salt la depasire |
Jump if Overflow |
JNO |
O=0 |
Salt la Nu depasire |
Jump if Not Overflow |
JCXZ |
CX=0 |
Salt la CX=0 |
Jump if CX=0 |
JECXZ |
ECX=0 |
Salt la ECX=0 |
Jump if ECX=0 |
LOOP |
CX # 0 |
Salt pentru CX # 0 |
CX=CX-1 si Jump pentru CX#0 |
Salturile JA, JAE, JB si JBE se refera la comparatii unde elementele sun fara semn.
Instructiunile SETcond memoreaza 1 la adresa daca se îndeplineste conditia testata:
SETS adresa pune 01H la adresa daca S=1
Salturi pentru control cicluri
LOOP adr ; CX=CX-1 si salt daca CX # 0
LOOPZ adr ; CX=CX-1 si salt daca Z=1 si CX # 0
LOOPE ; iesire pentru CX=0 sau Z=0
LOOPNZ adr ; CX=CX-1 si salt daca Z=0 si CX # 0
LOOPNE ; iesire pentru CX=0 sau Z=1
Programarea modulara presupune utilizarea subprogramelor, care asigura o dezvoltare ulterioara simpla a programului si o depanare usoara. O procedura este o secventa de instructiuni care executa un algoritm pe baza unei descrieri formale. Avantajul procedurilor este ca ele sunt reutilizabile.
In limbaj de asamblare exista proceduri (nu exista functii), definite cu directiva PROC si terminate cu ENDP. Revenirea din procedura în programul chemator se face cu instructiunea RET. Chemarea unei proceduri se face cu instructiunea CALL.
Parametrii procedurii se plaseaza înaintea chemarii în registre, intr-o zona de memorie sau în stiva. La scrierea procedurii se stabileste modul de transmitere a parametrilor. Parametrii pot fi transmisi prin valoare sau prin adresa. Tehnicile de transmitere a parametrilor spre subprograme se vor discuta în capitolul 4.
Vom exemplifica cu utilizarea unei proceduri care face media a 2 numere întregi X si Z care se plaseaza în registrele AX si BX. Rezultatul se obtine la iesirea din procedura în AX si se va plasa la revenirea în programul principal în variabila Z.
DOSSEG
.MODEL SMALL
.STACK 100H
.DATA
X DW 2540
Y DW 15417
Z DW 0 ; Z=(X+Y)/2 rezultat
C2 DW 2 ; constanta 2
.CODE
; Pregatire parametrii...
ST1: MOV AX,X ; primul parametru
MOV BX,Y ; parametru 2
CALL Pmed ; chemare subpr. Adr.de revenire în stiva (Top stiva=IP)
MOV Z,AX ; memorare rezultat
...
Pmed PROC NEAR ; procedura locala (near)
ADD AX,BX ; AX= X+Y
CWD ; se putea SHR AX,1
IDIV C2 ; AX=(X+Y)/2
RET ; revenire în program la adresa de revenire din stiva (IP=Top stiva)
Pmed ENDP ; sfârsit procedura
END ST1
La chemarea unui subprogram prin CALL, se pune adresa de revenire (IP) în stiva si se sare la prima instructiune din procedura (IP=offset Pmed). In procedura se executa secventa de instructiuni pâna la instructiunea RET, care încarca în IP adresa din vârful stivei revenind la instructiunea urmatoare dupa CALL.
Instructiunea CALL se deosebeste de JMP doar ca depune în stiva registru de instructiuni IP, care va fi utilizat de RET pentru a reveni în program si a continua cu instructiunea urmatoare.
La chemarea unei proceduri de tip FAR, care poate fi în alt segment, instructiunea CALL are adresa pe 4 octeti si depune în stiva atât IP cât si CS si încarca din adresa instructiunii noile valori pentru IP si CS.
O procedura de tip FAR se deosebeste de una de tip NEAR doar prin faptul ca instructiunea RET incarca din stiva atât adresa de revenire în IP cât si adresa segmentului în CS. Se recomanda ca procedurile sa fie globale (de tip FAR) pentru a putea fi pastrate în orice segment si sa poata fi apelate din oricare segment de program. Instructiunea RET are codul C3H pentru proceduri de tip NEAR si CBH pentru cele de tip FAR.
CALL far ptr Pmed ; pune în stiva IP si CS
Pmed PROC FAR
RET ; incarca din stiva IP si CS
Near CALL
- pune în stiva IP
- salt în segmentul curent cu -32K pâna la +32K fata de IP
Cod instr |
Deplasament | |
CALL |
Near CALL deplasament pe 2 octet |
IP=IP+25400
Far CALL
- pune în stiva IP si CS
- salt în afara segmentului curent si trebuie modificat IP si reg. CS
Cod |
Deplas. in segm |
Reg CS | |
CALL |
Adresa segment |
Far CALL deplasament pe 4 octeti |
IP=4200 CS=adresa segment
Ca si la JMP se pot face apeluri de proceduri indirect prin registre:
CALL BX ; adresa procedurii este în BX
CALL word ptr [BX] ; în BX adresa unei tabele de adrese de proceduri locale
CALL dword ptr[BX] ; în BX adresa unei tabele de adrese de proceduri globale
4.4.1. Conversia din zecimal în binar
Dispozitivele periferice ale calculatorului(tastatura, ecran, imprimanta) sunt proiectate sa lucreze cu siruri de caractere codificate în ASCII. Numerele se introduc ca sir de cifre zecimale codificate în ASCII având codurile 30, 31h, 32h, 33h,...39h pentru 0, 1, 2, 3,...9. Pentru a putea face calcule în dispozitivul aritmetic, care lucreaza în binar, sirul de cifre trebuie convertit.
Numarul 14257 introdus de la consola este un sir ASCII reprezentat sub forma:
Adresa sir |
Cifre max |
Nr.cifre |
| ||||
DX |
0A |
BX adresa început numar zecimal
Luam pe rând cifrele si eliminam primi 4 biti (3 din fata) si obtinem valoarea lor în binar.
Calculul numarului binar corespunzator îl facem iterativ folosind valoarea cifrele codificate în binar astfel:
N=1*10000+4*1000+2*100+5*10+7
Se poate calcula iterativ fara a folosi puterile lui 10 dupa algoritmul
N=0 N=((((0+1)*10+4)*10+2)*10+5)*10+7
Programul prezentat mai jos citeste de la tastatura un numar ASCII de maxim 5 cifre ASCII ( reprezentabil pe 2 octeti) memorat la adresa Z1 si apeleaza o procedura de conversie care functioneaza dupa acest algoritm.
Functia DOS de afisare mesaj are codul 9 (09H) care se pune în AH si cere adresa mesajului în DX. Mesajul de afisat se va termina obligatoriu cu
Functia DOS de citire mesaj de la tastatura are codul 10 (0AH), care se pune în AH si cere adresa sirului de receptionat în DX. Zona ce receptioneaza sirul (Z1) are în primul octet numarul de octeti maxim asteptati, iar în octetul 2 numarul de octeti receptionati (sirul se termina cu enter).
La chemarea procedurii de conversie CZB în BX se încarca adresa primului caracter din sirul de cifre zecimale si în CX numarul de cifre zecimale. Rezultatul va fi returnat în registrul AX
; Conversie zecimal ASCII - binar 2 octeti
.286c
dosseg
.model small
.stack 100
.data
; numar zecimal ASCII introdus de la tastatura
z1 db 10,0,10 dup (30h),10,13,'$' ; nr zecimal
zece dw 10
n db 0 ; numar cifre zecimale
dw 17394 ; pentru verificare rezultat
bin dw 0 ; numar binar rezultat
m1 db 13,10,'Introduceti un numar de 5 cifre:',13,10,'$'
.code
st1: mov ax,@data
mov ds,ax
mov dx,offset m1 ; afisare mesaj dialog
mov ah,9
int 21h
mov dx,offset z1 ; adresa numar zecimal
mov ah,10 ; asteptare numar
int 21h
mov bx,offset z1+2 ; adresa prima cifra
mov cx,0
mov cl,z1+1 ; numar de cifre numar zecimal
call czb ; procedura conversie zec-bin
mov bin,ax ; memorare numar binar
int 3
; Procedura conversie zecimal ASCII -binar 2 octeti
; - intrare BX = adresa numar zecimal, CX = numar cifre zecimale
; - iesire AX = numar binar
czb proc
xor ax,ax ; AX = 0
mov si,ax ; index prima cifra
mov n,cl ; numar cifre zecimale
c3: mov cl,[bx+si] ; incarcare cifra ASCII
and cl,0fh ; anulare primii 4 biti
mul zece ; N = N*10
add ax,cx ; N = N*10 + cifra
inc si ; urmatoarea cifra
dec n
jnz c3
ret
czb endp
end st1
4.4.2. Conversie binar-zecimal ASCII
Consideram un numar binar N pe 16 biti care trebuie afisat pe monitor în ASCII. Conversia în zecimal se face în procedura CBZ, împartind repetat numarul cu 10 si retinem resturile împartirii din DX, care se memoreaza într-o zona ZEC din dreapta spre stânga. Iesirea din ciclu se face când câtul împartirii din registrul AX este zero.
La intrarea în procedura se verifica daca numarul este negativ, caz în care se complementeaza si se pozitioneaza un indicator (CH=1). Înainte de iesirea din procedura se verifica indicatorul si daca numarul a fost negativ i se pune un - în fata, iar daca a fost pozitiv se pune un +.
La chemarea procedurii se încarca în AX numarul binar ce trebuie convertit, în BX adresa zonei ZEC unde se va pune sirul zecimal si în SI pozitia ultimului octet în sir.
La revenirea din procedura se afiseaza rezultatul cu functia DOS având codul 9.
Se putea utiliza numai SI care sa contina adresa ultimului octet din sir
MOV SI,offset zec+5
.286c ; -------- ----- ------ -----
dosseg ; Conversie binar - zecimal ASCII
.model small ; -------- ----- ------ -----
.data
; numarul zecimal ASCII rezultat se afiseaza
zec db 6 dup (20h),10,13,'$' ; rezultat zecimal
zece dw 10
n db 0
bin dw -17394 ; numar binar de convertit
m1 db 13,10,'Numarul in zecimal este:',13,10,'$'
.code
st1: mov ax,@data
mov ds,ax
mov dx,offset m1 ; afisare mesaj de dialog
mov ah,9
int 21h
mov si,6-1 ; index ultima cifra zecimala
mov bx,offset zec ; adresa zona numar zecimal
mov ax,bin ; numar binar
call cbz ; conversie binar zecimal
mov dx,offset zec ; afisare rezultat conversie
mov ah,09h
int 21h
mov ah,4Ch ; terminare program - iesire in DOS
int 21h
; Procedura conversie binar - zecimal ASCII
; - intrare AX = numar binar BX = adresa zona pt numar zecimal
SI = index ultima cifra zecimala
cbz proc
xor cx,cx ; CX = 0
or ax,ax ; pozitionare indicatori
jge d1 ; numar pozitiv
mov ch,1 ; indicator numar negativ
neg ax ; valoare absoluta
d1: mov dx,0 ; pregatire impartire
div zece ; bin/10 CIT in AX
or dl,30h ; corectie ASCII REST din DL
mov byte ptr [bx+si],dl ; memorare cifra zecimala
dec si ; index cifra urmatoare
or ax,ax ; verificare CIT = 0
jnz d1 ; ciclu daca AX > 0
mov byte ptr [bx+si],'+' ; semn implicit
or ch,ch ; verificare indicator negativ
jz sf
mov byte ptr [bx+si],'-' ; semn negativ
sf: ret
cbz endp
end st1
4.4.3. Program înmultire doua numere zecimale ASCII
.286c ;-------- ----- ------ ------
Dosseg ; Utilizare subprograme de conversie
.model small ; Calcul c = a*b de la tastatura
.data ; -------- ----- ------ -----
; In z1 se transfera numerele zecimale ASCII
z1 db 10,0,10 dup (30h),10,13,'$'
zece dw 10
n db 0
m1 db 13,10,'Introduceti '
a db 10,13,'a: $'
b db 10,13,'b: $'
abin dw 0 ; numere binare
bbin dw 0
cbin dw 0
czec db 13,10,'a*b= ' ; rezultat de afisat
zec db 6 dup(20h),13,10,'$'
.code
st1: mov ax,@data
mov ds,ax
; mesaj citeste a
mov dx,offset m1
mov ah,09h
int 21h
; citeste a in ASCII
mov dx,offset z1
mov ah,10
int 21h
; conversie a in binar
mov bx,offset z1+2
mov cx,0
mov cl,z1+1
call czb
mov abin,ax
; mesaj citeste b
mov dx,offset b
mov ah,09h
int 21h
; citeste b in ASCII
mov dx,offset z1
mov ah,10
int 21h
;conversie b in binar
mov bx,offset z1+2
mov cx,0
mov cl,z1+1
call czb
mov bbin,ax
; acum in ax avem bbin
mul abin ; c=a*b
mov cbin,ax
; acum in ax avem a*b
; conversie rezultat binar - zecimal
mov bx,offset zec
mov si,5
call cbz
; afisare c
mov dx,offset czec
mov ah,09h
int 21h
; terminare
mov ax,4C00h
int 21h
; se copiaza procedurile de conversie CBZ si CZB
include convert.asm
end st1
|