Tutorial Limbaj de Asamblare (Assembler) Intel 8086 – Partea 4 – Structuri de control

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 jumpForma interna
Jump intersegment5 octeti: 1 pentru codul operatiei (EAh), 2 pentru offset şi 2 pentru adresa segment.
Jump intrasegment3 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.
  
Tipuri de salturi (jump-uri)

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”.
OperatieInstructiune de salt conditionat daca ambii operanzi sunt considerati fara semnInstructiune de salt conditionat daca unul dintre operanzi este cu semn
<> or !=JNE sau JNZJNE sau JNZ
= or ==JE sau JZJE sau JZ
>=JNBJNL
>JNBE sau JAJNLE or JG
<=JNAJNG
<JNAE sau JBJNGE 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 &lt; 10 (cu semn)
.code

CMP total, 10

JL less10             ;sari daca total &lt; 10

…

less10:
                         ;FFFFh = -1, codul va sari la less10 pt. ca –1 &lt; 10.
                         ;sari daca total &lt; 10 (fara semn)
CMP total, 10

JB less10             ; sare daca total &lt; 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 evoluatIn 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 evoluatIn 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 evoluatIn 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 evoluatIn 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 evoluatIn 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: