PROF. CARMELO CALARCO Breve guida AL LINGUAGGIO ASSEMBLY (emulatore EMU8086) 1
IL LINGUAGGIO ASSEMBLY Il linguaggio assembly è un linguaggio di programmazione a basso livello. Per linguaggi di basso livello si intendono il sottogruppo linguaggi di programmazione orientanti alla macchina, al contrario del linguaggio di programmazione ad alto livello che è orientato all'utente. Un esempio di linguaggio a basso livello è l'assembly. Per programmare in assembly è necessario conoscere la struttura di base di un PC. La struttura più semplice di un computer può essere così schematizzata: Il SYSTEM BUS (parte colorata in giallo) connette le varie componenti del computer. La CPU è il cuore di un computer, esegue tutte le operazioni di calcolo e rappresenta quindi il parametro principale per valutare le prestazioni di un computer. È composta da un unità con funzioni aritmetiche e logiche chiamata ALU (Arithmetic/Logic Unit), da un unità di controllo e temporizzazione chiamata CTU (Control/Timing Unit) e dai registri, piccole memorie che contengono i dati 2
da utilizzare nelle operazioni matematico/logiche o di controllo. La RAM è l area di memoria in cui i programmi sono caricati per poi essere mandati in esecuzione. Il processore 8086 ha una serie di registri (14) a 16 bit, è possibile distinguere tra: registri accumulatori, utilizzabili indifferentemente come registri a 16 bit (word) o 8 bit: AX registro accumulatore (diviso in AH / AL). BX registro base, contiene l indirizzo di base di una tabella o di un vettore (diviso in BH / BL). CX registro contatore usato nelle operazioni fra stringhe e nelle iterazioni come registro contatore a sedici bit (diviso in CH / CL). DX registro dati (diviso in DH / DL). Questi registri sono usati normalmente per i seguenti scopi: - operazioni aritmetiche ad otto e a sedici bit; - operazioni logiche; - trasferimento dei dati. Registri indice, contengono l indirizzo per raggiungere le locazioni di memoria all interno del segmento dati, sono due: SI - registro indice sorgente. DI registro indice destinazione. 3
Registri puntatore, (o Index o Offset) sono generalmente utilizzati come puntatori a dati in memoria (contengono cioè gli indirizzi di memoria). Si possono dividere in: BP registro puntatore alla base dello stack (Base Pointer). SP registro puntatore alla fine dello stack (Stack Pointer). IP registro puntatore delle istruzioni: lavora in parallelo al segmento CS e punta all istruzione che è in esecuzione. Lo stack è un area di memoria della CPU in cui i dati vengono estratti col metodo FIFO (First In First Out) Registri di segmento La memoria della CPU è suddivisa in paragrafi, costituiti da 16 byte contigui e da segmenti costituiti ciascuno da 64k byte. Ogni segmento inizia in corrispondenza di un paragrafo, ossia ad un indirizzo multiplo di 16. CS segmento del codice: punta all indirizzo di testa del segmento contenente il codice del programma. DS segmento dei dati: punta all indirizzo di testa del segmento contenente i dati usati dal programma. ES segmento extra, ovvero segmento dati aggiuntivo. SS segmento dello stack: punta al segmento contenente lo stack. Registro dei flag o di stato Si tratta di un registro a 16 bit, chiamato anche registro di stato, contenente 9 bit utilizzati per indicare differenti condizioni durante l esecuzione del programma. 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 OF DF IF TF SF ZF AF PF CF I bit 0,2,4,6,7,11, contengono flag di stato, che indicano risultati di operazioni di programma. I bit 8,9,10, contengono flag di controllo. Gli altri non vengono utilizzati. 4
SINTASSI LINGUAGGIO ASSEMBLY Il processore 8086 è un processore a due indirizzi, la sintassi generale è la seguente: ISTRUZIONE DESTINAZIONE, SORGENTE dove: istruzione è un codice operativo; destinazione è l operando che riceve il risultato; sorgente è l operando che fornisce un valore al microprocessore. La destinazione può essere un registro o una variabile. La sorgente può essere un registro, una variabile, una costante. Vediamo alcuni esempi possibili: ed alcuni esempi errati: MOV ax,bx MOV bx,ax MOV variabile,ax ADD al,bx (dimensioni diverse) ADD var1,var2 (due variabili) ADD 5,ax (la dest. non può essere una costante) 5
INDIRIZZAMENTO DEI DATI DEL PROCESSORE 8086 Gli indirizzamenti possibili sono: 1) indirizzamento immediato, il sorgente è una costante: MOV AL,8 (cifra decimale) MOV AL,0FH (cifra esadecimale, seguita dal suffisso H e prec. dallo 0 se inizia con una lettera)[b:binario/o:ottale] 2) indirizzamento con registro, gli operandi sono dei registri: MOV AX,BX ADD DL,AL CMP AX,DX MOV CX,BH (non valida - dimensioni diverse) 3) indirizzamento diretto, uno dei due operandi è una variabile: MOV AX,PIPPO MOV PLUTO,AL MOV TIZIO,5 MOV 5,TIZIO (non valida costante come destinazione) MOV CAIO,TIZIO (non valida due variabili) 6
MODELLO DI UN PROGRAMMA IN ASSEMBLY CON L EMULATORE EMU8086
alcuni modelli di memoria processore 8086: TYNY: unico seg per i dati e per il codice; SMALL: un seg per il codice ed uno per i dati; COMPACT: un seg per il codice e più seg per i dati; MEDIUM: un seg per i dati e più seg per il codice; LARGE: più segmenti per i dati e per la memoria; Definizione di Costanti Le costanti sono nomi dati a valori non compaiono nel codice oggetto ed eseguibile Il valore di una costante non può essere modificato Durante la traduzione, l assemblatore sostituisce ogni occorrenza del nome di una costante con il valore corrispondente Esempi: MAX EQU 10h VAT EQU @ MOV AH,MAX ;diventa MOV AH,10h MOV AL,VAT ;diventa MOV AL,40h (cod. ASCII di @) *** Definizione di variabili Sintassi: <nome> <tipo> <val_iniziale> dove: <nome> è un identificatore <tipo> indica la dimensione e può essere DB: Byte (8 bit) DW: Word (16 bit) DD: Double Word (32 bit) (non usato nell 8086) <val_iniziale> è il valore di inizializzazione e può essere un valore numerico (es.: VAR1 DB 10) una stringa di caratteri (es.: VAR1 DB casa: $ ) il carattere? (indica nessun valore, es.: VAR1 DB?) 8
LABORATORIO DI SISTEMI ASSEMBLY 8086 Dichiarazione di una stringa di caratteri:.data MESSAGGIO1 DB "Inserisci un carattere $" Codice per l output di una stringa di caratteri: MOV DX,OFFSET MESSAGGIO1 MOV AH,09H INT 21H Codice che sposta a capo il cursore:.data CAPORIGA DB 13,10,"$" Input di un carattere inserito dalla tastiera: (il carattere digitato viene inserito nel registro AL).data CARAT DB? MOV AH, 01H => viene caricato in AL INT 21H MOV CARAT, AL Output di un carattere inserito dalla tastiera: MOV DL, CARAT MOV AH, 02H INT 21H 9
Dichiarazione di una variabile stringa:.data STRINGA DB N,?,N DUP (?) i cicli: MOV CX,VALORE OBIETTIVO: LOOP OBIETTIVO Salto incondizionato: etichetta: JMP etichetta JMP etichetta1 etichetta1: Confronto: CMP DEST, SORG Esempi di confronto: cmp registro,variabile cmp ax,var1 cmp registro,registro cmp ax,bx cmp variabile,costante cmp var,5 cmp registro,costante cmp al,0dh es.: cmp var1,0dh (13) je etichetta 10
Salti condizionati senza segno: (in funzione del risultato della CMP) JE/JNE: salta se DEST=/ SORG (sintassi JE/JNE <etichetta>) JB/JBE: salta se DEST</<=SORG (sintassi JB/JBE <etichetta>) JA/JAE: salta se DEST>/>=SORG (sintassi JA/JAE <etichetta>) Salti condizionati con segno: (in funzione del risultato della CMP) JE/JNE: salta se DEST=/ SORG (sintassi JE/JNE <etichetta>) JL/JLE: salta se DEST</<=SORG (sintassi JL/JLE <etichetta>) JG/JGE: salta se DEST>/>=SORG (sintassi JG/JGE <etichetta>) 11
incremento: INC VAR1 INC BX decremento: DEC VAR1 DEC BX sottrazione: (sintassi SUB DEST, SORG) esempi: SUB AX,10 SUB AX,AX SUB VAR1,10 SUB AX,BX SUB BX,VAR1 addizione: (sintassi ADD DEST,SORG) esempi: ADD AX,10 ADD VAR1,10 ADD AX,BX ADD BX,VAR1 12
divisione: Senza segno: DIV (DIVision, unsigned) Sintassi: DIV <source> SUB AX,AX ; azzeramento del registro Divisione di un byte per un altro byte MOV AL,VAR1 ; dividendo a 8 bit DIV VAR2 ; quoziente in AL e resto in AH Divisione di una word per un byte MOV AX,VAR1 ; dividendo a 16 bit DIV VAR2 ; quoziente in AL e resto in AH Con segno: IDIV (Integer DIVision) Stessa sintassi di DIV moltiplicazione: Senza segno: MUL (MULtiply, unsigned) Sintassi: MUL <source> MOV AL,NUMERO1 ; operando a 8 bit MUL NUMERO2 ; risultato in AL (8 bit) MOVE AX,NUMERO1 ; operando a 16 bit MUL NUMERO2 ; risultato in AX (16 bit) Con segno: IMUL (Integer MULtiply) Stessa sintassi di MUL 13
Le variabili (array) Gli array sono sequenze di dati di tipo omogeneo Es.: vettori numerici (1,2,5,3) Es.: stringhe di caratteri ( prova ) Le variabili array si dichiarano come segue: a DB 1, 4, 6, 16, 3, 0 ; array di 6 byte b DB H, e, l, l, o ; array di caratteri c DB 5 DUP(9) ; come c DB 9,9,9,9,9 d DW 10 DUP(?) ; array di 10 word non inizializzate Uso delle variabili array Per leggere/scrivere il contenuto di un elemento: MOV <Registro>, <Variabile>[indice] MOV <Variabile>[indice], <Registro> Esempio: MOV AL, a[3] ;copia in AL l elemento dell array a di indice 3 E possibile usare i registri BX, SI, DI, BP per contenere l indice: MOV SI, 3 MOV AL, a[si] ; copia in AL l elemento dell array a di indice 3 14
vettori di caratteri non definito: dimensionamento: DIM EQU 10 (inizio del progr.) dichiarazione: VET DB DIM DUP (?) definizione nel programma: VET[SI] >SI indice del vettore 15
Esempi di codice: Trasformazione di un carattere in un numero SUB NUM, 30h (sottrae al valore corrispondente del codice ASCII del carattere il valore 30h[48d], il risultato è un valore che va da 0 a 9 [per es. se il carattere inserito da tastiera num = 2, il corrispondente codice ASCII è 50, sottraendo 48, avremo 2 come valore numerico] ) Trasformazione di un numero ad una cifra in un carattere ADD NUM, 30h (somma al valore corrispondente del codice ASCII del carattere il valore 30h[48d], il risultato è un valore che va da 48 a 57 [per es. se il valore di num = 2, il corrispondente codice ASCII è 50, sommando 48, avremo 50] ) 16
Input numero a due cifre: LABORATORIO DI SISTEMI ASSEMBLY 8086
Visualizzazione numero a due cifre: LABORATORIO DI SISTEMI ASSEMBLY 8086
Input/output vettore di un carattere: LABORATORIO DI SISTEMI ASSEMBLY 8086
Input di un vettore numerico con elementi a 2 cifre: n EQU 10.
Output di un vettore numerico con elementi a 2 cifre: