In acest tutorial destinat limbajului de asamblare pentru procesoare din familia Intel 8086 sunt prezentate structurile de control:
- structura alternativa, sau structura IF
- structura pre-conditionata, sau WHILE-DO
- structura post-conditionata, sau DO-WHILE
- structura alternativa multipla, sau CASE
Structura alternativa IF
In limbajele de nivel inalt structura de control alternativa este asociata cu expresia IF-THEN-ELSE. Implementarea structurii alternative presupune:
- evaluarea unei expresii;
- compararea a doua valori.
In ambele cazuri sunt initializate flag-urile de conditie, prezentate in partea I a tutorialului – Tutorial Limbaj de Asamblare (Assembler) Intel 8086 – Partea 1 – Elemente de baza.
Daca conditia evaluata este adevarata, atunci se executa secventa de instructiuni de pe ramura true; altfel expresiile de pe ramura false au prioritate.
In Assembler se utilizeaza pentru a compara doi operanzi instructiunile
- CMP
- CMPSB
- CMPSW.
Tipuri de salturi in limbaj de asamblare
- salturi neconditionate: JMP;
- salturi conditionate: JA sau JNBE, JAE sau JNB, JB sau JNAE, JBE sau JNA, JC, JCXZ sau JECXZ, JE sau JZ, JG sau JNLE, JGE sau JNL, JL sau JNGE, JLE sau JNZ, JNC, JNE sau JNG, JNO, JNP sau JPO, LOOP, LOOPE sau LOOPZ, LOOPNE sau LOOPNZ.
Procesorul 8086 permite mai multe modalitati de a efectua un salt prin intermediul instructiunii jmp. Destinatia saltului poate fi in acelaşi segment (intrasegment) sau intr-un segment diferite (intersegment).
Tip jump | Forma interna |
Jump intersegment | 5 octeti: 1 pentru codul operatiei (EAh), 2 pentru offset şi 2 pentru adresa segment. |
Jump intrasegment | 3 octeti: 1 pentru codul operatiei (E9h), 2 pentru offset. |
Jump-uri scurte (short jumps) | 2 octeti: 1 pentru codul operatiei (EBh), 1 pentru a reprezenta o valoare cu semn aferenta offset-ului. In acest caz, destinatia trebuie sa fie intre +127 şi -128 de octeti fata de instructiunea de salt. |
Instructiunea CMP
Flag-urile (descrise in Partea 1 – Elemente de baza) modificate de rezultatul instructiunii CMP sunt:
- OF;
- SF;
- ZF;
- AF;
- PF;
- CF;
Instructiunea CMP compara cei doi operanzi prin intermediul unei scaderi logice. Asta inseamna ca cei doi operanzi nu sunt modificati, insa bitii de flag sunt setati astfel incat sa indice rezultatul diferentei.
Exemplu de secventa de cod necesara compararii a doua valori intregi in limbaj de asamblare.
CMP DX, BX;
- Cand BX = 0004 şi DX = 0008,
DX – BX = 0004 (Atentie – aceasta scadere nu modifica operanzii)
– nu are loc overflow (OF=0)– rezultatul este pozitiv (SF=0)
- Cand BX = 000A şi DX = 0008,
DX – BX = FFFE (- 2)
– nu are loc overflow (OF=0)– negativ (SF=1)
Alte exemple pentru instructiunea assembler CMP
- se considera registrele si valorile AX = 10, BX = -12 (decimal)
- CMP AX, BX
AX – BX = +22
PL (positive, SF=0), CY (carry, CF=1), NV (no
Overflow, OF=0), NZ (not zero, ZF=0)
- CMP BX, AX
BX – AX = -22
NG (negative, SF=1), NC (no carry, CF=0), NV (no
Overflow, OF=0), NZ (not zero, ZF=0)
- CMP AX, AX
AX – AX = 0
PL (positive, SF=0), NC (no carry, CF=0;), NV (no
Overflow, OF=0), ZR (zero, ZF=1)
Ce putem compara?
- registru cu registru: CMP AX, BX
- registru cu memorie (variabile definite): CMP AX, mval
- registru cu constante: CMP AX, 42
- memorie cu registru: CMP mval, AX
- memorie cu constanta (!) CMP mval, 42
Ce nu putem compara?
- Nu se poate compara memorie cu memorie!!!
- CMP a, b ;instructiune gresita
- Una dintre valori trebuie copiata intr-un registru inainte de a realiza comparatia.
Salturi conditionate
- Salturile conditionate sunt utilizate pentru a trece la o alta locatie in segmentul de cod in fucntie de valorile anumitor biti de flag;
- Numerele care sunt comparate pot reprezenta atat valori cu semn cat şi fara semn. Flag-uri diferite sunt verificate in functie de interpretarea valorilor.
- Cum ştie procesorul cum interpreteaza utilizatorul valorile (fie cu semn, fie fara semn)?
Raspuns: in functie de tipul instructiunii de salt.
- Salturi fara semn (valorile comparate sunt considerate fara semn) se refera prin cuvintele cheie “above” pentru mai mare şi “below” pentru mai mic.
- Salturile cu semn se refera prin “greater” şi “less”.
Operatie | Instructiune de salt conditionat daca ambii operanzi sunt considerati fara semn | Instructiune de salt conditionat daca unul dintre operanzi este cu semn |
<> or != | JNE sau JNZ | JNE sau JNZ |
= or == | JE sau JZ | JE sau JZ |
>= | JNB | JNL |
> | JNBE sau JA | JNLE or JG |
<= | JNA | JNG |
< | JNAE sau JB | JNGE sau JL |
Exemplu program assembler in care este evidentiata diferenta dintre Valori cu semn vs. Valori fara semn
.data total dw 0FFFFh ; sari daca total < 10 (cu semn) .code CMP total, 10 JL less10 ;sari daca total < 10 … less10: ;FFFFh = -1, codul va sari la less10 pt. ca –1 < 10. ;sari daca total < 10 (fara semn) CMP total, 10 JB less10 ; sare daca total < 10 …. less10: ;Acest cod nu va efectua saltul la <strong>less10</strong> pentru ca valoarea ;FFFFh luata fara semn este 65535 > 10.
Intrebare: Cum ştie programul daca sa considere FFFFh ca fiind –1 or 65,535? Raspuns: Utilizatorul ii spune acest lucru prin tipul instructiunii de salt conditionat.
Utilizarea salturilor conditionate
- Salturile conditionate sunt utilizate de obicei dupa o instructiune CMP.
- Se pot utilizat salturi conditionate şi dupa o operatie aritmetica pentru ca şi acestea modifica bitii de flag in functie de rezultat.
Expresia de tip If implementata in limbaj de asamblare
Limbaj evoluat | In Assembler (tot in pseudo-cod!): |
if (op1 = op2) then <expresie1> <expresie 2> end if | cmp op1, op2 jne fals < expresie 1> < expresie 2> fals: <restul programului> |
Exemplu aplicatie assembler in care este utilizata structura de control de tip IF
.data op1 db 10 op2 db –12 op3 db ? .code mov al, op1 ;why? cmp al, op2 ;op1 = op2? jne eticheta ;daca nu, sari mov bl, op2 ;expresia 1 mov op3, bl ;expresia 2 eticheta: add al, op2
Expresia de tip IF-THEN-ELSE implementata in limbaj de asamblare
Limbaj evoluat | In Assembler (tot in pseudo-cod!): |
if (temp > max) then max = temp else max = max + 1 endif | cmp op1, op2 jle else <statement1> <statement2> jmp done else: <statement3> <statement4> done: |
Exemplu aplicatie assembler in care este utilizata structura de control de tip IF-THEN-ELSE
mov ax, temp mov bx, max cmp ax, bx ;compara temp cu max if: ;"if" jle els ;sari daca temp <= max mov max, ax ;temp > max "then" jmp done ;salt neconditionat else: inc bx ; temp <= max "else" mov max, bx done:
Expresia de tip DO-WHILE implementata in limbaj de asamblare
Limbaj evoluat | In Assembler (tot in pseudo-cod!): |
i=n; do { <statement1> <statement2> i=i-1; } while (i>=0) | mov cx,n repeat: <statement1> <statement2> loop repeat |
Exemplu aplicatie assembler pentru determinarea sumei elementelor unui vector, ce implementeaza structura de control Do-While prin intermediul instructiunii Loop.
.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
Expresia de tip WHILE-DO implementata in limbaj de asamblare
Limbaj evoluat | In Assembler (tot in pseudo-cod!): |
i=n; while (i>=0) do { <statement1> <statement2> i=i-1; } | mov cx,n repeat: cmp op1,op2 ;verificare conditie jle exit ;conditie iesire <statement1> <statement2> loop repeat exit: |
Expresia de tip CASE implementata in limbaj de asamblare
Limbaj evoluat | In Assembler (tot in pseudo-cod!): |
switch (value) { case constant1: <statement1> break; case constant2: <statement2> break; … default: <statements> | cmp value,constant1 je case1 cmp value,constant2 je case2 … jmp default case1: jmp final case2: Jmp final … default: final: |