Set di Istruzioni P 8086
In generale le istruzioni di qualsiasi P sono riconducibili ai
seguenti gruppi fondamentali:
1. Istruzioni di trasferimento dati
2. Istruzioni aritmetiche e logiche
3. Istruzioni di shift e rotazione
4. Istruzioni per la manipolazione delle stringhe
5. Istruzioni di controllo della sequenza
6. Istruzioni di controllo del P
Istruzioni
Aritmetiche
Logiche
Istruzioni di
Trasferimento dati
Istruzioni per il
Controllo della Sequenza
SET
ISTRUZIONI
P 8086
Istruzioni per la
Manipolazione di
Stringhe
Istruzioni di
Shift e Rotazione
Istruzioni per il
Controllo del P
1
ISTRUZIONI DI
TRASFERIMENTO DATI
Queste istruzioni hanno come obiettivo lo spostamento di
dati o per la memoria o per le periferiche di I/O, con uno dei
registri interni della CPU. È ammesso anche lo spostamento
tra registri, mentre raramente è consentito quello diretto tra
memoria e memoria.
ISTRUZIONI DI
TRASFERIMENTO
DATI
Tra registri
Registri - Disp. I/O
Registri - Memoria
2
ISTRUZIONI
LOGICHE / ARITMETICHE
Queste istruzioni sono strettamente collegate con le funzioni
implementate nell’ALU, che è il circuito combinatorio che le
realizza. Sono previste operazioni con segno e senza
segno, a dimensione variabile in funzione degli operandi ed
in grado di aggiustare la codifica del risultato al fine di
adeguarla alla rappresentazione decimale. Le operazioni di
moltiplicazione e divisione non sono totalmente
combinatorie, bensì sono realizzate tramite un algoritmo a
passi successivi e quindi richiedono un notevole tempo di
esecuzione. Le operazioni logiche implementate sono
rappresentate dai principali operatori booleani.
3
ISTRUZIONI DI
SHIFT E ROTAZIONE
Queste istruzioni hanno l’obiettivo di “spostare” a destra o a
sinistra il contenuto dell’ operando di un certo numero di
posti. Le differenze tra le varie istruzioni riguardano come
vengono trattati i bit che “escono” dall’ operando e viceversa
quelli che sono immessi a causa della traslazione o
rotazione.
4
ISTRUZIONI DI
CONTROLLO DELLA
SEQUENZA
Questo tipo di istruzioni permettono di variare la struttura
strettamente sequenziale di un programma imponendo al
registro IP un nuovo valore di indirizzo. Le istruzioni di
questo gruppo si possono ulteriormente suddividere in 4
categorie:
1. Salti incondizionati
2. Salti subordinati ad una condizione
3. Chiamata a subroutine e ritorno
4. Interrupt software
Istruzioni di Controllo
Sequenza
Salti
incondizionati
Interrupt Software
CALL subroutine
Salti condizionati
5
ISTRUZIONI DI
MANIPOLAZIONE DELLE
STRINGHE
Le stringhe, nel linguaggio dell’8086, sono sequenze di byte
o di word. Il set di istruzioni di questo p comprende 5
istruzioni realizzate appositamente per la manipolazione
delle stringhe. Caratteristica comune di queste istruzioni è di
non avere un operando: infatti lavorano su stringhe
indirizzate dai registri indice SI e DI, automaticamente
aggiornati dopo l’operazione. L’aggiornamento può
consistere in una operazione di incremento o di decremento
dell’indice, in relazione allo stato della flag DF (direction
flag).
SI: Source Index
DI: Destination Index
6
ISTRUZIONI DI
TRASFERIMENTO DATI
Questo gruppo di istruzioni è quello statisticamente più
utilizzato. In esse spicca l’istruzione MOV, estremamente
flessibile e molto potente, grazie ai numerosi modi di
indirizzamento di cui dispone.
MOV op _ dest. op_sorg
Reg. / Mem .
Reg./ Mem .
Reg. / Mem .
Reg.
Immediato
Reg. Segmento
L’operando
sorgente
viene
copiato
nell’operando
destinazione. Si noti che tale istruzione non è distruttiva per
l’operando sorgente: sicuramente ciò che era presente nell’
operando destinazione verrà cancellato.
7
Vediamo ora quali sono le potenzialità di questa istruzione,
raccogliendole in forma tabellare.
MODI DI INDIRIZZAMENTO
SUPPORTATI
Registri
Reg/Mem  Reg
Reg/Mem 
Immed.
SI
SI
SI
SI
SI *
NO
Di uso generale
AX, BX, CX, DX
[AH, AL,…, DH, DL]
Puntatori e indici
SI, DI, SP, BP
Di Segmento
CS, DS, ES, SS
* Solo uno dei due registri può essere di segmento.
Esempi:
a)
b)
c)
d)
e)
MOV
MOV
MOV
MOV
MOV
AL, 00
CX, 00FF
[0204], AX
BX, [0010]
[BX], AL
8
PUSH / POP
Queste istruzioni permettono di caricare (PUSH) o prelevare
(POP) i dati posti nell’area di memoria Stack.
PUSH op_sorg
POP op_dest
OP: REG / MEM; Reg = Registro a 16 bit escluso IP ed RF
Il registro IP è escluso in quanto “salvato” automaticamente
quando si realizza un salto.
Il registro RF delle Flag è escluso in quanto esistono per
esse apposite istruzioni di salvataggio.
9
PUSHF / POPF
Queste istruzioni funzionano in modo analogo alle normali
PUSH e POP però il loro operando è fisso. L’operando su
cui esse operano è il registro delle flag. Si noti che queste
istruzioni sono le uniche che permettono l’accesso alle flag
nel senso di manipolazione. Si pensi alla flag di trappola “T”
che permette l’esecuzione del programma in modo “passo passo”.
Esempio:
Inserimento del contenuto del registro delle flag, in cima allo
stack, quindi spostamento di questo nel registro AX.
Operazione inversa.
a) PUSHF + POP AX
FLAG H
FLAG L
b) PUSH AX + POPF
FLAG H
FLAG L
In questo esempio si nota come dopo una PUSHF , che
inserisce in cima allo stack il contenuto del registro delle
flag, basta realizzare una normalissima istruzione di POP
(nel nostro caso POP AX) per avere a disposizione il
contenuto delle flag. Il tutto può essere ripristinato tramite
una normale istruzione di POP.
10
LAHF / SAHF
Queste sono istruzioni che agiscono sul registro delle flag,
in particolare sulla parte bassa di questo, spostandolo nel
registro AH, e viceversa:
LAHF = L oad AH with flag
SAHF = S tore AH into flag
Esse permettono di leggere e di modificare il valore dei flag.
Per queste in particolare si faccia riferimento alla tabella
seguente:
SF: Sign flag
ZF: Zero flag
AF: Aux flag
PF: Parity flag
CF: Carry flag
CF: Può essere sia testato che modificato. (istruzioni di salto
condizionato o da CF )
SF, ZF, PF: Possono essere solo testati.
AF: Non può essere né letto né modificato. Tale flag viene
utilizzato direttamente dalla ALU.
11
XCHG
Questa istruzione è a due 2 operandi dei quali si scambia
il contenuto:
XCHG = eXCHanGe
Sintassi:
XCHG op_1, op_2
Modi di
Indirizzamento:
REG / MEM
REG
REG
REG
Registri di uso generale
Registri indici, base
NON tra registri di segmento
REG
MEM
Sia in modo diretto che in modo
indiretto
Esempi:
XCHG
XCHG
XCHG
BX, SI
AL, [xxxx]
DI, [BX + SI + Spiazzamento 8/16 bit con segno]
12
XLAT
XLAT = transLATe byte to AL
Questa istruzione utilizza il modo di indirizzata implicito,
ovvero non ha operandi ed utilizza registri fissi per puntare
alla memoria. In particolare utilizza il registro BX; l’indirizzo
di memoria a cui ci riferirà così realizzato:
[DS:BX+AL]
In pratica la memoria viene indirizzata dal registro BX con
un offset positivo contenuto in AL, il tutto all’interno del
segmento dei dato puntato da DS.
“IL DATO CONTENUTO ALL’INDIRIZZO SPECIFICATO,
VIENE TRASLATO NEL REGISTRO AL.”
13
LEA
LEA = Load Effective Address to Register
Sintassi: LEA Registro destinazione, ind. Memoria
Il registro destinazione è un registro di uso generale a 16
bit, indice o base; in esso sarà caricato l’offset specificato
dal secondo operando. L’indirizzo di memoria espresso dal
secondo operando è in forma diretta o indiretta.
Esempi:
LEA SI, [BX + SI + 4]
SI = BX + DI + 4
CON MODALITÁ INDIRETTA
LEA SI, [1000]
CON MODALITÁ DIRETTA
14
LDS /LES
LDS = Load pointer to DS
LES = Load pointer to ES
Sintassi: LDS operando _ destinazione, operando _sorgente
Op_dest : registro
Op_sorg : riferimento diretto o indiretto alla memoria
“Il contenuto della locazione di memoria indirizzata dall’
operando sorgente viene posto nel registro specificato dal
primo operando, mentre il contenuto della locazione
successiva viene posto nel registro DS (LDS) o ES (LES).”
Esempio:
LDS BX, [SI + 2]
(LES BX, [SI + 2])
SI = 0200
Questo tipo di istruzioni sono utilizzate in programmi di una
certa complessità, in cui sono presenti più segmenti dati.
15
ISTRUZIONI
ARITMETICHE
È facilmente intuibile come questo gruppo di istruzioni sia di
fondamentale importanza per un µp. L’8086 oltre alle
consuete operazioni di somma e sottrazione, consente
istruzioni relative a operazioni di moltiplicazione e
divisione, tra operandi a 8 bit o a 16 bit con o senza segno!
Tali istruzioni non sono frutto di hardware bensì di
firmware, ovvero tramite un microprogramma memorizzato
nella CPU. In considerazione di ciò, tali istruzioni sono
relativamente lente. Le istruzioni aritmetiche, insieme a
quelle logiche e di manipolazione dei flag, sono le uniche,
con qualche eccezione, che variano il contenuto del
registro delle flag.
16
ADDIZIONE
E
DESTINAZIONE
SOTTRAZIONE
SORGENTE
ALU
CF
Le istruzioni di addizione e sottrazione sono disponibili nel
formato a 8 e 16 bit, con o senza eventuale riporto.
Sintassi:
ADD
ADC
SUB
SBB
dest, sorg;
dest, sorg;
dest, sorg;
dest, sorg;
dest = dest + sorg
dest = dest + sorg + carry
dest = dest – sorg
dest = dest – sorg – carry
17
N.B.: Le istruzioni di somma e sottrazione alterano il
contenuto di tutti i flag aritmetici:
OF: posto a 1 in caso di overflow
SF: copia del bit di segno
ZF: posto a 1 se il risultato è 0
AF: posto a 1 se c’è riporto intermedio
PF: posto ad 1 se il risultato è pari
CF: posto ad 1 in caso di riporto sia per operazioni su byte
che su word
Modi di indirizzamento supportati:
REG / MEM  REGISTRO
REG / MEM  IMMEDIATO
DESTINAZIONE
Registro
Memoria
Registro
Registro
Memoria
Accumulatore
SORGENTE
Immediato
Immediato
Registro
Memoria
Registro
Immediato
18
ESEMPI
ADD AX, 1
ADC [DI],0100
SUB AL, BL
SBB DX, [1000]
ADD [DI], AX
SUB AL, 50
Esempio di Somma di 2 parole da 32 bit
MOV
ADD
MOV
MOV
ADC
MOV
AX, WORD1_L
AX, WORD2_L;
WORD3_L, AX
AX, WORD1_H
AX, WORD2_H;
WORD3_H, AX
word1_L + word2_L = word3_L (mod. flag)
word1_H + word2_H = word3_H (mod. flag)
Word1_H
Word1_L
AX
Carry
Flag
Word2_H
ALU
AX
Carry
Flag
AX
Word2_L
ALU
AX
DAA / DAS
Word3_H
Word3_L
2a Addizione con riporto
1a Addizione senza riporto
19
DAA
DAS
(Decimal Adjust for Add)
(Decimal Adjust for Subtract)
“Le operazioni di somma e sottrazione avvengono su cifre
binarie espresse in esadecimale, Al fine di implementare
una aritmetica in codice BCD, occorre aggiustare i risultati.
Si ricordi infatti che in codice BCD le combinazioni a 4 bit da
1010 a 1111 non esistono: tali combinazioni sono possibili
però in operazioni HEX. Le istruzioni precedenti servono
quindi ad eliminare le ambiguità in codice BCD.”
Esempio:
AH
AL
MOV
AL, 47
00
47
ADD
AL, 34
00
7B
00
81
DAA
Come si nota dal risultato, in codice BCD il numero 7B non
ha senso, non esistendo la combinazione ‘1011’ = ( B ) HEX ,
occorre quindi (come sicuramente si ricorderà !) sommare la
quantità “ 6 ” per poter rientrare in codice. Tale operazione è
realizzata dalla DAA . Tale istruzione non ha un operando,
bensì opererà sul risultato dell’addizione: va quindi posta
logicamente dopo di essa.
“ operazione ad 8 bit “ .
20
Tutto quanto a proposito della DAA vale anche per la DAS,
fermo restando che, trattandosi di una sottrazione, al
simbolo ‘ E ’ = ‘ 1110 ’ che non è contemplato nel codice
BCD andrà sottratta la quantità ‘6’ = ‘0110’.
Esempio:
MOV
SUB
DAS
AL, 65
AL, 37
(65) Hex
=
(37) Hex
=
-----------(2E) Hex
=
(0110 0101) Bin (0011 0111) Bin =
---------------------(0010 1110) Bin -
(06) Hex
-----------(28)Hex
(0000 0110) Bin
--------------------(0010 1000) Bin
=
=
=
(28)Hex è il risultato corretto in BCD dopo la DAS
21
CMP
Tale istruzione non ha un operando, bensì opererà sul
risultato della sottrazione: va quindi posta logicamente dopo
di essa.
“operazione ad 8 bit”.
Normalmente tale istruzione viene utilizzata insieme alle
istruzioni di salto condizionato, al fine di implementare delle
strutture condizionali.
Sintassi:
CMP op_1, op_2
In sostanza viene realizzata una operazione di sottrazione
tra op_1 ed op_2, senza però modificare nessun operando,
bensì modifica solo il valore delle flag.
22
MODI DI INDIRIZZAMENTO
REG / MEM
REG / MEM
REG
IMMEDIATO
Esempi:
CMP
CMP
CMP
CMP
CMP
N.B.
Modo di indirizzamento:
Reg, Reg
[xxxx], Reg
[Reg], Reg
[Reg], xx
BY [Reg + Reg + offset], xx
Reg - Reg
Mem dir. - Reg
Mem ind.- Reg
Registro imm.
Mem ind.imm.
BY = Byte PTR = Byte puntato in memoria
dall’indirizzo
[Reg + Reg + offset] .
23
NEG
Questa istruzione fornisce il complemento a 2 dell’ operando.
Il risultato sarà memorizzato nell’ operando stesso.
Sintassi : NEG op
Esempio:
MOV
AL, 50
NEG
AL
( B0 )Hex = (-50)Hex
Modi di indirizzamento supportati:
REG / MEM
NEG AL
NEG BY [bx + di]
NEG WO [xxxx]
N.B.:
; Reg
; memoria indiretto
; memoria diretto
WO = WORD PTR = Word (2 byte) puntata in
memoria dall’indirizzo [xxxx]
24
INC / DEC
Queste istruzioni incrementano o decrementano il contenuto
dell’operando. Non c’è influenza sulla flag di carry.
Sintassi : INC op / DEC op
Modi di indirizzamento supportati : REG / MEM
Esempi:
INC AX;
DEC
AL, [BX] ;
DEC
WO [xxxx] ;
Registro
Registro indiretto
Memoria diretto
25
MUL / IMUL
L’istruzione MUL effettua la moltiplicazione tra numeri a 8 o
16 bit senza segno, mentre l’istruzione IMUL agisce su
numeri con segno. Le due istruzioni sono codificate con due
codici diversi in quanto le operazioni su numeri con segno
abbisognano di intervernti correttivi prima e dopo
l’operazione stessa.
L’OPERAZIONE VIENE EFFETTUATA TRAMITE UN
ALGORITMO IN FIRMWARE.
Sintassi:
MUL
IMUL
OP
OP
; (unsigned MUL tiply)
; (Integer MUL tiply)
L’operando può essere un Registro oppure la memoria.
REG / MEM
L’altro operando è implicitamente l’accumulatore.
AL = operazione a 8 bit
AX = operazione a 16 bit
I flag modificati sono essenzialmente OF e CF ovvero la flag di
Overflow e quella di Carry.
26
SCHEMATIZZAZIONE DELLA “ MUL” E DELLA “IMUL” AD 8 E 16 BIT
Moltiplicando (8bit) (16bit)
AL (AX)
Moltiplicatore (8 bit)
(16 bit)
OPERANDO 8 bit (16 bit)
MUL/IMUL
Prodotto (16 bit)
Prodotto (16 bit bassi )
Prodotto (16bit alti )
(DX)
AX (AX)
27
DIV / IDIV
Sintassi:
DIV
IDIV
op
op
; (Unsigned DIV ision)
; (Integer DIV ision)
MODI DI INDIRIZZAMENTO REG - MEM
OPERANDO
DIV
IDIV
REG 8 BIT
DIV CL
IDIV CL
REG 16 BIT
DIV CX
IDIV CX
MEM 8 BIT
DIV [1000]
IDIV [1000]
MEM 16 BIT
DIV TABLE [SI] IDIV TABLE [SI]
In particolare la DIV esegue la divisione senza segno tra il
contenuto dell’accumulatore (nel caso di 1 byte) o
dell’accumulatore e della sua estensione, ovvero DX (nel
caso di divisione a parola), per l’operando sorgente. Il
quoziente viene depositato in AL o in AX, a seconda che la
divisione sia ad 8 o a 16 bit. Il resto invece viene depositato
in AH (8 bit) o in DX (16bit). Se il quoziente va oltre la
capacità del Registro destinazione o se si usa uno zero
come divisore, il componente genera automaticamente una
interruzione. Nel caso della IDIV il tutto è analogo al
precedente, ma gli operandi vengono trattati con segno. Le
operazioni di correzione del risultato sono identiche a quelle
viste per la IMUL.
28
SCHEMATIZZAZIONE DELLA “ DIV” E DELLA “IDIV” AD 8 Bit .
DIVISORE ( 8 bit)
DIVIDENDO ( 8 bit)
OPERANDO
AX
DIV / IDIV
RESTO ( 8 bit)
QUOZIENTE ( 8 bit)
AH
AL
29
SCHEMATIZZAZIONE DELLA “ DIV” E DELLA “ IDIV ” AD 16 Bit .
DIVISORE ( 16 bit)
DIVIDENDO ( 16 bit)
DX
AX
OPERANDO
DIV / IDIV
RESTO ( 8 bit)
QUOZIENTE ( 8 bit)
AH
AL
30
ISTRUZIONI
LOGICHE
La caratteristica di questo gruppo di istruzioni, è che non
considerano l’operando come un numero (binario, esadecimale o
BCD) bensì come un insieme di bit. Queste istruzioni infatti, sono
definite “logiche” in quanto effettuano una operazione Logica
Boolena sui bit dell’ operando. Possiamo aggiungere ancora che
questo gruppo di istruzioni può divedersi in due sottogruppi, a
seconda del numero di operandi coinvolti nelle operazioni
considerate, in particolare si avranno:
a) SINGOLO OPERANDO (9 Istruzioni)
b) DOPPIO OPERANDO (4 Istruzioni)
SINGOLO OPERANDO
DOPPIO OPERANDO
NOT
AND
SHL
TEST
SHR
OR
SAL
XOR
SAR
ROL
ROR
RCR
RCL
31
Vediamo una per una tutte le istruzioni logiche appartenenti al 1°
gruppo:
NOT
Questa istruzione esegue la negazione
dell’operando: esegue il complemento a 1
agendo sul singolo bit del dato, sia esso
byte o parola.
SHL / SAL
Questa istruzione esegue lo slittamento
logico a sinistra del dato (byte o parola). Il
numero di spostamenti che si realizzano è
specificato in un apposito Registro
contatore .
SHIFT
SAIFT
CF
LEFT ( Tralsazione Logica a sinistra )
LEFT ( Tralsazione Aritmetica a sinistra )
7(15)
0
0
Byte o Word
SINTASSI :
SINTASSI :
SHL op , Count
SAL op , Count
Gli SHIFT si differenziano in LOGICI e ARITMETICI in quanto una
operazione di spostamento verso sinistra ha come effetto aritmetico
quello di moltiplicare per 2 l’operando.
32
Esempio:
MOV
SHL
BL, 07
BL, 1
;BL = 07
;BL = 0E
L’istruzione SAL è del tutto equivalente alla SHL: ha infatti lo stesso
codice operativo. Il DEBUG del DOS non riconosce questa
istruzione.
SHR
Questa istruzione esegue lo slittamento a destra
(logico o aritmetico) dell’operando.
SAR
Da notare come nell’istruzione SAR il bit più significatico si
conserva. La ragione di ciò va ricercata nella possibilità di errore
che si viene a creare nel caso SHR di operandi intesi come numeri
relativi. Si noti infatti che, così come l’istruzione di SHL significava
MOLTIPLICAZIONE per 2 ad ogni spostamento, anche l’istruzione
di SHR rappresenta un’operazione aritmetica, ovvero la DIVISIONE
per 2 ad ogni passaggio. Mentre però la SHL, intesa come
moltiplicazione, non introduce errori nel caso di operandi negativi,
ciò succede alla SHR, intesa come divisione, nel caso di numeri
negativi.
7(15)
0
CF
0
Byte o Word
SHIFT
RIGHT ( Tralsazione Logica a destra )
33
7(15)
0
CF
Byte o Word
SHIFT
ARITMETIC RIGHT
( Tralsazione Aritmetica a destra )
Esempio:
MOV
SHR
BL, FE
BL, 1
; BL = FE = (1111 1110)2 = (-2)10
; BL = 7F = (0111 1111)2 = (127)10
Si intuisce allora l’utilità di una istruzione che conservi il bit di segno la SAR :
MOV
SAR
BL, FE
BL, 1
;BL = FE = (1111 1110)2 = (-2)10
;BL = FF = (1111 1111)2 = (-1)10
OK
I flag vengono alterati, in particolare :
CF :
OF :
OF :
0
1
Copia del bit che “fuoriesce”
msb = [CF]
per traslazioni verso sinistra
msb  [CF]
0
SAR SINGOLA per traslazioni verso destra
MSB di op SHR
N.B.:
Se si utilizza come contatore di spostamenti, invece del valore 1, il Registro
CL, è possibile ottenere la moltiplicazione dell ’ operando per un numero che
sia potenza di 2. Combinando questa tecnica con la istruzione ADD è
possibile eseguire delle operazioni di moltiplicazione per costanti, in modo
molto più efficiente che la MUL.
34
Esempio:
MOV
MOV
SAL
CL, 04
AL, 08
AL, CL
; CL = 04 = (0000 0100)2 = (4) 10
; AL = 08 = (0000 1000)2 = (8) 10
; AL = 80 = (1000 0000)2 = (128) 10
Il risultato presente in AL è pari a 8 * 16. Pensiamo ora di scrivere in una
locazione di memoria un DATO. Sarà possibile moltiplicare tale dato per un
certo numero, attraverso l’implementazione algoritmica della seguente
formula:
DATO = (DATO * 2 i + DATO) * 2 j
I = 0, 1, 2, …
J = 0, 1, 2, …
(2 i + j + 2 j ) Moltiplicatore di dato
Esempio:
Dato = 03 = (0000 0011) 2 = (3) 10
I = 2 ; J = 1 => (2 3 + 2 ) = 10 => DATO * 10
MOV
MOV
AX, DATO
CL, 02
SAL
ADD
SAL
AX, CL
DATO, AX
DATO, 1
; AX = 03 = (0000 0011)2 = (3)10
; Inizializzazione di CL per la
moltiplicazione per 4
; AX = 03 * 4 = (0000 0011)2 = (3)10
; DATO = 03 + 0C = 0F = (0000 1111)2
; DATO = 0F * 2 = 1E = (0001 1110)2
35
ROTATE LEFT
( Rotazione Logica a sinistra )
SINTASSI :
CF
ROL op , Count
7(15)
0
Byte o Word
ROTATE RIGHT
( Rotazione Logica a destra )
SINTASSI :
7(15)
ROR op , Count
0
CF
Byte o Word
L’istruzione ROL esegue la rotazione verso SINISTRA senza
riporto. Il numero delle rotazioni è specificato in COUNT. Analoga
è la funzione della ROR ma con rotazione verso DESTRA
36
ROTATE with CARRY LEFT
( Rotazione Logica a sinistra con Carry )
SINTASSI :
CF
RCL op , Count
7(15)
0
Byte o Word
ROTATE with CARRY RIGHT
( Rotazione Logica a destra )
SINTASSI :
7(15)
ROR op , Count
0
Byte o Word
37
CF
L’istruzione RCL esegue la rotazione verso SINISTRA del dato
coinvolgendo nell’ operazione il Carry. Tale bit, viene considerato
come facente parte dell’ operando . Alla fine della rotazione il bit più
pesante dell’ operando va ad occupare il posto del bit meno
pesante dell’ operando. In modo analogo si comporta l’ istruzione
RCR, con la variante di una rotazione verso destra. Chiaramente il
numero di rotazioni è specificato in COUNT. Le istruzioni RCL e
RCR sono delle rotazioni a 9 o 17 bit, in cui il 9° o il 17° bit è
rappresentato dal carry. Il loro uso è specificatamente legato alle
operazioni di SHIFT su dati le cui dimensioni superano i 16 bit. In
sostanza si sfrutta il fatto che con queste istruzioni ( e solo con
queste) è possibile immettere nell’ operando il contenuto del carry.
Esempi potrebbero essere le operazioni di moltiplicazione o di
divisione.
Esempio : Moltiplicazione di una parola a 32 bit contenuta in
DX:AX
MOV
MOV
SAL
1
RCL
AX , D21E ; Parte Bassa del Dato in AX
DX , 095A ; Parte Alta del Dato in DX
AX , 1
; Prima AX = D21E dopo AX = A43C CF =
DX , 1
; Prima DX =095A dopo DX = 12B5
DX
0000
0101
1010
RCL
CF
0
1001
AX
0000
0000
0000
0000
0
38
0000
0000
SAL
CF
0000
0000
0000
0000
0000
0000
Per quanto riguarda le istruzioni a 2 operandi, esse condizionano le
flags del registro di stato. In particolare i flag CF ed OF restano
azzerati, mentre i restanti risentono del risultato dell’ operazione. Le
istruzioni di questo sottogruppo sono:
AND
Sintassi : AND
OP_DEST
,
OP_SORG
TEST
Sintassi : AND
OP_DEST
,
OP_SORG
OR
Sintassi : AND
OP_DEST
,
OP_SORG
XOR
Sintassi : AND
OP_DEST
,
OP_SORG
Modi di Indirizzamento :
Registro / Memoria  Registro
Registro / Memoria  Registro
39
Queste istruzioni hanno vai campi di impiego. In particolare le
istruzioni di OR ed AND possono essere utilizzate per settare o
resettare dei bit di una parola.
MODIFICA DEI FLAGS
0
Risultato Positivo
1
Risultato Negativo
0
Risultato  0
1
Risultato = 0
SF (Sign Flag)
ZF (Zero Flag)
AF (Auxiliary Flag)
Indeterminato
0 Risultato con numero dispari di “ 1 “
PF (Auxiliary Flag)
1 Risultato con numero pari di “ 1 “
CF (Sign Flag)
OF (Overflow Flag)
0
0
Gli altri flag non vengono modificati .
40
ISTRUZIONI DI
CONTROLLO DELLA
SEQUENZA
In questo blocco rientrano tutte quelle istruzioni che sono associate all’
interruzione della normale sequenza del programma di lavoro. Tali
interruzioni possono configurarsi in modo diverso. Esse, infatti, possono
essere dovute a salti di programma, condizionati o non, a chiamate o
ritorni da subroutine ed infine ad interrupt software. Quindi le istruzioni di
questo gruppo possono raggrupparsi in 4 categorie:
1)
2)
3)
4)
Salti Incondizionati
Salti Condizionati
Chiamata o ritorno da Subroutine
Interrupt Software
SALTI
INCONDIZIONATI : JMP
OPERANDO
INTRASEGMENTO
FORMA DIRETTA
INTERSEGMENTO
OPERANDO : INDIRIZZO
INTRASEGMENTO
FORMA INDIRETTA
INTERSEGMENTO
41
Questa istruzione esegue il salto non condizionato. Si trasferisce infatti, il
controllo ad una certa locazione obiettivo, senza nulla verificare. l’indirizzo
della locazione obiettivo, puo’ essere ottenuto in diversi modi, che comunque
coinvolgono il Registro puntatore IP, in particolare l’indirizzo della locazione
obiettivo e’ fornito dal contenuto di IP a cui viene sommato uno spostamento
dotato di segno. A proposito di quanto appena detto, va aggiunto “ che ciò
e’ vero, ossia e’ quello che il P si aspetta, solo quando si lavora con
i codici esadecimali, perché sia il DEBUG del DOS che tutti gli
assemblatori, utilizzano una diversa convenzione. L’uso degli
assemblatori o del DEBUG del DOS, obbliga ad indicare “b” come
operando, non lo spiazzamento bensì l’indirizzo dell’ offset all’interno
del segmento, ovvero il valore che IP deve assumere.
SALTO DIRETTO INTRASEGMENTO
JMP
JMP
SPIAZZAMENTO A 8 BIT
SPIAZZAMENTO A 16 BIT
SALTO DIRETTO INTERSEGMENTO
JMP
SEGMENT : OFFSET
In questo tipo di Istruzione di salto , si riferimento a valori di IP e di CS
che sono contenuti nell’ istruzione stessa.
ESEMPIO:
JMP 19C0 : 0130
CS = 19C0
HEX
, IP = 0130
HEX
INDIRIZZO FISICO: 19D30HEX
42
SALTO INDIRETTO INTRASEGMENTO
JMP
REGISTRO/ MEMORIA
Registro puo’ essere un qualsiasi Registro a 16 bit, con esclusione di quelli
di segmento, mentre la memoria e’ un riferimento diretto o indiretto alla
memoria:
ESEMPI:
A) JMP [1000] :
B) JMP [BX]
La word all’indirizzo di memoria puntato da BX,
nel segmento dati, rappresenta l’offset , IP = [1000]
: La word all’indirizzo di memoria
nel segmento dati, rappresenta
BX
0200
0200
03
0201
01
IP
0103
0203
0204
INSERIMENTO
DATI
43
puntato da BX,
l’offset, IP = [bx]
SALTI
CONDIZIONATI
I salti condizionati sono utilizzati per generare delle diramazioni dei cicli
in un programma. E’ altresi’ chiaro che essi vanno posti dopo quelle
istruzioni che variano le flag. Queste istruzioni possono dividersi in 3
sezioni:
1) Condizioni per numeri assoluti
2) Condizioni per numeri relativi
dopo una
CMP OP1,OP2
3) Condizioni sui
dopo un ‘ istruzione con
effetto sui flag
flag
La sezione 1 e la 2, sono utilizzate dopo un’ istruzione di comparazione,
mentre la 3 dopo una qualsiasi istruzione che modifica i flag.
SINTASSI:
J condizione , spiazzamento
Spiazzamento:
Condizione:
Valore relativo ad 8 bit ( - 128 ; + 127 ). Tale valore
sara’ sommato al contenuto attuale del IP che
rappresenta l’ indirizzo dell’ istruzione di quella di
salto.
Vedi tabella
44
SALTO DI INTERSEGMENTO
JMP
FAR MEMORIA
L’operando in questo caso e’ solo un riferimento diretto o indiretto alla
memoria. non e’ possibile infatti, disporre di un Registro come riferimento, in
quanto e’ necessario un indirizzo fisico, che non e’ possibile esprimere
attraverso un unico Registro. l’operatore far e’ indispensabile e va
anteposto a “memoria”, per poter distinguere questo tipo di salto da
quello indiretto intrasegmento con riferimento alla memoria, diretto o
indiretto.
ESEMPIO
JMP FAR [SI]: La parola posta all’indirizzo puntato da si, nel segmento
dati, rappresenta l’indirizzo fisico di memoria da caricare
in CS ed IP; IP =[SI] CS=[SI+2]
JMP FAR [SI]
CON SI=0200
SI
0200
PI
0200 3C
0201
01
0202
0203
0204
45
C0
013C
CS
19
19C0
ISTRUZIONI
LOOP
JCXZ
Del gruppo di istruzioni di salto , fanno parte anche:
LOOP spiazzamento
( CX=CX – 1 , SALTA SE CX /= 0 )
JCXZ
(SALTA SE CX = 0 )
spiazzamento
N.B.
Sia la sintassi che i modi di indirizzamento sono simili a quelli dei salti
condizionati , ma in questo caso la condizione non e’ sulle flag , bensi’
sullo stato del Registro interno cx. nessun flag viene modificato da
queste istruzioni. Tramite l’istruzione loop e’ possibile ideare facilmente
un ciclo,
esempio:
RIPETI
:
MOV
CALL
LOOP
CX, n° Cicli
Routine
la routine sara’ ripetuta n volte.
Ripeti
L ‘ istruzione loop presenta alcune varianti:
LOOPE
SPIAZZ.
(CX = CX - 1 SALTA SE CX /=0 E ZF=1 )
LOOP EQUAL
LOOPZ
SPIAZZ.
(CX = CX - 1 SALTA SE CX /=0 E ZF=1 )
LOOP ZERO
LOOPNE SPIAZZ.
(CX = CX -1 SALTA SE CX /=0 E ZF=1 )
LOOP NOT EQUAL
LOOPNZ
SPIAZZ.
(CX = CX -1 SALTA SE CX /=0 E ZF=1) LOOP NOT ZERO
46
CALL
RET
Queste istruzioni costituiscono il mezzo attraverso il quale il P 8086
implementa i sottoprogrammi.
SINTASSI: CALL OFFSET
quando il P incontra una istruzione di CALL, per prima cosa
decrementa il Registro SP, salva il Registro IP , quindi caricalo stesso
IP con il valore fornito dall’operando. il segmento di stack e’ puntato dal
Registro SS (stack segment), mentre l’offset all’interno del segmento e’
dato da SP (stack pointer). In base alla modalita’ di indirizzamento, si
possono avere 4 diversi tipi di chiamata, in particolare :
 CHIAMATA DIRETTA INTRASEGMENTO
 CHIAMATA DIRETTA INTERSEGMENTO
 CHIAMATA INDIRETTA INTRASEGMENTO
 CHIAMATA INDIRETTA INTERSEGMENTO
