Sei sulla pagina 1di 139

μP 8086 e Introduzione alla

programmazione Assembly
Prof. Orazio Gambino

prof. Orazio Gambino


Microprocessore Intel 8086

Intel 8086 Intel I7


prof. Orazio Gambino
Il chip del μP 8086

prof. Orazio Gambino


La piedinatura del μP 8086
Tutti i registri interni, così come i bus di dati interni ed
esterni, sono a 16 bit, a dfferenza di altri μP dello stesso
periodo che erano ad 8 bit (Motorola 6800, Zilog Z80,
Rockwel 6502 ed altri). Un bus di indirizzo esterno a 20
bit fornisce uno spazio di indirizzo fisico di 1 MB (220 =
1.048.576). Ci sono due modi di funzionamento MAX
(sistemi multi-processore) e MIN (sistemi monoproces-
sore, per cui valgono i corrispondenti segnali in paren-
tesi). Ecco il significato di alcuni pin più importanti:
-AD0…AD19 bus indirizzi esterno
-D0…D15 bus dati esterno (multiplexato con il bus
indirizzi AD0…AD15)
-CLK segnale di clock
-RESET per il reset del μP
-Vcc alimentazione (+5V)
-GND massa
-RD abilita la RAM per la lettura (quando il livello è low)
-WR prof. Orazio Gambino
abilita la RAM per la scrittura (segnale LOCK per bloccare gli altri μP in MAX MODE.
MICROPROCESSORI INTEL 8086/8088

• microprocessori Intel • data bus: 8 bit per


della terza generazione l’8088, 16 bit per l’8086
• progetto del 1978/79 • identico formato delle
• address bus: 20 bit ( 1M istruzioni
byte)
prof. Orazio Gambino
Schema del del μP 8086(1)
Execution Unit
è la Cpu vera e propria ed è
costituita da :
•registri di dato, tra cui
l’Accumulatore
•registro di flag
•registro istruzione
•unità di controllo
•unità aritmetico-logica, ALU
•registri e bus interno a 16 bit
(8086/8088)
_______________________
•Esegue le istruzioni ( fase di
execute)
•fornisce dati e indirizzi al BIU
•modifica registri generali e
prof. Orazio Gambino registro flag
Schema del del μP 8086(2)
Bus Interface Unit
gestisce l’indirizzamento, il
prelievo dei dati/istruzioni, il
colloquio con i dispositivi
esterni. Comprende :
•la logica di controllo dei bus,
•quattro registri a 16 bit, detti
registri di segmento : CS, DS. SS,
ES.
•il registro contatore di
programma (IP)
•Quattro registri puntatore :
SP, BP, SI, DI
•l’ Instruction Queue (coda
istruzioni), registro FIFO a 6
byte, in cui vengono memoriz-
prof. Orazio Gambino zate le istruzioni da eseguire.
EU e BIU
• Le due unità possono • L’EU non ha connessioni
operare in modo dirette con il bus di sistema
indipendente l'una (cioè, con il mondo esterno)
dall'altra.
• La CPU è in grado di
sovrapporre le fasi di fetch e
execute.
• Tutte le volte che l'EU deve
eseguire un'istruzione che il
BIU ha già caricato nella
coda delle istruzioni, il
tempo richiesto per il fetch
delle istruzioni è nullo
prof. Orazio Gambino
Localizzazione delle parti del μP 8086

prof. Orazio Gambino


I registri del del μP 8086
Registri Principali

È possibile accedere ai registri


principali chiamati AX, BX, CX,
DX come doppi registri a 8 bit
mentre gli altri quattro, SI, DI,
BP, SP, sono solo a 16 bit.
Sono usati per memorizzare
operandi ed il risultato delle
operazioni.

Esempio in Assembly 8086:

Mem. Mnem. Operands Comment


2003 MOV AX, [3000] [AX] <- [3000]
2007 MOV BX, [3002] [BX] <- [3002]
200B ADD AX, BX [AX] <- [AX] + [BX]

prof. Orazio Gambino


Registro di Stato
I bit (flag) del RS sono impostati ad 1

I registri del del μP 8086 dopo l’esecuzione di una opera-zione


aritmetico-logica al verificarsi dei
seguenti eventi:
-Carry La somma genera un riporto o
se il risultato di una sottrazione è < 0
-Parity numero pari di bit 1 nel
risultato
-Auxiliary Carry: la somma dei semi-
byte bassi genera un riporto
-Zero: il risultato è 0
-Sign: MSB del risultato è 1 (numero
negativo)
-Trap: single step mode for debugging
-Interrupt interrupt da una periferica
-Direction: Questo flag viene utilizzato
specificamente nelle istruzioni di
stringa.Se è impostato ad 1, si accede
alla stringa da una posi-zione di
memoria superiore verso una
posizione di memoria inferiore.
-Overflow: in una somma ad 8 bit il
prof. Orazio Gambino risultato richiede un numero di bit >
8
Schema logico di un sistema a μP 8086

prof. Orazio Gambino


http://www.kswichit.com/8086/8086kit.htm
prof. Orazio Gambino
I registri del del μP 8086:
segmentazione della memoria
Registri di Segmento
La capacità di indirizzamento del μP 8086
è di 1Mbyte, infatti si è visto che vi sono
20 pin per l’indirizzo nella RAM. Allora ci
vorrebbe un registro MAR a 20 bit, ma
sappiamo che, per motivi costruttivi, i
registri possono essere da 8 o 16 bit.
Come fare? Si usa la segmentazione: 16
segmenti (4 bit) da 64 Kbyte (massimo 16
bit). 16*65536 byte = 1048576 byte
Code segment register (CS): indirizza la
posizione del segmento di memoria in cui
è memorizzato il programma eseguibile
Data segment register (DS):punta al
segmento della memoria in cui sono
memorizzati i dati.
Extra Segment Register (ES): si riferisce
anche a un segmento della memoria che
è un altro segmento di dati.
Stack Segment Register (SS): serve per
prof. Orazio Gambino indirizzare il segmento di memoria per lo
stack.
I registri del del μP 8086:
segmentazione della memoria (2)

prof. Orazio Gambino


I registri del del μP 8086:
segmentazione (3)
I 16 bit di un qualsiasi registro di segmento vengono interpretati come i 16 bit più significativi di
un indirizzo lineare a 20 bit, chiamato indirizzo di segmento, di cui i restanti quattro bit meno
significativi sono tutti zeri. L'indirizzo del segmento viene sempre aggiunto a un offset a 16 bit
nell'istruzione per produrre un indirizzo lineare, che è lo stesso dell'indirizzo. Ad esempio,
l'indirizzo segmentato 06EFh: 1234h (qui il suffisso "h" significa esadecimale) ha un selettore di
segmento di 06EFh, che rappresenta un indirizzo di segmento di 06EF0h, al quale viene aggiunto
l'offset, ottenendo l'indirizzo lineare 06EF0h + 1234h = 08124h.

A causa del modo in cui vengono sommati l'indirizzo del segmento e l'offset, un singolo indirizzo
lineare può essere mappato fino a 212 = 4096 segmenti distinti: coppie di offset. Ad esempio,
l'indirizzo lineare 08124h può avere gli indirizzi segmentati 06EFh: 1234h, 0812h: 0004h, 0000h:
8124h, ecc. (si legge segmento:offset)
prof. Orazio Gambino
I registri del del μP 8086:
segmentazione (4)
Sembra complicato. Ma non facevano prima a tentare di creare un registro MAR a 20 bit? No.

I principali vantaggi della segmentazione sono i seguenti:

• Fornisce un potente meccanismo di gestione della memoria.

• Le operazioni relative ai dati o allo stack possono essere eseguite in diversi segmenti.

• L'operazione relativa al codice può essere eseguita in segmenti di codice separati.

• Permette ai processi di condividere facilmente i dati.

• Consente di estendere la capacità di indirizzamento del processore, ovvero la segmentazione


consente l'uso di registri a 16 bit per fornire una capacità di indirizzamento di 1 Megabyte.
Senza segmentazione, richiederebbe registri a 20 bit.

• È possibile aumentare la dimensione della memoria dei dati del codice o impilare segmenti
prof. Orazio Gambino
oltre i 64 KB assegnando più di un segmento per ogni area.
I registri del μP 8086
Registri Indice o Registri Puntatore

-SP (Stack Pointer): Viene utilizzato come


offset insieme a SS per accedere al segmento
di stack.
-BP (puntatore base):Questo è il registro del
puntatore di base che punta ai dati nel
segmento dello stack. A differenza di SP,
possiamo usare BP per accedere ai dati negli
altri segmenti.
-SI (indice sorgente):Questo è il registro
dell'indice di origine che viene utilizzato per
puntare a posizioni di memoria nel segmento
di dati indirizzato da DS. Aumentando il
contenuto di SI si può facilmente accedere a
posizioni di memoria consecutive.
-DI (Indice destinazioni):Questo è il registro
dell'indice di destinazione che svolge la stessa
funzione di SI. Esiste una classe di istruzioni
chiamate operazioni su stringa che utilizzano
DI per accedere alle posizioni di memoria
indirizzate da ES. .
prof. Orazio Gambino
GUI Turbo Assembler (TASM)
https://sourceforge.net/projects/guitasm8086/

Importante!!! Il file .asm deve essere salvato con


nome file
prof. Orazio nel formato DOS 8.3
Gambino
Assembly 8086
• L’Assembler è l'assemblatore, ossia il programma
che traduce il codice sorgente in un file oggetto
eseguibile dal computer.
• Quindi, l‘Assembly sono le istruzioni e la sintassi
del linguaggio di programmazione, mentre
l‘Assembler è il software che lo traduce in
linguaggio macchina eseguibile.
• Le istruzioni possono essere scritte sia maiuscole
che minuscole (non è case-sensitive).
prof. Orazio Gambino
Assembly 8086

• I compiti dell’Assembler sono i seguenti:


• Riceve in ingresso il codice Assembly proprio del μP
• Interpreta ed esegue le direttive all’Assemblatore
• Esegue le pseudoistruzioni
• Produce le istruzioni in Linguaggio Macchina
• Produce un file oggetto con estensione .obj
prof. Orazio Gambino
Assembly 8086
• Per produrre il file eseguibile è necessario un
ulteriore passaggio ad opera del Linker che:
– Riceve in ingresso il file .obj
– Rilocare i vari moduli di cui è formato il codice
finale
– Risoluzione dei riferimenti delle labels
– Produce finalmente un file .exe

prof. Orazio Gambino


Struttura di un programma Assembly
• Un programma Assembly è composto da
quattro sezioni chiamate Segmenti:
STACK

DATI

CODICE

EXTRA
prof. Orazio Gambino
Struttura di un programma Assembly 8086
• Lo stack segment costituisce quella zona della RAM in cui può
essere fatto il push dei dati (funzionamento LIFO, Last In First
Out)
• Il data segment contiene le dichiarazioni delle variabili
statiche (spazio di memoria allocato al momento della
compilazione)
• Il code segment contiene le istruzioni e le direttive del
programma da eseguire
• L’ extra segment viene definito dall’utente e di solito viene
usato per dati addizionali
• I tipi dei segmenti sono ottenuti associando ai registri SS, DS,
CS e ES l’indirizzo di partenza dei segmenti definiti
• Per un programma Assembly e compilato con TASM, occorre
definire
prof. Orazio Gambino il modello di memoria, lo stack ed il segmento codice
Assembly 8086: sintassi delle istruzioni
Ogni istruzione è composta in generale da:

• Un’ Etichetta (o Label) : liberamente scelta dal programmatore


per fissare un riferimento di posizione nel codice
• Un Codice Operativo (Operation Code, abbrev. OpCode): un
acronimo dell’istruzione definito
• Uno o più Operandi (Operands): possono essere registri,
indirizzi di memoria, valori esadecimali, etichetta. Sono uno o
due in funzione di quanti ne richiede l’ OpCode.
Esempio:
Label OpCode Operand(s)
START: MOV AX,BX
prof. Orazio Gambino
Direttive dell’Assemblatore
.model (o MODEL)
Definisce il tipo dei segmenti di memoria da
utilizzare nel programma.
.stack (o STACK)
Dice al compilatore quanto spazio deve riservare per lo stack. Se
viene omesso il compilatore usa per default 400h (1Kb)
.data (o DATA)
Definisce le variabili ed array che verranno utilizzati nel segmento
del codice.
.code (o CODE)
E’ il cuore di un programma Assembly in cui si trovano le istruzioni
che costituiscono il codice del programma.
prof. Orazio Gambino
Direttiva .model
TINY: tutto il codice e i dati sono in un unico segmento (stanno in 64Kb).
Questo modello è il modello utilizzato per i file con estensione COM.
SMALL: è il modello più comune, un segmento per il codice e uno solo per i
dati (statici, globali, heap) e lo stack, Tutti i segmenti non superano i 64Kb.
Quindi il valore iniziale di DS ed SS non coincide con quello di CS
MEDIUM: il codice usa più segmenti, può quindi superare la barriera dei 64Kb.
I dati e lo stack sono gestiti come nel modello small.
COMPACT: è come lo small ma per accedere ai dati uso puntatori di tipo FAR
quest'ultimi possono infatti superare i 64Kb.
LARGE: è come il compact ma con il codice in più segmenti; sia codice che dati
superano i 64Kb.
HUGE: Il modello huge consente di gestire (in teoria) sino ad 1 Mb di dati statici
e globali, estendendo ad essi la modalità di indirizzamento implementata
dai modelli large e medium per il codice. E' l'unico modello che estende ad
1 Mb il limite teorico sia per il codice che per tutti i tipi di dato
FLAT : supporta la modalità a 32bit dei processori 386+; in questa modalità
viene abolita il metodo di indirizzamento SEGMENTO:OFFSET, l'indirizzo è
prof. Orazio Gambino
dato da un unico numero a 32bit. Sotto Win32 è l'unico modello ammesso.
Direttiva .stack
• Lo stack viene utilizzato nei programmi per:
– creare un'area temporanea per i registri quando
questi vengono utilizzati per qualche scopo
– salvare l'indirizzo di ritorno della procedura
corrente al momento dell'invocazione
dell'istruzione call
– contenere gli argomenti (eventualmente) passati
come parametri ad una procedura al momento
della sua esecuzione
– memorizzare le variabili locali di una procedura

prof. Orazio Gambino


Direttiva .data
• La direttiva .data serve per definire le variabili.
Si possono usare gli stessi esempi di
definizione delle variabili visti in una delle
slide precedenti.

• Permette di definire:
– il nome
– il tipo
– il contenuto delle variabili in memoria.
prof. Orazio Gambino
Direttiva .data
nome tipo espressione [, espressione] ...
• nome – etichetta del dato
• tipo – viene interpretato come lunghezza del
dato (se scalare) o di ogni elemento del dato
(se array) - i tipi più utilizzati sono:
DB riserva uno o più byte (8 bit)
DW riserva una o più word (16 bit)
DD riserva una o più doubleword (32 bit)
prof. Orazio Gambino
Direttiva .data
• espressione - contenuto iniziale del dato:
– un' espressione costante
– una stringa di caratteri (solo DB; char=byte)
– un punto di domanda (nessuna inizializzazione)
– un'espressione che fornisce un indirizzo
(solo DW e DD, near o far address)
– un'espressione DUPlicata per la quale si usa il
comando DUP per la generazione multipla di
gruppi di dati
prof. Orazio Gambino
Direttiva .data
.data
ByteVar DB 0 ; 1 byte inizializzato a 0
ByteArray DB 1,2,3,4 ; array di 4 byte
String DB '8','0','8','6' ; array di 4 caratteri
String DB '8086' ; equivale al precedente
Titolo DB 'Titolo',ODH,0AH ; ovvero 13 e 10 stringa che contiene
anche una coppia di caratteri CR/LF (Carriage Return/Line
Feed)
Zeros DB 256 dup (0) ; array di 256 byte inizializzati a 0
Tabella DB 50 dup (?); array di 50 byte non inizializzati
WordVar DW 100*50 ; scalare di una word (2 byte)
Matrix DW 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 ; array di 16 word
Matrix DW 4 dup (1, 3 dup (0)) ; equivale al precedente
NearPointer DW Matrix; contiene l'offset di Matrix
DoubleVar DD ? ; scalare di una double word (4 byte)
FarPointer DD Matrix; contiene l'offset e l'indirizzo del
prof. Orazio Gambino
segmento di Matrix
Direttiva .code
• Segmento per la scrittura del codice.
• Qualunque codice si scriva, deve avere lo stesso finale:
.code
start: ;etichetta
………
………
;the closing
MOV AX,4C00H ;queste 3 righe
INT 21H ;di chiusura
RET ;sono obbligatorie
end start
prof. Orazio Gambino
Struttura di un programma Assembly
8086
• La struttura di un programma Assembly 8086 è la seguente
con le direttive dell’assemblatore:

.model modello di memoria ;seleziona il modello di


memoria
.stack dimensione dello stack ;definisce la dimensione dello
stack
.data ;dichiarazioni di variabili ed array

.code
Label_inizio_codice

..
End Label_inizio_codice
prof. Orazio Gambino
Esempio di un programma essenziale
in Assembly 8086
.model small ;seleziona il modello di memoria
.stack 100H ;definisce la dimensione dello stack
.data ;dichiarazioni di variabili ed array

.code
start: ;label di inizio codice

;the closing
MOV AX,4C00H ; ultime due righe obbligatorie
INT 21H ;interrupt 21H del S.O. MsDos

end start
prof. Orazio Gambino
Assembly 8086: tipi di istruzioni

Il set di istruzioni dell’Assembler Intel 80x86 può essere


suddiviso nelle seguenti classi:

• Istruzioni di trasferimento (mov, push, pop, etc…)


• Istruzioni aritmetiche (add, sub, cmp, mul, div, etc…)
• Istruzioni logiche: (and, or, xor, not, etc …)
• Istruzioni di manipolazione di bit (shl, shr, etc …)
• Istruzioni di controllo (jmp, call, ret, jg, jge, loop, etc…)
• Istruzioni di input/output (in, out,etc..)
• Istruzioni di manipolazione di stringhe (es movs, stos, lods,etc..)
• Istruzioni di controllo dello stato della macchina (hlt, wait,etc..)

prof. Orazio Gambino


Assembly 8086: istruzione MOV
Sintassi: MOV operando destinazione, operando sorgente

• Questa istruzione copia un dato dall’operando source all’operando destination


• Posso usare i registri come operandi, l’importante è che siano della stessa
ampiezza
Alcuni esempi di usi di MOV consentiti:
mov ax, bx ; Copia il valore da BX in AX
mov dl, al ; Copia il valore da AL in DL
mov si, dx ; Copia il valore da DX in SI
mov sp, bp ; Copia il valore da BP in SP
mov dh, cl ; Copia il valore da CL in DH
mov ax, ax ; Non fa nulla, ma è legale
mov ax, cs ; Copia il valore di CS in AX
mov ds, ax ; Copia il valore di AX in DS
Attenzione!!! Quando si usano i registri di segmento non si può usare CS come
operando destinazione e soltanto uno degli operandi può essere un registro
segmento
prof. Orazio Gambino
Assembly 8086: istruzione MOV e
metodi di indirizzamento
Che cosa sono i metodi d’indirizzamento?
Con metodi di indirizzamento, in
programmazione Assembly, si indicano le
modalità con cui un microprocessore consente
alle istruzioni di accedere agli operandi delle
istruzioni durante il ciclo di fetch-execute.

Gli operandi vengono recuperati dall'unità di


controllo in base al loro indirizzo, che può essere
specificato in vari modi, detti appunto metodi di
indirizzamento.
prof. Orazio Gambino
Assembly 8086: istruzione MOV e
metodi di indirizzamento
• Immediate addressing MOV BX,23FFh
– Metti nel registro BX il numero 23FFh
• Register addressing MOV BX,CX
– Copia il contenuto di CX in BX
• Direct addressing MOV AX,[0410h]
MOV BX,var
MOV var,BX
– Metti in AX il contenuto delle locazioni
0410h-0410h
• Register indirect addressing MOV AX,[BX]
– Copia in AX il contenuto dei due byte puntati da BX nel
Data Segment DS
prof. Orazio Gambino
Assembly 8086: istruzione MOV e
metodi di indirizzamento
• Based addressing MOV AX,[BX+4]
– Metti in AX il dato del data segment DS con Offset indicato dal
contenuto di BX+4
• Based-indexed addressing MOV
AX,[AX+DI] oppure MOV AX,[AX][DI]
– Metti in AX il contenuto delle due locazioni con indirizzo AX+DI
• Based-indexed with displacement
MOV AX,[BX+DI+08] oppure MOV AX,[AX][DI+08]
– Metti in AX il contenuto delle due locazioni puntate da BX+DI+08

prof. Orazio Gambino


Assembly 8086: istruzione MOV e
metodi di indirizzamento
• Direct-Offset addressing
BYTE_Array DB 14, 15, 22, 45 ; Array of bytes
WORD_Array DW 134, 345, 564, 123 ; Array of words

MOV CL, BYTE_ Array[2] ;Gets the 3rd element of the BYTE_TABLE
MOV CL, BYTE_ Array + 2 ;Gets the 3rd element of the BYTE_TABLE
MOV CX, WORD_ Array[3] ;Gets the 4th element of the WORD_TABLE
MOV CX, WORD_ Array + 3 ;Gets the 4th element of the WORD_TABLE
– Copia nel registro il valore nell’array indicizzato. Da
notare due diversi tipi di sintassi entrambe valide.

prof. Orazio Gambino


Assembly 8086: istruzione MOV e
metodi di indirizzamento
• Tenere sempre in considerazione negli
indirizzamenti con variabili che i registri a 16
bit di uso generico (AX,BX,CX e DX) devono
essere usati con variabili anch’esse a 16 bit
(word)
• Gli equivalenti registri ABCD-L e ABCD-H
devono essere usati con variabili ad 8 bit
(byte)

prof. Orazio Gambino


Adresing.asm
.model small
.data
var_x db 45h
.code
start:
mov bl,3Fh ;immediate a 8 bit
mov bx,23FFh ;immediato a 16 bit
mov ax,[0410h] ;diretto
mov al, var_x[bx] ;a registro EA= BX+offset di VAR_X
mov al, [bx +1] ; EA = BX +1
mov al, var_x[bx +1] ; EA = BX + 1 + offset di VAR_X
mov ax, [bp][di] ;indicizzato con indice base
mov ax, [bp+di] ;indicizzato con indice base
mov ax, [bx+di+08] ; indicizzato con dislocazione
; the closing
mov ax,4c00h
int 21h
end start
prof. Orazio Gambino
Assembly 8086: istruzione MOV e
metodi di indirizzamento
NON sono ammessi i seguenti indirizzamenti:
• memoria <- memoria (MOV 0410H,0500H)
– Si deve, invece, passare attraverso un registro general-purpose. Per il
codice sopra il codice corretto è il seguente:
MOV AX,0500H
MOV 0410H,AX
• Registro di segmento <- Immediato MOV DS,0500H
– Si deve, invece, passare attraverso un registro general-purpose. Per il
codice sopra il codice corretto è il seguente:
MOV AX,0500H
MOV DS,AX
prof. Orazio Gambino
Valori numerici degli operandi
• di default, tutti i valori numerici sono espressi in base dieci
• è possibile esprimere le costanti numeriche:
– in base 16 (esadecimale) mediante il suffisso H (ATTENZIONE!!! il
primo digit deve però essere numerico, quindi non scriverai FFh bensì
0FFh, serve a distinguere il numero HEX da un’etichetta)
– in base 8 (octal) mediante il suffisso O
– in base 2 (binario) mediante il suffisso B
• Ad esempio:
0FFh
0h
777O
11001b
3Fh
FFh errata !
778O errata !
prof. Orazio Gambino
Labels - Etichette
• Le Labels (Etichette) sono nomi definiti dall’utente che
rappresentano indirizzi
– Le Labels permettono al programmatore di riferirsi ad indirizzi usando nomi logici –
con questa soluzione si evita di riferirsi ad indirizzi (punti del programma) che
peraltro non hanno un valore di memoria assegnato.
– Sarà il Linker, nella fase di compilazione del sorgente, a risolvere le labels
sostituendo gli indirizzi

• Le Labels sono usate per identificare indirizzi per:


– Controllo di flusso – identificare l’indirizzo di un obiettivo
– Variabili di memoria – identificare indirizzi dove i dati sono memorizzati.
• Più precisamente, le Labels identificano indirizzi di offset
– Le Labels per il controllo di flusso, saranno combinate con il registro CS
– Le Labels per le variabili in memoria, saranno combinate con il registro DS
• Le Labels appaiono in 2 ruoli: definizione e riferimento
prof. Orazio Gambino
Labels - Etichette
• L'etichetta rappresenta l'offset dell'indirizzo del
primo byte allocato che segue la definizione
• Usato dall'assemblatore per decidere l'indirizzo
esatto
• Deve essere il primo testo non vuoto su una riga
• Il nome deve iniziare con l'alfa A .. Z a ..z e quindi può
contenere: alfa, numerico, "_"
• Se l'etichetta è un target del flusso di controllo
(diverso dal nome della procedura - in seguito), è
necessario aggiungere ":"
prof. Orazio Gambino
Labels - Etichette
• Impossibile ridefinire le parole riservate, ad es. MOV
(un'istruzione di assemblaggio)
• Se utilizzata come operando, il simbolo “:” viene
omesso
• Esempio di definizioni delle etichette del flusso di
controllo:
MOV bl,00H
CMP bl,00H
JE EQUAL
...
EQUAL:
MOV DX,OFFSET msg2
prof. Orazio Gambino
Etichette per le variabili
• Labels per le variabili
– Si riferisce all’indirizzo di memoria in cui si trova il dato
– Indica l’offset rispetto all’indirizzo caricato nel DS in cui si
trova il dato
– Nome assegnato dal programmatore che deve essere self-
explained

.data
Message DB ‘Hi Mom!’
MessageNullT DB ‘Hi Mom!’, 0
DOSMessage DB ‘Hi Mom!’, ‘$’

prof. Orazio Gambino


Definizione del Data Segment
• E’ fondamentale la corretta inizializzazione del
registro DS in testa all’esecuzione del codice
Modo sbagliato:
MOV DS, @data
Modo giusto:
MOV AX, @data ;Immediate mode
MOV DS, AX ; Register mode

prof. Orazio Gambino


operando Offset
• Il registro DS contiene l’indirizzo di memoria a
partire dal quale si trovano le variabili nel
segmento dati
• E’ necessario, però, ricavare l’indirizzo della
singola variabile
• Per questo motivo, ci viene in aiuto l’operando
offset
• L'operando offset restituisce l'offset di una
variabile, cioè la distanza in byte della variabile
dall'inizio del segmento dati
prof. Orazio Gambino
offset.asm
.model small mov si, offset wvar
.data mov si, offset dvar1
bvar db 45h,'$' mov si, offset dvar2
wvar dw 1f5h mov ax,4c00h
dvar1 dw 1f6h int 21h
dvar2 dw 1f6h end start
.code
start:
mov ax,@data ; Initialize DS
mov ds,ax ; Initialize DS
mov si, offset bvar ; si contiene l’indirizzo di bvar
mov dx,si
mov ah,9 ; queste due righe stampano la stringa che inizia
int 21h ; a partire dall’indirizzo di bvar. Il simbolo $ è
prof. Orazio Gambino ; il simbolo terminatore della stringa
Ofsetdir.asm
model small mov dx,offset carattere_B
.stack 100h mov ah,9 ;print a message
.data int 21h
carattere_A db 41h,'$' mov dx,offset carattere_C
carattere_B db 42h,'$' mov ah,9 ; call to print
carattere_C db 43h,'$' int 21h
.code mov ax,4C00h ;back to DOS
int 21h
start: end start
mov ax,@data;Initialize DS
mov ds,ax ; Initialize DS
mov dx,offset carattere_A
mov ah,9 ;call to print
int 21h
prof. Orazio Gambino
vettore.asm
.model small ;the closing
MOV AX,4C00H
.data INT 21H
vettore DB
41h,'$',42h,'$',43h,'$' END INIZIO ;fine del
programma
.code
INIZIO:

mov ax, @data


mov ds, ax
mov dx, offset vettore+2

mov ah, 09h ; display


int 21h ; Call MS-DOS
prof. Orazio Gambino
Interrupt
• Il primo programma • Nelle prossime slides
“Hello World!” fa largo vedremo più
uso dell’interrupt. approfonditamente
• Anzi, è proprio cos’è un interrupt.
l’interrupt che effettua
sia l’azione di
visualizzazione che di
uscita dal programma.

prof. Orazio Gambino


Interrupt-1
• Sono il mezzo con cui i circuiti esterni al microprocessore
comunicano il vericarsi di un evento
• i microprocessori possono rispondere ad interrupt
hardware e/o software
• un dispositivo hardware puo produrre un segnale di
interrupt che viene elaborato dal PIC (Programmable
Interrupt Controller) e da questi trasmesso al processoregli
interrupt software vengono generati mediante la funzione
INT
• L'effetto di un interrupt è che il processore arresta la sua
normale attivita ed esegue una routine residente in
memoria (gestione di interrupt) al termine, il
microprocessore riprende la sua attivita dal punto in cui
l'interrupt
prof. Orazio Gambino l'aveva fermato
Interrupt-2
• La famiglia di processori 80x86 gestisce fino a 256
interrupt differenti (da 00h fino a FFh), dove H sta
per esadecimale
• Ad ogni interrupt è associata una routine
• L'indirizzo di ognuna delle 256 routine e
memorizzato in una tabella, detta tabella dei
vettori di interrupt
• Ogni vettore di interrupt occupa 4 byte, quindi
l'indirizzo di ogni vettore di interrupt puo essere
ottenuto moltiplicando per 4 il numero
dell'interrupt
prof. Orazio Gambino
Interrupt-3
• Quando il processore esegue l'istruzione:
INT 12H
vengono caricati sullo stack i contenuti correnti:
– del registro dei flag
– del registro del codice (CS)
– del registro IP (Instruction Pointer)
• Il processore esegue la routine di gestione dell'interrupt
• La routine termina con l'istruzione IRET, che scarica dallo stack
i contenuti dei registri della routine interrotta
• Il controllo viene restituito al programma interrotto

prof. Orazio Gambino


Interrupt-4
Interrupt Descrizione
20H (32D) Arresto del programma
21H (33D) Servizi generali del DOS
22H (34D) Indirizzo di terminazione
23H (35D) Indirizzo del gestore del Ctrl-C
24H (36D) Indirizzo gestore errori critici
25H (37D) Lettura disco assoluta
26H (38D) Scrittura disco assoluta
27H (39D) TSR (Terminate and Stay Resident)
28H (20D) Interrupt stato d'attesa DOS
2FH (47D) Interrupt Multiplex
prof. Orazio Gambino
Interrupt-5
Uno degli interrupt piu utilizzati è
INT 21H
Nell'elenco alcune funzioni:
Funzione Descrizione
00H (00D) Termina
01H (01D) Input di un carattere con eco
02H (02D) Output di un carattere
05H (05D) Output della stampante
08H (08D) Input dalla console senza eco
09H (09D) Output di una stringa
0FH (15D) Apertura file
10H (16D) Chiusura file
prof. Orazio Gambino
Interrupt-6
Esempio di utilizzo di una delle funzioni dell'interrupt
int 21h:
mov ah, 1h
int 21h
Nell'esempio:
• il valore 1h viene caricato nel registro ah (viene
selezionata la funzione di input carattere)
• viene invocato l'interrupt
• il carattere digitato da tastiera viene memorizzato nel
registro al

prof. Orazio Gambino


key.asm
.model small
.stack 100h
.code
start:
mov ah, 8h ;carica un carattere
int 21h ;nel semibyte basso di ax (cioè al)
mov dl, al ;copia il carattere in al
mov ah, 2h ;display in contenuto
int 21h ;di al
mov ax, 4c00h
int 21h
end start
prof. Orazio Gambino
Primo programma: Hello World!
.model small
.stack 100h
.data
message db "Hello, world!",0dh,0ah,'$'
.code
start:
mov ax,@data ; Inizializza il DataSegment DS
mov ds,ax ; Inizializza il DataSegment DS
mov ah,9 ; Chiamata alla funzione DOS per scrivere una stringa
mov dx,offset message ; carica in DX l’indirizzo in
; cui si trova la stringa
int 21h ; chiamata all’interrupt 21h
mov ax,4C00h ; DOS Function call to exit back to DOS
int 21h
prof. Orazio Gambino end start
Codifica di “Hello World!”
Offset
.model small
Address Machine Encoding .stack 100h
Assembly Programming
0000 .data
0000 48 65 6C 6C 6F 2C message db "Hello, world!", 0dh, 0ah, '$'
20 77 6F 72 6C 64
21 0D 0A 24
0000 .code
0000 start:
0000 B8 ---- R MOV AX, @data Initialized DS
0003 8E D8 MOV DS, AX MUST!
0005 B4 09 MOV AH, 9
0007 BA 0000 R MOV DX, OFFSET message DOS function to
000A CD 21 INT 21h display message

000C B8 4C00 MOV AX, 4C00h Return to


000F CD 21 INT 21h DOS control
0011 end start MUST!

prof. Orazio Gambino SYSC3006 64


LEA (Load Effective Address)
• Abbiamo visto come le parentesi quadre [] nei vari
indirizzamenti (per es. diretto, indiretto e
indicizzato) e l’operando offset determinino lo
indirizzo effettivo (Effective Address-EA) da cui
prelevare il dato.
MOV AX, OFFSET TABLE
• Carica in AX l’EA della variabile TABLE.
• Però, l’istruzione LEA permette di utilizzare
l’indicizzazione dell’operando sorgente.
• L’operando offset calcola l’EA a tempo di
compilazione, calcolando lo scostamento dall’inizio
del segmento dati.
prof. Orazio Gambino
LEA (Load Effective Address)
• Non è quindi possibile utilizzare la seguente
istruzione per l’accesso ad un vettore VETT:
MOV BX, OFFSET VETT[SI]
• L’istruzione LEA trasferisce l’EA dell’operando
sorgente (e non il suo valore!) nell’operando
destinazione.
• L’operando sorgente deve essere un
riferimento alla memoria e l’operando
destinazione deve essere un registro a 16 bit.
prof. Orazio Gambino
LEA (Load Effective Address)
• L’istruzione LEA permette, al contrario dello
operando offset, permette di effettuare
l’indicizzazione tramite registro:
LEA BX, TABLE[SI]
Nelle prossime 2 slide troviamo esempi di
applicazione dell’istruzione LEA: il primo sul
codice di Hello World! e nel secondo su un
vettore di dati.
prof. Orazio Gambino
lea.asm
.model small
.stack 100h
.data
message db "Hello, world!",0dh,0ah,'$'
.code
start:
mov ax,@data ; Initialize DS
mov ds,ax ; Initialize DS
lea dx,message
mov ah,9 ; DOS Function call to print a message
int 21h
mov ax,4C00h ; DOS Function call to exit back to DOS
int 21h
endprof.start
Orazio Gambino
leavet.asm
.model small add si,2h
.data lea dx, vettore[si]
vettore DB mov ah, 09h
41h,'$',42h,'$',43h,'$‘ int 21h
.code ret
INIZIO:
mov ax, @data Codice ;the closing
ripetuto
mov ds, ax MOV AX,4C00H
mov si, 0h INT 21H
lea dx, vettore[si]
mov ah, 09h
int 21h
ret End INIZIO
prof. Orazio Gambino
leavetca.asm lea+call
.model small call stdout
.data
;the closing
vettore DB 41h,'$',42h,'$’
.code
MOV AX,4C00H
INIZIO: INT 21H
mov ax, @data RET
mov ds, ax stdout:
mov si, 0h mov ah, 09h
lea dx, vettore[si] int 21h
call stdout ret
add si,2h
lea dx, vettore[si] End INIZIO
prof. Orazio Gambino
Subroutine: Call, Proc, Endp
• E’ possibile richiamare più volte una porzione
di codice con le chiamate subroutines,
evitando di scrivere sempre lo stesso codice.
• Infatti, una subroutine incapsula linee di
codice in modo che possano essere
riutilizzate.
• Se una subroutine è fornita da un altro
programmatore, si può utilizzare senza
preoccuparsi di come funziona internamente.
prof. Orazio Gambino
Subroutine: Call, Proc, Endp
• Con le subroutines è possibile realizzare codice
modulare, cioè si può realizzare un programma .asm
costituito da chiamate a subroutines; il problema viene
fremmentato in sottoproblemi di cui si conoscono le
soluzioni, secondo una metodologia di progettazione
algoritmica “top-down”.
• La stessa operazione può essere definita con parametri
diversi
• Semplifica i test e la manutenzione
• Nei linguaggi ad alto livello, sono chiamati: funzioni,
procedure, metodi
• Nei linguaggi assembly, sono chiamati: subroutine
prof. Orazio Gambino
Subroutine: Creare una subroutine
<NomeProcedura> PROC [near|far]
..
; some code to do something
.ret ; if this is not here then your computer will crash
<NomeProcedura> ENDP

La direttiva near indica che la subroutine può essere


chiamata solo nello stesso segmento di codice, far da
sono opzionali. Di default è attiva l’opzione near.
Per invocare una subroutine basta usare l’istruzione Call:

call <NomeProcedura>
prof. Orazio Gambino
Subroutine: chiamata alla subroutine
• Codice che chiama la subroutine:
– Salvataggio dell’indirizzo di ritorno nello stack
(invisibile al programmatore)
– Passaggio dei parametri
• Subroutine che viene chiamata:
– Estrazione dell’indirizzo di ritorno dallo stack
(invisibile al programmatore)
– Prelevamento dei parametri
– Esecuzione del codice
– Salvataggio dei risultati nell’output
– Ritorno al normale flusso di esecuzione (ret)
prof. Orazio Gambino
Rappresentazione della chiamata a
subroutine
mov dx,offset message
call Print
mov ax,4C00h
………
Print Proc
….
ret
Print Endp

prof. Orazio Gambino


Subroutine: proc.asm
.model small Print Proc
.stack 100h mov ah,9 ; print
.data int 21h
message db "Hello, ret
world!",0dh,0ah,'$'
Print endp
.code
start:
end start
mov ax,@data
mov ds,ax
mov dx,offset message
call Print
mov ax,4C00h ; back to DOS
int 21h
prof. Orazio Gambino
Subroutines: DUP.asm
.model small ; subroutine puts
.stack 100h puts proc
.data mov ah, 9h
ostr db 50 dup('*'),'$' int 21h
.code ret
start: puts endp
mov ax, @data end start
mov ds, ax
mov dx, offset ostr
call puts
mov ax, 4c00h
int 21h
;;;;;;;;;;;;;;;;;;
prof. Orazio Gambino
Subroutine: Passaggio dei parametri
• Le subroutine non sarebbero così utili se non
si potessero passare parametri per modificarli
o utilizzarli all'interno della procedura.
• Vi sono tre diversi modi di passare un
parametro:
– tramite registri
– tramite variabili in memoria
– tramite stack

prof. Orazio Gambino


Passaggio tramite registri
• In realtà nell’esempio Proc.asm abbiamo già usato
questo tipo di passaggio perché il registro dx
conserva il dato che verrà usato dalla subroutine
• Offre ottimi vantaggi…
– Il codice risulta molto veloce
– Ogni registro rappresenta un parametro e quindi il
codice risulta di facile scrittura

• … ma anche svantaggi.
– Il nome del registro non è autoesplicativo del suo
contenuto: l’uso del commento diventa vitale per la
comprensione del contenuto di un registro.
– Il numero dei registri è limitato: se ci vogliono molti
parametri come si fa? Si adottano i tipi di passaggi che
seguono.
prof. Orazio Gambino
Subroutine: Passaggio tramite registri
ProcReg.asm
.model small PrintChar PROC
.code
push bx ; save registers to be destroyed
push cx
Start:
xor bh,bh ; clear bh - video page 0
mov dh,4 ;row to print character on mov ah,2 ; function 2 - move cursor
mov dl,5 ;column to print character on int 10h ; row and col are already in dx
; altri due modi di scrivere
; 45 nel registro dx pop bx ; restore bx
; mov dx,0000001000000101b
; mov dx,0405h xor bh,bh ; display page - 0
mov al,254 ; ascii value of block to mov ah,9 ; write char & attrib
display
mov cx,1 ; display it once
mov bl,4 ; colour to display character
int 10h ; call bios service

call PrintChar ; print our character pop cx ; restore registers


mov ax,4C00h ; terminate program
int 21h ret ; return to where it was called
PrintChar ENDP

prof. Orazio Gambino end Start


Passaggio tramite variabili del data
segment
• Per passare i parametri attraverso la memoria, è
sufficiente copiare i parametri in variabili
dichiarate nel segmento .data
• Si può usare una variabile nello stesso modo in
cui si usa un registro, ma bisogna tenere conto
che le istruzioni che utilizzano i registri sono
molto più veloci.
• Infatti, mentre con i registri accediamo a
memorie ram statiche, con le variabili accediamo
a ram dinamiche, cioè la memoria centrale.
prof. Orazio Gambino
Subroutine: Passaggio tramite variabili
ProcVar.asm
.model small PrintChar PROC

.data push ax cx bx ;save registers to be destroyed

Row db ?
xor bh,bh ; clear bh - video page 0
Col db ?
Colour db ? mov ah,2 ; function 2 - move cursor
Char db ? mov dh,Row
mov dl,Col
.code int 10h ; call Bios service

Start:
mov al,Char
mov Row,4 ; row to print character mov bl,Colour
mov Col,5 ; column to print character on xor bh,bh ; display page - 0
mov Char,254 ; ascii value of block to mov ah,9 ; function 09h write char & attrib
display
mov Colour,4 ; colour to display character mov cx,1 ; display it once
int 10h ; call bios service
call PrintChar ; print our character
mov ax,4C00h ; terminate program pop bx cx ax ; restore registers
int 21h

ret ; return to where it was called


PrintChar ENDP

end Start

prof. Orazio Gambino


Alcune novità in ProcVar.asm
• Rispetto al codice già visto, ci sono alcuni
aspetti che lo distinguono e che comunque
possono essere usati in altri contesti, cioè non
necessariamente solo nel passaggio di
parametri ad una procedura.
• Le variabili nel data segment hanno un punto
interrogativo: questo significa che la memoria
per la variabile è allocata, ma non è definito
alcun valore al suo interno.
prof. Orazio Gambino
Alcune novità in ProcVar.asm
• Manca l’inizializzazione del registro DS:
mov ax,@data
mov ds,ax
• Infatti, non si fa uso di un registro che
contiene l’Effective Address della variabile, ma
si fa riferimento all’indirizzo della variabile in
modo statico usando direttamente l’etichetta
(nome) della variabile.

prof. Orazio Gambino


Alcune novità in ProcVar.asm
• Per cancellare un contenuto si fa uso
dell’operando booleano xor
xor bh,bh
• E’ equivalente a:
mov bh,0h
• L’istruzione xor impiega meno cicli di clock
della mov per cui risulta più veloce.
• Nel linguaggio assembly di qualsiasi
microprocessore le istruzioni che richiedono
meno cicli macchina sono quelle preferite.
prof. Orazio Gambino
Subroutine: passaggio dei parametri tramite stack
• Chiamata alla subroutine:
– Riserva spazio sullo stack per i parametri di output
– Pone sullo stack i parametri di input
– Salta alla subroutine (indirizzo di ritorno su stack)
– Preleva i parametri di output dallo stack
• Subroutine
– Preleva l’indirizzo di ritorno dallo stack (utilizzando l’offset relativo
allo SP) e lo salva in un registro indirizzi
– Preleva i parametri di input dallo stack (utilizzando gli offset
relativi allo SP) e li copia nei registri dati/indirizzi
– Effettua la propria elaborazione e calcola i parametri di output
– Pone i parametri di output sullo stack nelle posizioni per essi
riservate (utilizzando gli offset relativi allo SP)
– Ripulisce lo stack
– Salta all’indirizzo di ritorno
prof. Orazio Gambino
.model small
procstak.asm
.code xor bh,bh ; clear bh - video page 0
Start: mov ah,2 ; function 2 - move cursor
mov dh,4 ; row to print string on mov dx,[bp+8] ; restore dx
mov dl,5 ; column to print string on int 10h ; call bios service
mov al,254 ; ascii value of
block to display mov ax,[bp+6] ; character
mov bl,4 ; colour to display mov bx,[bp+4] ; attribute
character xor bh,bh ; display page - 0
push dx ax bx ; put parameters mov ah,9 ; function 09h write char
onto the stack & attrib
mov cx,1 ; display it once
call PrintString int 10h ; call bios service

pop bx ax dx ;restore registers pop cx ; restore registers


mov ax,4C00h ;terminate program pop bp
int 21h
ret ; return to where it was called
PrintString PROC PrintString ENDP

push bp ; save bp end Start


mov bp,sp ; put sp into bp
push cx ; save registers to be
destroyed
prof. Orazio Gambino
Istruzioni di trasferimento: push e pop
• Si è già detto che lo stack e una struttura LIFO (Last In First Out),
cioè l'ultimo valore inserito e sempre il primo ad essere estratto
• Il runtime stack e un array di memoria gestita direttamente dalla
CPU mediante due registri: SS e SP
• Il registro SS indica l'indirizzo iniziale del segmento di memoria
dedicato allo stack
• Il registro SP contiene un offset a 16 bit relativo a qualche
locazione dello stack
• Il registro SP viene manipolato raramente, viene invece
esplicitamente modicato da istruzioni come CALL, RET, PUSH e POP
• Il registro StackPointer SP punta all'ultimo intero inserito nello
stack
prof. Orazio Gambino
Istruzioni di trasferimento: push e pop
• Un'operazione di push decrementa lo stack pointer
di 4 e copia un valore nella locazione dello stack
puntata dallo stack pointer. Lo stack segment
determina l’inizio della zona dello stack.
PRIMA DOPO

SP  1000h 0006h SS  1000h 0006h


0FFCh SP  0FFCh 00a5h
0FF8h 0FF8h
0FF4h 0FF4h
….. …..

prof. Orazio Gambino


Istruzioni di trasferimento: push e pop
• Un'operazione di pop incrementa lo stack pointer di
4 e rimuove un valore nella locazione dello stack
puntata dallo stack pointer. Lo stack segment inizia a
1000h.
PRIMA DOPO
SS  1000h 0006h SP  1000h 0006h
SP  0FFCh 00a5h 0FFCh
0FF8h 0FF8h
0FF4h 0FF4h
….. …..

prof. Orazio Gambino


Istruzioni di trasferimento: xchg
• Scambia il contenuto di due operandi
• Le possibilita sono:
xchg reg, reg
xchg reg, mem
xchg mem, reg
• Per esempio:
xchg ax, bx
xchg ah, al
xchg var1, bx

prof. Orazio Gambino


Incremento e decremento
• Permettono (rispettivamente) di incrementare e
decrementare di 1 un singolo operando. La sintassi è la
seguente:
inc <operando>
dec <operando>
• L’operando può essere un registro o una locazione di
memoria
• Per esempio:
.data
var word 1000h
.code
inc var ; var = 1001h
mov bx, var
dec bx ; bx = 1000h
prof. Orazio Gambino
Addizione: add e adc
• Permettono di addizionare l'operando sorgente allo
operando destinazione
• Entrambi gli operandi possono essere con o senza segno
• La sintassi: add dest,source
• La somma di dest e source viene memorizzata in
dest
• Per esempio:
.data
Var1 DW 2000h
Var2 DW 1000h
.code
mov ax, var1
prof. Orazio Gambino
add ax, var2
Addizione: add e adc
• Il primo operando può essere un registro o una
locazione di memoria, il secondo può essere un registro,
una locazione di memoria o un valore immediato
• I due operandi devono avere la stessa dimensione.
• Inoltre i due operandi NON possono essere entrambi
locazioni di memoria.
• L’istruzione add ha effetti sul registro di stato (registro
dei flags):
– ZF : ha il valore 1 se il risultato è zero;
– SF : ha il valore 1 se il risultato è negativo;
– CF : ha il valore 1 se si è verificato un riporto (carry)
sul bit più significativo.
prof. Orazio Gambino
Addizione: add e adc
• L'istruzione adc esegue esegue la somma di
due operandi, con o senza segno consideran-
do anche il valore del carry flag (CF) e inseren-
do il risultato della somma nel primo operan-
do.
• La sua sintassi è:
adc dest,source

prof. Orazio Gambino


Addizione: add e adc
• Tramite le istruzioni add e adc si può effettuare la
somma di due operandi a 32 bit
(AX:BX) <- (AX:BX) + (CX:DX)
add bx,dx ; somma i 16 bit meno significativi
adc ax,cx ; somma i 16 bit più significativi

adc tiene conto del carry dell’istruzione add usata


per la somma dei 16 bit meno significativi
prof. Orazio Gambino
add-adc.asm
.model small
.stack
; ***sommma a 32 bit***

.data
vet dw 1000h,2000h,3000h,4000h

.code
start:
mov ax, vet
mov bx, vet[1]
mov cx, vet[2]
carry
mov dx, vet[3] x

ax x x x x x x x x x x x x x x x x adc bx x x x x x x x x x x x x x x x x add
add bx, dx
adc ax, cx
cx x x x x x x x x x x x x x x x x = dx x x x x x x x x x x x x x x x x =

mov ax,4C00H x x x x x x x x x x x x x x xx x x x x x x x x x x x x x x x x

int 21H
prof. Orazio Gambino
end start
Sottrazione: sub e subb
• L'istruzione sub esegue la sottrazione tra due
operandi con o senza segno e posiziona il
risultato della sottrazione nel primo operando.
• La sua sintassi è:
sub dest,source
• Il primo operando può essere un registro o
una locazione di memoria, il secondo può
essere un registro, una locazione di memoria o
un valore immediato
• dest = dest - source
prof. Orazio Gambino
Sottrazione: sub e subb
• i due operandi devono avere la stessa
dimensione.
• Inoltre i due operandi NON possono essere
entrambi locazioni di memoria.
• In base al risultato vengono settati i seguenti
flag:
– ZF : ha il valore 1 se il risultato è zero;
– SF : ha il valore 1 se il risultato è negativo;
– CF : ha il valore 1 se si è verificato un riporto (carry)
sul bit più significativo.

prof. Orazio Gambino


Sottrazione: sub e subb
• subb (SuBtract with Borrow)
• Effettua la stessa operazione di sub, ma
comprendendo il carry flag
• dest = dest – source – CF
• L'istruzione SBB permette di effettuare la
sottrazione di numeri maggiori di 16 bit.
(AX:BX) <- (AX:BX) – (CX:DX)

SUB BX, DX ;sottrae i 16 bit meno significativi


SBB AX, CX ;sottrae i 16 bit più significativi

prof. Orazio Gambino


sub_subb.asm
.model small
.stack

; ***sottrazione a 32 bit***

.data
vet dw 1000h,2000h,3000h,4000h

.code

start:
mov ax, vet
mov bx, vet[1]
mov cx, vet[2]
mov dx, vet[3]

SUB BX, DX ;sottrae i 16 bit meno significativi


SBB AX, CX ;sottrae i 16 bit più significativi

mov ax,4C00H
int 21H

end start

prof. Orazio Gambino


Istruzione NEG
• Inverte il segno di un numero mediante
complemento a due
• Sono permessi gli operandi:
NEG reg
NEG mem

prof. Orazio Gambino


Moltiplicazione: mul e imul
• L'istruzione MUL esegue la moltiplicazione tra due
numeri senza segno. La sua sintassi è:
mul <operando>
Corrisponde all'istruzione:
AX = AL*<operando> se l'operando è un byte
AX = DX:AX=AX*<operando> se l'operando è un word
• Quindi a seconda della dimensione dell'operando,
l'istruzione si comporta in modo diverso:
- Se l'operando è di tipo byte, l'altro operando deve
essere posto in AL e il risultato viene posto in AX.
- Se l'operando è di tipo word, l'altro operando deve
essere posto in AX e il risultato viene posto nei due
registri DX:AX.
Da notare è che l'operando non può essere un valore
immediato.
prof. Orazio Gambino
Moltiplicazione: mul e imul
• L'istruzione MUL imposta il CF per indicare se la
parte alta del risultato è usata o no: il flag è a 1 se
viene usata anche la parte alta.
mov al, 5h
mov bl, 10h
mul bl ; CF = 0
mov ax, var1 ; var1 word 2000h
mul var2 ; var2 word 0100h; CF = 1
• Per eseguire moltiplicazioni tra numeri con segno
si utilizza l'istruzione IMUL, che prevede le stesse
caratteristiche dell'istruzione MUL con l'unica
differenza che al posto del flag CF utilizza il flag di
overflow OF.
• Inoltre IMUL può utilizzare anche due o tre
argomenti.
prof. Orazio Gambino
Moltiplicazione: mul e imul
; 1. moltiplicazione con segno 48 * 4
mov al, 48
mov bl, 4
imul bl ; ax = 00c0h, OF = 1
; (ah non e' un'estensione di segno di al)
; 2. moltiplicazione con segno -4 * 4
mov al, -4
mov bl, 4
imul bl ; ax = fff0h, OF = 0
; (ah e' un'estensione di segno di al)
; 3. moltiplicazione con segno 48 * 4
mov ax, 48
mov bx, 4
imul bx ; dx:ax = 000000c0h, OF = 0
; (dx e' un'estensione di segno di ax)
prof. Orazio Gambino
• var4 = (var1 + var2) * var3 • var4 = (var1 * 5) / (var2 - 3)

mov ax, var1 mov ax, var1


add ax, var2 mov bx, 5
mul var3 mul bx
jc overflow mov bx, var2
mov var4, ax sub bx, 3
jmp prossimo div bx
overflow: mov var4, bx
; messaggio di errore per
overflow

prof. Orazio Gambino


Divisione: div e idiv
• L'istruzione DIV esegue la divisione intera tra due
numeri senza segno. La sua sintassi è:
DIV <operando>
• Corrisponde all'istruzione:
– se l'operando è un byte : AL = AX/<operando> e
AH=resto
– se l'operando è un word: AX = DX:AX/<operando> e
DX=Resto
• Da notare è che il divisore NON può essere un
valore immediato.
• L'istruzione DIV può causare una condizione di
overflow se il risultato è troppo grande per
essere contenuto nel registro relativo.
prof. Orazio Gambino
Divisione: div e idiv
• Si deve porre particolare attenzione alla divisione per 0
e per 1.
• Per eseguire divisioni tra numeri con segno si utilizza
l'istruzione IDIV, che prevede le stesse caratteristiche
dell'istruzione DIV.

mov ax, 0083h


mov bl, 2
div bl ; al = 41h, ah = 01h
__________________________________________
mov dx, 0
mov ax, 8003h
mov cx, 100h
div cx ; ax = 0080h, dx = 0003h

prof. Orazio Gambino


div_idiv.asm
.model small
.stack

.data
wvar dw 5000

.code

start:
neg wvar
mov ax, wvar ; dividendo (wvar sword -5000)
cwd ; estensione del segno in dx
;The CWD (convert word to doubleword) instruction
;extends the sign bit of AX into the DX register
mov bx, 256 ; divisore
idiv bx ; quoziente ax = -19, resto dx = -136

mov ax,4C00H
int 21H
end start

prof. Orazio Gambino


Esempio: implementazione della
funzione f(x,y,z) = -x + (y-z)
.model small ; secondo termine (y - z)
.stack mov bx, y
.data sub bx, z
res dw 0 ; addizione e memorizzazione
x dw 25 add ax, bx
y dw 30 mov res, ax
z dw 40
.code ;the closing
start: MOV AX,4C00H
; primo termine (-x) INT 21H
mov ax, x RET
neg ax
end start
prof. Orazio Gambino
Istruzioni di salto
• Un trasferimento di controllo, o branch un
modo di alterare l'ordine in cui le istruzioni
vengono eseguite
• Tutti i linguaggi di programmazione
presentano istruzioni di branching
• E’ possibile suddividere queste istruzioni in:
– trasferimenti incondizionati, per esempio
mediante l'istruzione JMP
– trasferimenti condizionati, in cui la ramicazione si
verifica soltanto se una certa condizione vera. Per
esempio, l'istruzione LOOP
prof. Orazio Gambino
Istruzioni di salto - Loop
• Fornisce un modo semplice per ripetere l'esecuzione di un
blocco di istruzioni per un numero specificato di volte
• il registro cx viene automaticamente utilizzato come contatore
e viene decrementato ogni volta che il ciclo si ripete
• la sintassi : loop <etichetta>
• Esempio:
mov ax,0
mov cx,5
L1:
inc ax
prof. Orazio Gambino loop L1
Istruzioni di salto - Loop
• Avvertenze
– Bisogna evitare di inizializzare il registro cx a zero
prima di avviare il loop. Se questo avvenisse,
l'istruzione loop incrementerebbe cx a e itererebbe
65536 volte
– L’etichetta del ciclo deve trovarsi nell'intervallo da
-128 a +127 rispetto al contatore locale; le istruzioni
macchina hanno una dimensione media di 3 byte,
quindi un loop può contenere circa 40 istruzioni
– una modica del valore di cx all'interno del loop può
avere effetti indesiderati
prof. Orazio Gambino
conta.asm
.model small L1:
.stack mov str,bl
.data mov dx,offset str
str db '0','$' mov ah,9
.code int 21h
start: inc bl
mov ax, @data loop L1
mov ds, ax
mov bl,41h ;the closing
mov cx,05h mov ax,4c00h
int 21h
cx si autodecrementa
nel ciclo fino ad arrivare end start
a0
prof. Orazio Gambino
copia.asm
.model small mov ah,9 ; DOS Function
.data call to
str1 db "ciao","$" ; print a
str2 db 5 dup('0') message
mov dx,offset str2
.code
int 21h
start:
mov ax, @data
mov ds, ax ;the closing
mov bl,0 MOV AX,4C00H
mov cx,5
INT 21H
L1:
mov bl, str1[si] end start
mov str2[si], bl
inc si
loop L1

prof. Orazio Gambino


.model small
.stack
.data
Prod_Int.asm mov al,[risultato]
call print

vet_h db 1,2,3,4
vet_v db 5,6,7,8 mov ax,4C00H
risultato db 00h,00h,'$' int 21H
.code
start: print proc
mov ax,@data ; Initialize DS
mov bl, 10 ; Base 10 -> divisor
mov ds,ax ; Initialize DS
mov ax,0001h ;lea di, DEC_END
mul vet_h mov di,offset risultato+2
mul vet_v ; ax=1*vet_h[0]*vet_v[0] L1:
add risultato,al dec di ; fill the decimal-string
in reverse order
mov ax,0001h
xor ah, ah ; Clear AH for division
mul vet_h[1]
mul vet_v[1] ; div bl ; AL = AX / BL Remainder AH
ax=1*vet_h[1]*vet_v[1] or ah, 30h ; Convert AH to ASCII
add risultato,al mov BYTE PTR [di], ah ;
Save AH in the decimal-string
mov ax,0001h test al, al ; AL == 0?
mul vet_h[2]
jnz L1 ; No: once more
mul vet_v[2] ;
ax=1*vet_h[2]*vet_v[2] mov ah, 09h ; WRITE STRING TO
add risultato,al STANDARD OUTPUT
mov dx, di ; Result of al2dec
mov ax,0001h int 21h
mul vet_h[3] ret ; Return DS:DI Pointer to the
mul vet_v[3] ; decimal-string
ax=1*vet_h[3]*vet_v[3]
prof. Orazio Gambino
print endp
add risultato,al
ProdLoop.asm
.model small print proc
.stack mov bl, 10 ; Base 10 -> divisor
.data mov di,offset risultato+2
vet_h db 1,2,3,4 L1:
vet_v db 5,6,7,8 dec di ; fill the decimal-string in
risultato db 00h,00h,'$' ; reverse order
xor ah, ah ; Clear AH for division
.code div bl ; AL = AX / BL Remainder AH
start: or ah, 30h ; Convert AH to ASCII
mov ax,@data ; Initialize DS mov BYTE PTR [di], ah ;
mov ds,ax ; Initialize DS Save AH in the decimal-string
mov bx,0000h test al, al ; AL == 0?
mov cx,04h jnz L1 ; No: once more
mov ah, 09h
Ciclo: ; WRITE STRING TO STANDARD OUTPUT
mov ax,0001h mov dx, di ; Result saved into dx
mul vet_h[bx] int 21h
mul vet_v[bx] ; ax=1*vet_h[bx]*vet_v[bx] ret ng
add risultato,al
print endp
inc bx
loop Ciclo
end start
mov al,[risultato]
call print
prof. Orazio Gambino
strinv.asm
.model small L2:
.stack 100h pop ax
.data mov str2[si], al
str1 db "ciao","$" inc si
str2 db 5 dup(0) loop L2
.code mov al, "$"
start: inc si
mov ax, @data mov str2[si], al
mov ds, ax mov dx, offset str2
mov si, 0 mov ah, 9h
mov cx, 5 int 21h
dec cx ;the closing
L1: MOV AX,4C00H
mov al, str1[si] INT 21H
push ax end start
inc si
loop L1
mov cx, 5
dec cx
mov si, 0
prof. Orazio Gambino
Istruzioni di salto - Jmp
• Provoca un trasferimento incondizionato ad una
locazione interna al segmento di codice
• la locazione destinazione deve essere identicata
mediante un'etichetta
• la sintassi : jmp <etichetta>
• Esempio:
top:
...
...
jmp top ; attenzione si genera un loop infinito

prof. Orazio Gambino


Confronto CMP
• Per fare in modo che il salto venga eseguito
solo se si verifica una particolare condizione, si
usano le istruzioni di salto condizionato. Le
istruzioni di salto condizionato si basano sul
valore dei flag impostati dalle operazioni
aritmetico-logiche e dall'istruzione CMP
• L'istruzione CMP permette di confrontare due
dati e ha il formato:

cmp <operando1>, <operando2>

prof. Orazio Gambino


Confronto CMP
• Il primo operando può essere un registro o una
locazione di memoria, il secondo può essere un
registro, una locazione di memoria o un valore
immediato; i due operandi devono avere la stessa
dimensione.
• Inoltre i due operandi NON possono essere entrambi
locazioni di memoria.
• L'istruzione CMP si comporta come una sottrazione;
sottrae dal primo operando il secondo, trascurando
però il risultato.
• Essa infatti modifica solo i flag affinché possano essere
usati correttamente dalla successiva istruzione di salto
condizionato.
prof. Orazio Gambino
Salti Condizionati
• Ad ogni flag sono associate due istruzioni di salto
condizionato: una che salta se il suo valore è a uno,
mentre l'altra salta se il valore è a zero (quest'ultima è
indicata dalla lettera N che sta ad indicare Not).
• Tali istruzioni sono:
- JZ : salta se il flag Z è a 1 (Zero Flag)
- JNZ : salta se il flag Z è a 0
- JS : salta se il flag S è a 1 (Sign Flag)
- JNS : salta se il flag S è a 0
- JO : salta se il flag O è a 1 (OverFlow Flag)
- JNO : salta se il flag O è a 0
- JC : salta se il flag C è a 1 (Carry Flag)
- JNC : salta se il flag C è a 0
- JP : salta se il flag P è a 1 (Parity Flag)
- JNP : salta se il flag P è a 0
prof. Orazio Gambino
jc.asm
.model small MOV DX,OFFSET msg
.stack 100h MOV AH,09H
.data INT 21H
num1 db 50H JMP EXIT
num2 db 0FFh
msg DB "carry = carry1:
0",10,13,'$' MOV DX,OFFSET msg2
msg2 DB "carry = MOV AH,09H
1",10,13,'$' INT 21H
.code EXIT:
START: MOV AX,4C00H
MOV AX,@data INT 21H
MOV DS,AX RET
MOV bl,num1
add bl,num2 END START
JC carry1 ; jump
se CF = 1
prof. Orazio Gambino
Confronto e salto
condizionato CMP , Jxx

• Oltre alle istruzioni di salto condizionato che si


riferiscono direttamente ai flag, ve ne sono altre,
basate sugli stessi flag ma più facili da ricordare e
utilizzare.

- JE : salta se Operando1=Operando2
- JNE : salta se Operando1<>Operando2

prof. Orazio Gambino


Confronto e salto
condizionato CMP , Jxx
• Confronto tra numeri con segno:
- JL : salta se operando1<operando2
- JG : salta se operando1>operando2
- JLE : salta se operando1<=operando2
- JGE : salta se operando1>=operando2
• Confronto tra numeri senza segno:
- JB : salta se operando1<operando2
- JA : salta se operando1>operando2
- JBE : salta se operando1<=operando2
- JAE : salta se operando1>=operando2
prof. Orazio Gambino
Salto condizionato
• IMPORTANTE !!!!
Da notare che nel processore 8086 le
istruzioni di salto richiedono che
l'indirizzo di destinazione sia
abbastanza vicino: tra -128 byte e
+127 byte.

prof. Orazio Gambino


divzero.asm
mov ax, dividendo
mov bl, divisore
cmp bl, 0
je DivZero
div bl
...
divZero:
; messaggio di errore per tentata
divisione per zero
prof. Orazio Gambino
.model small
.stack 100h Confront.asm
.data
msg DB "bl is NOT equal to 0",10,13,'$'
msg2 DB "bl is equal to 0",10,13,'$'

.code

START:
MOV AX,@data ;Data viene trasferito nel registro AX
MOV DS,AX ;il registro AX viene trasferito nel reg. di segmento DS

MOV bl,01H
CMP bl,00H
JE EQUAL

MOV DX,OFFSET msg ;caricamento offset della frase da stampare


MOV AH,09H ;richiesta di stampa: 09H nel registro alto AH
INT 21H ;interrupt per la stampa
JMP EXIT

EQUAL:
MOV DX,OFFSET msg2
MOV AH,09H ;richiesta di stampa: 09H nel registro alto AH
INT 21H ;interrupt per la stampa

EXIT:
MOV AX,4C00H
INT 21H

END START
prof. Orazio Gambino
Flags e salti condizionati
• Ecco alcuni dei flag coinvolti nelle istruzioni
di salto condizionato:
– CF(Carry Flag, flag di Riporto): viene forzata a 1 se
una somma/sottrazione ha prodotto riporto/prestito;
influenza i seguenti salti condizionati: JC (salta
se CF=1), JNC (salta se CF=0), JB (salta
se CF=1), JAE (salta se CF=0), JA (salta
se CF=0 e ZF=0), JBE (salta se CF=1 o ZF=1).
– PF(Parity Flag, flag di Parità): viene forzata a 1 se il
risultato di un'operazione contiene un numero pari
di 1
– AF(Auxiliary Flag, flag di Riporto Ausiliario): viene
forzata a 1 se un'operazione ha prodotto riporto tra il
primo (bit0÷bit3) e il secondo nibble (bit4÷bit7).
prof. Orazio Gambino
Flags e salti condizionati
– ZF(Zero Flag, flag di Zero): viene forzata a 1 se
un'operazione ha dato risultato nullo; influenza i
seguenti salti condizionati: JZ (salta se ZF=1), JNZ (salta
se ZF=0), JE (salta se ZF=1), JNE (salta
se ZF=0), JG (salta se ZF=0 e SF=OF), JLE (salta
se ZF=1 o SF<>OF), JA (salta se ZF=0 e CF=0), JBE (salta
se ZF=1 o CF=1).
– SF(Sign Flag, flag di Segno): viene forzata al valore
corrente del bit più significativo del risultato di
un'operazione; come è noto nei numeri con
segno 0 significa positivo e 1 significa negativo;
influenza i seguenti salti condizionati: JS (salta
se SF=1), JNS (salta se SF=0), JG (salta
se SF=OF e ZF=0), JGE (salta se SF=OF), JL (salta
se SF<>OF), JLE (salta se SF<>OF o ZF=1).
prof. Orazio Gambino
Flags e salti condizionati
– OF(Overflow Flag, flag di Overflow): viene forzata
a 1 se un'operazione ha prodotto trabocco, cioè ha
superato il numero massimo per il registro coinvolto
(256=100H a 8bit, 65536=10000H a 16bit, ecc);
influenza i seguenti salti condizionati: JO (salta
se OF=1), JNO (salta se OF=0).

prof. Orazio Gambino


Istruzioni di salto
condizionato - Jxxx

prof. Orazio Gambino


Cicli condizionati
• Con i salti condizionati (e non) è possibile
creare cicli differenti da quelli creati con
l’istruzione Loop
• Infatti, è possibile creare condizioni per
l’uscita dal ciclo, o per continuarlo differenti,
dal semplice conteggio sul registro cx
• Gli esempi a seguire riguardano proprio

prof. Orazio Gambino


CicloCon.asm
.model small
.stack 100h
.data
message db 'Hello, world!',0dh,0ah,'$'

.code

start:
mov ax,@data ; Initialize DS
mov ds,ax ; Initialize DS
xor si,si
ciclo:
mov bl,message[si]
cmp bl,'$' ; verifica che la stringa sia finita
je exit
inc si
cmp bl,'w' ; sostituiamo la w con W
jne ciclo
mov message[si-1],'W'

exit:
mov dx,offset message
mov ah,9 ; DOS Function call to print a message
int 21h

mov ax,4C00h ; DOS Function call to exit back to DOS


int 21h

prof.
endOrazio Gambino
start
copia$.asm
.model small exit:
.data mov ah,9 ; DOS
str1 db “ciao","$" Function call to
str2 db ? print a message
mov dx,offset str2
.code int 21h

start: ;the closing


mov ax, @data MOV AX,4C00H
mov ds, ax INT 21H
mov bl,0 end start
L1:
mov bl, str1[si]
mov str2[si], bl
cmp bl,'$'
je exit
inc si
prof. Oraziojmp
Gambino L1
Scorrimento e Rotazione dei bit
• Scorrimento • Rotazione
– SHL (shift left) – ROL (rotate left)
– SHR (shift right) – ROR (rotate right)
– SAL (shift arithmetic left) – RCL (rotate carry left)
– SAR (shift arithmetic right) – RCR (rotate carry right)

Lo shift logico riempie di zeri le La rotazione può avvenire


posizioni che si liberano, con o senza presenza del bit
mentre lo shift aritmetico di carry che viene coinvolto
riempie le posizioni che si nella rotazione.
liberano con il bit disegno del
numero soggetto a
scorrimento.

prof. Orazio Gambino


Scorrimento e Rotazione dei bit
• Scorrimento • Rotazione
SHL/SHR <destination>, count ROL/ROR <destination>, count
SAL/SAR <destination>, count RCL/RCR <destination>, count

SHL/SHR reg, imm8 ROL/ROR reg, imm8


SHL/SHR mem, imm8 ROL/ROR mem, imm8
SAL/SAR reg, imm8 RCL/RCR reg, imm8
SAL/SAR mem, imm8 RCL/RCR mem, imm8

prof. Orazio Gambino


Scorrimento e Rotazione dei bit
• Scorrimento • Rotazione
mov bl, 8Fh ; bl = 1001111b mov al, 40h ; al = 01000000b
shl bl, 1 ; bl = 0011110b,CF = 1 rol al, 1 ; al = 10000000b CF = 0
… rol al, 1 ; al = 00000001b CF = 1
mov dl, 5 ; dl = 00000101 5 rol al, 1 ; al = 00000010b CF = 0
shl dl, 1 ; dl = 00001010 10 …
… mov al, 26h
mov dl, 10 ; dl = 00001010 10 rol al, 4 ; al = 62h
shl dl, 2 ; dl = 00101000 40 …
… mov al, 01h ; al = 00000001b
mov al, 0d0h ; al = 11010000b ror al, 1 ; al = 10000000b CF = 1
shr al, 1 ; al = 01101000b, CF=0 ror al, 1 ; al = 01000000b CF = 0
… …
mov dl, 32 ; dl = 00100000 32 clc ; CF=0
shr dl, 1 ; dl = 00010000 16 mov bl, 88h ; bl = 10001000b CF=0
… rcl bl, 1 ; bl = 00010000b CF = 1
mov al, 01000000b ; al = 64 rcl bl, 1 ; bl = 00100001b CF = 0
shrprof.al, 3 ; al = 00001000b 8
Orazio Gambino
Scorrimento e Rotazione dei bit
• Scorrimento • Rotazione
mov al, 0f0h ; al = 11110000b (-16) stc ; CF = 1
sar al, 1 ; al = 11111000b (-8) CF=0 mov ah, 10h ; ah = 00010000b CF=1
… rcr ah, 1 ; ah = 10001000b
mov dl, -128 ; dl = 10000000b (-128)
sar dl, 3 ; dl = 11110000b (-16)

prof. Orazio Gambino

Potrebbero piacerti anche