Martedì, 21 Gennaio 2020 09:18

Esempio 14: if else in assembly

Scritto da

Vediamo più nel dettaglio  il costrutto if/else in assembly e approfondiamo il concetto di "salto"

Già nell'esempio 13 abbiamo visto il funzionamento dell'if, costrutto che in assembly si traduce con una costruzione inversa della condizione con l'uscita dalla if attraverso un salto di codice verso una label, una etichetta che contraddistingue una riga di codice fuori dalla condizione. L'else per certi versi rafforza questa necessita. Riprendiamo l'esempio precedente modificandolo un po' trasformandolo in un "trova massimo tra due numeri letti in input".

In SASM scriviamo questo frammento:

%include "io.inc"

section .data

max dd 0

 

section .text

global CMAIN

CMAIN:

mov ebp, esp ;for correct debugging

  

GET_DEC 4, eax ;la nostra x

GET_DEC 4, edx ;la nostra y

 

cmp eax, edx

jg else

PRINT_STRING "x è più piccolo di y"

mov [max], edx

jmp fuoridallif ;forzo l'uscita per non eseguire il blocco else:

 

else:

PRINT_STRING "x è più grande di y"

mov [max], eax

 

fuoridallif:

NEWLINE

PRINT_DEC 4, max

 

xor eax, eax

ret

 

Proviamo ad analizzare frammento per frammento.

Dichiariamoci una variabile da 32 bit che chiamiamo max, dove inseriremo il risultato finale. Le prime due righe GET_DEC si occupano di leggere due numeri dalla finestra laterale di input. Scriviamoci sullo stesso rigo due numeri di esempio con uno spazio tra i due. A questo punto dobbiamo inserire un blocco condizionale, il classico if. Se volessimo scomodare il c++, dovremmo scrivere un frammento come il seguente

if (x <= y)
{
 cout<<"x più piccolo";
 //devi saltare fuori per non fare l'else
}
else
{
 cout<<"x è più grande";
}

l'operatore if in assembly si indica con cmp, contrazione della parola "compare", che prende due valori, ovvero per noi i registri eax, edx che contengono  le nostre x ed y, rispettivamente. Ora bisogna cercare di imporre una condizione come il <= dell'esempio in c. Come notato nella lezione/post precedente, il trucco dell'assembly è quello di imporre una condizione "inversa" ovvero se voglio controllare x<=y devo verificare x > y per imporre il salto al codice opportuno. Ed infatti con l'operatore jg, jumper greater, salta se più grande all'etichetta che abbiamo chiamato else:. Se non viene eseguito il salto, l'assembler scende al codice immediatamente sotto che corrisponde al caso "x più piccolo", che stampa una stringa a video e mette nella variabile max il valore del registro opportuno. A questo punto dobbiamo risaltare per non eseguire il codice sotto corrispondente all'else ed andiamo col comando jmp, jump all'etichetta fuoridallif. Se dal jg siamo saltati all'etichetta else, andiamo a stampare il messaggio sotto ed aggiornare il valore della variabile max. Il codice fuori quindi dal costrutto if/else, che sia eseguito dal salto o dall'uscita dell'else, semplicemente stampa una linea vuota con NEWLINE e il contenuto della variabile max.

Lo stesso esercizio visto con EMU8086 con i registri a 16bit è del tutto analogo. Ricordiamo che la funzione per semplificare la lettura da tastiera inserisce il numero letto direttamente nel registro CX, quindi bisogna aver premura di spostare il valore in un altro registro per leggere il successivo, che altrimenti andrebbe a sovrascrivere il primo. Le funzioni per if/else sono uguali a quelle commentate precedentemente. Tenete presente che il valore max che ci mettiamo da parte nella variabile, per essere stampato, deve essere riportato nel registro AX che è il parametro di default che viene preso dalla istruzione PRINT_NUM. 

include 'emu8086.inc'
.MODEL SMALL

.STACK
.DATA

max dw 0

.CODE
.STARTUP

call SCAN_NUM

mov ax, cx ; AX sarà la nostra x

call SCAN_NUM

mov dx, cx ; AX sarà la nostra y

 

cmp ax, dx

jg else

PRINTN 'x è più piccolo di y'

mov [max], dx

jmp fuoridallif ;forzo l'uscita per non eseguire il blocco else:

 

else:

PRINTN "x è più grande di y"

mov [max], ax

 

fuoridallif:

PRINTN ''

mov ax, max

call PRINT_NUM 


;mi dichiaro delle funzioni
DEFINE_SCAN_NUM
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS

.EXIT
END

 

Letto 108 volte
Prof. Alfredo Centinaro

Docente di "Scienze e tecnologie informatiche", "Tecnologie e progettazione di sistemi informatici", "Sistemi e Reti" presso IIS Alessandrini-Marino (Teramo), consulente e sviluppatore web. Ha collaborato per anni come sviluppatore presso MHT - Treviso, assistente Sistemi ed elaborazione dell'informazione in UniTE Corso di laurea in Scienze del turismo culturale, tutor presso Telecom Italia Learning Services (L'Aquila)

Articoli correlati (da tag)

Joomla SEF URLs by Artio