Abbiamo visto come il costrutto if/else si traduca in assembly con una serie di salti al punto corretto di codice da eseguire in base alla condizione valutata. Il ciclo in realtà è molto simile come approccio, tanto che non esiste una parola while vera e propria ma un if else che risalta su se stesso! Vediamo un esempio.
Partiamo da un frammento di codice C++ più intuitivo per lo studente. Un classico ciclo while con un iteratore che fa 5 step stampando il numero di iterazione
//fai un ciclo while che conta fino a 5
int =0;
while(i<5)
{
i++;
cout << i <<endl;
}
cout <<"finito!"
SASM
Il ciclo è molto semplice e non molto utile se non didatticamente: si limita a fare la stampa dei numeri 1,2,3,4,5 in pratica e della scritta “finito”. Il codice assembly è più semplice di quello che potete immaginare. Ne vediamo un esempio con SASM.
Utilizziamo il registro generico dx come contatore/variabile i. Lo inizializziamo a zero con il primo mov. Quindi mettiamo una etichetta: ci serve per delimitare il nostro ciclo while e saltare all’inizio dello stesso. A questo punto incrementiamo di 1 il registro dx, ne stamiamo l valore con la funzione preconfezionata PRINT_DEC ed eseguiamo finalmente il controllo del registro dx col valore 5 e l’istruzione cmp. A questo punto valutiamo il risultato della comparazione: se più piccolo, lower, salta jump all’inizio del ciclo dove c’è l’etichetta ciclowhile, utilizzando JumpLower, jl. Se il jl non è soddisafatto è implicito che si esce dal ciclo e si va alla stampa successiva di fine e relativo reset
%include “io.inc”
section .text
global CMAIN
CMAIN:
mov edx, 0
ciclowhile:
inc edx
PRINT_DEC 4, edx
cmp edx, 5
jl ciclowhile
PRINT_STRING “Finito!”
xor eax, eax
ret
EMU 8086
La versione con EMU8086 è del tutto analoga, usando le funzioni che semplificano le operazioni di stampa, ed è la seguente
include ‘emu8086.inc‘
.MODEL SMALL
.STACK
.DATA
.CODE
.STARTUP
mov ax, 0
ciclowhile:
inc ax
call PRINT_NUM
PRINTN ”
cmp ax,5
jl ciclowhile
PRINTN ‘Finito!’
;mi dichiaro delle funzioni di stampa e input
DEFINE_SCAN_NUM
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS
.EXIT
END
In questo caso abbiamo usato come contatore il registro AX, che “sbianchiamo” a zero, tenendo presente che il suo contenuto viene anche stampato in automatico come parametro di default della funzione PRINT_NUM che invochiamo con la annessa andata a capo PRINTN ”. Le condizioni di salto e comparazione sono equivalenti.
Ultima modifica 19 Dicembre 2022