47
1)
Esempio di chiamata diretta intrasegmento
PRIMA
IP : 0207
CS : 0204
5
: CALL 0300
DOPO
IP : 0300
CALL
00
MEMORIA BASSA
03
STACK
6
07
SS: SP-2
7
02
SS: SP-2
8
.
.
.
STACK
MEMORIA ALTA
CS : 0300
Subroutine
48
2) Esempio di chiamata diretta intersegmento :
CS
13D0 : 0204
CALL
CALL 47B5 : 0300
IP
STACK
47B5 : 0300
09
00
DOPO
02
03
D0
B5
13
47
CS
IP
13D0 : 0209
STACK
PRIMA
47B5 : 0300
Subroutine
SINTASSI : CALL SEGMENT : OFFSET
SP = SP – 2 , CS  [SP]
SP = SP – 2 , IP  [SP]
CS = SEGMENT , IP = OFFSET
49
3) CHIAMATA INDIRETTA INTERSEGMENTO
SINTASSI:
CALL FAR REG / MEMORIA
ESEMPIO:
CALL FAR
[DI]
SP = SP – 2 , CS
SP = SP – 2 , IP
CS = [DI +1] , IP =
;
;
;
[SP]
[SP]
[DI]
per quanto riguarda l’istruzione di RET, esistono due forme
diverse di rientro, in particolare:
1) RITORNO INTRASEGMENTO
R ET
2) RITORNO INTERSEGMENTO
RETF
RET
;
[SP]
IP ,
SP = SP + 2
RETF
;
[SP]
CS ,
SP = SP + 2 ,
50
[SP]
IP, SP =SP+2
INT n
INTERRUPT
SINTASSI :
INT n
SOFTWARE
n numero assoluto ad 8 Bit
Queste istruzioni sono impropriamente chiamate “interruzioni“, perché in
realtà non lo sono. Una interruzione e’ infatti, qualcosa di asincrono al
programma, che interrompe l’ attuale svolgimento delle operazioni, per
eseguire una particolare procedura. tale compito e’ svolto dalle
“interruzioni hardware“, da cui derivano, per meccanismo di
funzionamento, le interruzioni software. Le interruzioni int sono normali
istruzioni, poste all’ interno del programma in corso, quindi in tale
accezione non possono essere considerate delle interruzioni vere e
proprie.
INT
CALL
Il meccanismo di funzionamento delle INT e’ basato su una tabella di
1024 byte locata all’ indirizzo
0000 : 0000
tale tabella contiene 256 vettori da 4 byte che rappresentano altrettanti
indirizzi fisici a 32 bit SEG: OFFSET
Quando si incontra una istruzione di INT, il processore esegue la
routine posta all’indirizzo specificato nel vettore memorizzato nella
locazione 4 * N in poi in sostanza si effettua un salto indiretto in effetti
oltre al
“salto” il processore effettua qualcosa di
piu’, ovvero il
salvataggio dello “stato macchina”.
51
Salvataggio stato macchina
REGISTRO DELLE FLAG
REGISTRO CS
REGISTRO IP
AZZERAMENTO FLAG IF
AZZERAMENTO FLAG TF
STACK
CS
IP
IP
CS
FH
TABELLA DEI PUNTATORI
DELLE ROUTINE DI
FL
INT
IP
INT 00
0000:0000
INT 02
0000:0004
INT 03
0000:0008
INT 21
0000:0084
INT FF
0000:03FC
IP
IP
STACK
OFFSET L
SP = SP - 2 ; F  [ SP ]
OFFSET H
0  TF ; 0  IF
SEGMENT L
SP = SP - 2 ; CS  [ SP ]
SEGMENT H
SP = SP - 2 ; IP  [ SP ]
SP = SP - 2 ; F  [ SP ]
[ n * 4 ]  IP ; [ ( n* 4 ) +2 ]  CS
52
In definitiva si puo’ dire che questo tipo istruzione e’ simile ad una
CALL o ad un salto indiretto che pero’ sfrutta il meccanismo degli
interrupt di tipo hardware. La domanda che ora ci si può porre e’ la
seguente: perché visualizzare le INT software quando potremmo
utilizzare le CALL? la risposta e’ data dalla possibilità di trasportare
il codice prodotto da una macchina all’altra. Si consideri infatti che
anche piccole modifiche al sistema operativo o al BIOS, portano ad
alterare molti degli indirizzi di memoria e quindi dover cambiare
all’interno del sistema operativo stesso, molti degli operandi delle
CALL di sistema. Tramite l ’ uso degli INT, basterà modificare i vettori
posti all’interno della tabella delle interruzioni, lasciando inalterato il
programma. Cosi’ come per le CALL, anche per le INT e’ previsto il
rientro al programma principale:
I RET ;
[SP]
IP; SP = SP+2 ,
[SP]
FLAG_REG.
[SP]
CS , SP = SP+2
SP = SP+2
Come si puo’ notare, l’istruzione di RET, riporta il sistema nella
condizione precedente all’istruzione di INT.

INT O ( INTERRUPT ON OVERFLOW )
INT 4
OF = 1
INT3  INT n
( Normalmente utilizzata dai DEBUGGER )
n=3
Queste ultime due istruzioni sono codificate con un solo Byte
53
ISTRUZIONI DI
CONTROLLO
PROCESSORE
Di questa
categoria di istruzioni, alcune permettono di alterare il
contenuto del Registro delle flag, altre sono normalmente utilizzate dai
programmatori di sistema.
ISTRUZIONI CHE AGISCONO SUL CARRY FLAG (CF).
CLC ; CL EAR CARRY
CMC ; COMPLEMENT CARRY
STC ; S E T CARRY
ISTRUZIONI CHE AGISCONO SULLA DIRECTION FLAG (DF).
CLD
;
CLEAR DIRECTION
ISTRUZIONI CHE AGISCONO SUL FLAG INTERRUPT (IF).
CLI
STI
;
;
CLEAR INTERRUPT ENABLE
S E T INTERRUPT ENABLE
N.B
IF = 0
IF = 1
INTERRUZIONI
INTERRUZIONI
ESTERNE MASCHERABILI DISABILITATE
ESTERNE MASCHERABILI ABILITATE.
54
ISTRUZIONI SPECIALI
HLT
;
HALT
(FERMATA)
Quando viene eseguita questa istruzione, il processore si porta in uno stato
di inattività, dal quale non esce se non dopo una istruzione di RESET o di
una richiesta di interruzione.
wait ;
(attesa)
quando viene eseguita questa istruzione, il processore si porta in uno stato
di attesa, dal quale uscirà’ solo dopo una richiesta di interruzione esterna o
in seguito ad una istruzione di RESET o in base allo stato logico di un pin
della CPU, ovvero il pin di test. Se tale pin e’ allo stato logico zero si
procede nell ‘esecuzione del programma, altrimenti si resta in attesa che
tale stato logico si realizzi. Tale istruzione e’ normalmente utilizzata con
dispositivi esterni al fine di realizzare la sincronizzazione con la CPU, ad
esempio, coprocessori matematici, memorie ……… .
ESC ; ESCAPE
TO EXTERNAL DEVICE
SINTASSI : ESC
OPERANDO
Tale istruzione serve a generare istruzioni per il coprocessore matematico
8087. Durante un’istruzione successiva in memoria e risincronizza le
operazioni tramite l’istruzione wait.
LOCK ; BUS LOCK (BLOCCA)
Tale istruzione e’ posta prima di un‘ istruzione che non deve assolutamente
essere interrotta, ad esempio da una richiesta di rilascio del controllo dei
BUS.
55
ISTRUZIONI
DI I / O
La gestione delle periferiche di I/O e’ realizzata normalmente tramite
2 istruzioni specifiche, ciò’ non toglie pero’ possibilità’ di utilizzare le
istruzioni per l ’accesso dei dati in memoria (MOV).
GESTIONE
PERIFERICHE
I/O
I / O PORT
MAPPED
I / O MEMORY
MAPPED
Con questa modalità’ di gestione delle
periferiche, una parte di indirizzi sono associati
ad altrettante periferiche di i/o. Le istruzioni per
l’indirizzamento sono pertanto quelle relative
all’accesso dei dati in memoria.
I / O MEMORY MAPPED
:
I / O PORT MAPPED
: Questa modalità’ e’ quella normalmente
utilizzata dall’8086 e fa uso di 2 specifiche
istruzioni: IN ed OUT.
IN
:
OUT
SINTASSI :
:
IN
ACCUMULATORE , PORTA
SINTASSI : OUT
PORTA , ACCUMULATARE
56
I dati che si potranno spostare sono di lunghezza pari ad 1 byte o ad
1 word. Nel caso di una in essi occuperanno al o AX rispettivamente,
nel caso di una OUT il contenuto di al o AX rispettivamente e’ memorizzato
nella porta specificata. la porta selezionata può essere nel range 0  65535.
Due sono le diverse modalità’ di indirizzamento.
A) DIRETTO , PER PORTE TRA 0 ED FF
B) INDIRETTO , TRAMITE REGISTRO DX PER QUALSIASI INDIRIZZO.
ESEMPI :
IN AL , 60
; PORT [60]
OUT 43 , AL
; AL
IN AL , DX
; PORT [DX]
OUT DX , AL
; AL
AL
INDIRIZZAMENTO DIRETTO
PORT [43]
AL
INDIRIZZAMENTO INDIRETTO
PORT [DX]
N.B
Lo spazio di indirizzamento realmente utilizzato nei PC non e’ di 64 K
byte (0 / FFFF )Hex bensì da ( 0 / 3FF ) Hex .
57
IL LINGUAGGIO ASSEMBLY
Il linguaggio assembly e’ un linguaggio di basso livello mediante il
quale e’ possibile gestire in forma diretta tutte le risorse del P. Si noti
che la maggior parte delle istruzioni in linguaggio assembly coincidono con
le istruzioni mnemoniche del set di istruzioni del P. La differenza, tra un
programma scritto in linguaggio mnemonico ed uno scritto in linguaggio
assembly , sta nella “gestione della memoria”, nei “riferimenti dei salti” e
nell’ “interfaccia con il sistema operativo”. Infatti mentre in un programma
scritto esclusivamente in linguaggio mnemonico, tutto ciò’ che riguarda:
salti, locazioni di memoria, etc. viene espresso in forma numerica, in
linguaggio assembly si fa uso delle cosiddette “label” o “etichette”. La
procedura con la quale si realizza un programma scritto in assembly
e’ abbastanza simile a quella usata per i linguaggi ad alto livello.
I programmi utilizzati allo scopo sono detti “assemblatori”:
MASM ;
TASM
Le varie fasi che porteranno alla realizzazione del programma, fanno uso
di altrettanti programmi ovvero :
EDITOR
ASSEMBLER
LINKER
DEBUGGER
58
vediamoli singolarmente :
EDITOR
L’editor e’ il programma che ci permette di scrivere il cosiddetto “programma
software”, ad esso sarà associato un file con estensione .asm, ovvero
assembly.
ASSEMBLER
Tramite l’assemblatore, si realizza la fase appena successiva a quella
di
editor.
Fornendo al
programma
il file con estensione .asm,
l’assemblatore produrra’ un “file oggetto” con estensione .obj. Il file
oggetto conterrà’ la traduzione di tutte le estensioni in linguaggio
macchina, ma che e’ ancora incompleto riguardo l’interfaccia con il s.o.
tale fase in genere produce alcuni altri file utili per la documentazione
ed il DEBUG. Un file di tale genere e’ quello con estensione .lst (listing) .
LINKER
Il programma che permette di convertire il file oggetto in file eseguibile
dal dos e’ il linker. Il file che esso produrrà’ sara’ ad estensione .exe.
Tale file conterra’ tutte le istruzioni in linguaggio macchina ed in piu’
una testata di 512 byte detta header utilizzata dal S.O. per caricare
il file in memoria.
DEBUGGER
Il debugger e’ un programma che permette l’individuazione degli
eventuali errori presenti nel programma stesso. Lettereralmente significa
spulciare ovvero togliere elementi fastidiosi. Un programma di tal genere
permette di eseguire una serie di operazioni, quali:
1) OPERAZIONE DI DUMP
Tramite questa operazione il codice oggetto assemblato viene caricato in
memoria e visualizzato in tutte le forme possibili decimale, hex, ascii.
2) OPERAZIONE DI DISASSEMBLAGGIO
Tramite tale operazione e’ possibile avere in lista un codice mnemonico
dei comandi presenti in una versione del programma.
59
3) OPERAZIONE EDIT
Tramite tale operazione e’ possibile aggiungere o modificare codici
macchina nella prima versione del programma.
4) REGISTER DUMP E STACK DUMP
Con questa operazione e’ possibile visualizzare e modificare i contenuti
di tutti i Registri interni della cpu e in conteporanea una piccola porzione
di memoria attorno al valore puntato dallo stack pointer.
5) OPERAZIONE TRACE (SINGLE STEP)
Con tale operazione sara’ possibile eseguire un’ istruzione alla volta,
visualizzando i cambiamenti apportati ai Registri interni della CPU e
l’istruzione stessa.
6) BREAKPOINT
Tale operazione ci permette di aggiungere dei punti di blocco forzato
nell’esecuzione del programma, al fine di verificare lo stato della CPU in
particolari punti del programma. Questi blocchi si chiamano breakpoint.
60
SEQUENZA DELLE OPERAZIONI NECESSARIE PER LO SVILUPPO
DI UN PROGRAMMA ASSEMBLY
SVILUPPO DI UN
PROGRAMMA
IN ASSEMBLY
EDIT
 ASM
CORREZIONE DEGLI
ERRORI TRAMITE LE
INFORMAZIONI
DI TASM
( o MASM )
…  LST
ASSEMBLER
…  OBJ
SI
ERRORI
?
NO
CORREZIONE DEGLI
ERRORI TRAMITE LE
INFORMAZIONI DI
DEBUG
LINKER
…  EXE
ESECUZIONE
OK ?
NO
CAUSA
INDIVIDUATA
?
SI
SI
NO
FINE
DEBUG
61
LA STRUTTURA DI UN PROGRAMMA ASSEMBLY
I programmi scritti in linguaggio assembly
essenzialmente dai seguenti segmenti:
8086
sono
costituiti
1) SEGMENTO DI CODICE
2) SEGMENTO DI DATI
3) SEGMENTO DI STACK
si noti che un segmento di programma, e’ un insieme di istruzioni e/o
dati, i cui indirizzi sono tutti relativi allo stesso Registro di segmento.
DIRETTIVE ASSEMBLY
Le direttive assembly sono delle parole chiave mediante le quali
l’assemblatore svolge particolari compiti. Si ricorda infatti che una notevole
caratteristica dei programmi scritti in assembly, che non e’ disponibile in
assembler (scrittura in linguaggio mnemonico), e’ l’utilizzo delle label
allora sarà necessario specificare all’assemblatore che cosa fare quando
si incontrano questo tipo di comandi. Cioè l’assemblatore dovrà poter
interpretare non solo i formati mnemonici delle istruzioni tipiche della
CPU, ma anche dei comandi aggiuntivi che hanno lo scopo di informarlo
su come deve comportarsi ed interpretare le altre istruzioni e che non
devono generare codice macchina. Tali comandi, come già’ detto prendono
il nome di pseudo istruzioni o direttive e vanno inserite nel campo del
codice operativo, così come ogni istruzione.
DIRETTIVA SEGMENT
DIRETTIVA ASSUME
DIRETTIVA END
LA DICHIARAZIONE DELLE ETICHETTE (LABEL)
Una label e’ un nome che rappresenta l’ indirizzo di un’istruzione e può
essere utilizzata in un salto, una chiamata a sottoprogramma (CALL),
oppure in una istruzione di LOOP.
DIRETTIVA LABEL
62
LA DICHIARAZIONE DEI DATI
DIRETTIVA DB ( DEFINE BYTE )
DIRETTIVA DW (DEFINE WORLD)
DIRETTIVA DD
( DEFINE DOUBLE-WORLD )
DICHIARAZIONE DEI SIMBOLI
I simboli dei nomi descrittivi, che rappresentano un numero, un testo,
un’istruzione o un indirizzo. I simboli permettono di rendere più’ leggibile
un programma ed e’ pertanto opportuno utilizzarli il più frequentemente
possibile.
DIRETTIVA = ( SEGNO DI UGUAGLIANZA )
DIRETTIVA EQU (EQUATE )
LE BASI DEI NUMERI
I numeri interi possono essere espressi sia in forma decimale che
esadecimale, binaria ed ottale. Il numero deve essere seguito dalla lettera
che identifica la base:
B
Q
D
H
o
O
BINARIO
OTTALE
DECIMALE
ESADECIMALE
Normalmente i numeri sono espressi in forma decimale a meno
diversa indicazione, a tal scopo si usa una particolare direttiva.
di
DIRETTIVA RADIX
I COMMENTI
Come e’ noto ciò che nel file sorgente e’ scritto tra “ “, e’ considerato
come commento, quindi ignorato dall’ assemblatore.
E’ possibile un’alternativa a ciò, quando il commento lo si vuole su più’
linee:
DIRETTIVA COMMENT
63
SCRIVERE UN PROGRAMMA IN ASSEMBLER 8086
Per poter realizzare un programma in assembler 8086 e' necessario scrivere un file con estensione
*.asm con le caratteristiche minime specificate nei listati che seguono:
programma 1
; Programma per lo scambio di due valori a 16 bit
Dati SEGMENT
; definizione dati usati nel programma
Primo DW 0102h;
Secondo DW 0304h;
Dati ENDS
Sistema SEGMENT STACK
DW 100 DUP (?)
Top LABEL WORD
Sistema ENDS
; definiamo uno stack di 100 bytes
Codice SEGMENT
; Definizione dei segmenti
; ASSUME serve a definire a quale puntatore potrà essere assegnato la struttura
ASSUME CS: Codice, SS:Sistema, DS:Dati, ES:Dati
Inizio:
;Inizializzazione dei registri di segmento
MOV AX,sistema
MOV SS,AX
LEA AX,Top
MOV SP,AX
MOV AX,Dati
MOV DS,AX
MOV ES,AX
; calcolo del prodotto della parte bassa degli operandi
MOV AX,WORD PTR Primo
MOV BX,WORD PTR Secondo
MOV WORD PTR Primo,BX
MOV WORD PTR Secondo,AX
; ritorno al sistema operativo
MOV AL,00H
MOV AH,4CH
INT 21H
Codice ENDS
END
; ENDS fine segmento
inizio ; fine programma con definizione inizio, in IP verra' caricato l' indirizzo
; corrispondente a inizio
64
programma 2
;
; programma che stampa su video una stringa con int 21h
;
stack segment para stack 'stack' ; definiamo uno stack di 48 bytes che il sistema
db 48 dup ('stack')
; posizionerà dove meglio crede
stack ends
;
dati segment para 'dati'
; definizione di una stringa di caratteri ashii con il '$'
msg db
' si fa presto a dire ….','$'
dati ends
;
codice segment para 'codice'
assume ds:dati
; ASSUME serve a definire a quale puntatore
assume ss:stack
; potrà essere assegnato la struttura dati
assume cs:codice
;
org 0100h
; definiamo l' indirizzo d' inizio della procedura che segue
;
main proc near
; definiamo il tipo di procedura ( near-far )
;
push ds
; salviamo il puntatore alla zona dati
;
mov ax,dati
; posizioniamo il puntatore alla zona dati in cor rispondenza
mov ds,ax
; della struttura dati 'dati'
;
mov es,ax
; operazione inutile per il programma attuale
;
lea dx,msg
; assegno a dx l' indirizzo della stringa
;
mov ax,0900h ; definisco parametri in ax per poter stampare la stringa con int 21 ah = 09
int 21h
; richiamo l' int 21 - stampo la stringa
;
pop ds
; ripristino il puntatore alla zona dati iniziale
;
mov ax,4c00h ; definisco parametri in ax per poter interrompere il programma e ridare il
; controllo al sistema con l' int 21 ah = 4c
int 21h
; richiamo l' int 21 - fine programma ritorno al sistema operativo
;
main endp
; ENDP fine procedura main
;
codice ends
; ENDS fine segmento
;
end main
; fine programma con definizione inizio, in IP verra' caricato l' indirizzo
; corrispondente al main
65
OSSERVAZIONI
1 - i commenti devono essere preceduti dal ;
2 - le strutture dati vengono definiti tra le direttive SEGMENT ed ENDS
3 - le procedure vengono definite tra le direttive PROC ed ENDP
4 - ASSUME definisce sostanzialmente il tipo di struttura ma non assegna nessun valore numerico
ai puntatori di segmento
5 - ORG serve a definire gli indirizzi d' inizio di programma e subroutine
6 - PROC serve a definire le dimensioni dei programmi
7 - l' END finale fissa l’IP
Per assemblare il programma il comando é TASM nome programma senza estensione. Se si vuole
il listato il comando é tasm nome progr. /l.
Viene creato un file *.OBJ che deve essere linkato con il comando TLINK nome programma senza
estensione. Viene creato un file *.EXE che può essere direttamente eseguito oppure se ne può
realizzare il debug in due maniere differenti:
1 - con il comando DEBUG *.EXE e si entra nel debug classico del PC
2 - con il comando TD *.EXE e si entra in ambiente TURBO DEBUGGER
E’ preferibile l'ambiente TURBO DEBUGGER che é organizzato a finestre e permette di
visualizzare contemporaneamente tutte le caratteristiche (programma, memoria, registri) ed
evidenzia le modifiche attuate dal programma in esecuzione. Inoltre possiede un ottimo HELP . I
comandi sono quelli standard del debug, ma esiste la possibilità (con l' uso del mouse) di una più
facile selezione.
66
TURBO ASSEMBLER
Version 2.01 Copyright (c) 1988, 1990 Borland International
Sintassi: TASM [options] source [,object] [,listing] [,xref]
/a,/s
Alphabetic or Source-code segment ordering
/c
Generate cross-reference in listing
/dSYM[=VAL]
Define symbol SYM = 0, or = value VAL
/e,/r
Emulated or Real floating-point instructions
/h,/?
Display this help screen
/iPATH
Search PATH for include files
/jCMD
Jam in an assembler directive CMD (eg. /jIDEAL)
/kh#
Hash table capacity # symbols
/l,/la
Generate listing: l=normal listing, la=expanded listing
/ml,/mx,/mu
Case sensitivity on symbols: ml=all, mx=globals, mu=none
/mv#
Set maximum valid length for symbols
/m#
Allow # multiple passes to resolve forward references
/n
Suppress symbol tables in listing
/o,/op
Generate overlay object code, Phar Lap-style 32-bit fixups
/p
Check for code segment overrides in protected mode
/q
Suppress OBJ records not needed for linking
/t
Suppress messages if successful assembly
/w0,/w1,/w2
Set warning level: w0=none, w1=w2=warnings on
/w-xxx,/w+xxx
Disable (-) or enable (+) warning xxx
/x
Include false conditionals in listing
/z
Display source line with error message
/zi,/zd
Debug info: zi=full, zd=line numbers only
TURBO LINK
Version 3.01 Copyright (c) 1987, 1990 Borland International
Sintassi: TLINK objfiles, exefile, mapfile, libfiles
/m
map file with publics
/x
no map file at all
/i
initialize all segments
/l
include source line numbers
/s
detailed map of segments
/n
no default libraries
/d
warn if duplicate symbols in libraries
/c
lower case significant in symbols
/3
enable 32-bit processing
/v
include full symbolic debug information
/e
ignore Extended Dictionary
/t
create COM file
/o
overlay switch
/ye
expanded memory swapping
/yx
extended memory swapping
67
TURBO DEBUGGER
Version 2.01 Copyright (c) 1988, 1990 Borland International
Sintassi: TD [options] [program [arguments]] -x- = turn option x off
-c<file>
-do,-dp,-ds
-h,-?
-i
-k
-l
-m<#>
-p
-r
-rp<#>
-rs<#>
-sc
-sd<dir>
-sm<#>
-vg
-vn
-vp
-y<#>
-ye<#>
Use configuration file <file>
Screen updating: do=Other display, dp=Page flip, ds=Screen swap
Display this help screen
Allow process id switching
Allow keystroke recording
Assembler startup
Set heap size to # kbytes
Use mouse
Use remote debugging
Set COM # port for remote link
Remote link speed: 1=slowest, 2=slow, 3=medium, 4=fast
No case checking on symbols
Source file directory <dir>
Set spare symbol memory to # Kbytes (max 256Kb)
Complete graphics screen save
43/50 line display not allowed
Enable EGA/VGA palette save
Set overlay area size in Kb
Set EMS overlay area size to # 16Kb pages
68