|
Tutorial
|
Dettaglio Istruzioni |
|
|
 |
Istruzioni
della Cpu 80x86 |
SCHEDA n° 07 [I/
026
di 198] |
 |
|
CMPS - Confronta
i dati di 2 aree di memoria modificando le flags |
|
 | Questa istruzione
analizza il contenuto di 2 locazioni di memoria e modifica le
flag in funzione del risultato. |
 | In pratica simula
la sottrazione del sorgente dalla
destinazione
senza però alterare
il contenuto della destinazione (come farebbe invece l'effettiva
sottrazione, SUB); questo basta per
modificare le flag coinvolte dal risultato e a favorire gli eventuali salti
condizionati (Jxx) conseguenti. |
 | Per funzionare correttamente è necessario
specificare entrambi gli operandi, di solito con l'etichetta
del primo dei dati di ciascuna area; in questo modo
l'assemblatore è in grado di stabilire la dimensione
del dato da assumere e collocare in memoria; se gli operandi non
vengono dichiarati l'assemblatore segnala errore. |
 | Si tratta di una istruzione piuttosto
efficiente, nata per confrontare il contenuto di 2
aree di memoria, per esempio 2
stringhe di caratteri. |
 | Nonostante la necessità di dichiarare
l'operando sorgente (solo per motivi di corretta compilazione) per default
utilizza comunque le coppie di registri
DS:SI per puntare in minuendo
(destinazione) e ES:DI per puntare il
sottraendo (sorgente), per cui l'uso di questa istruzione ha senso solo se, in
precedenza, i registri SI e
DI sono stati inizializzati con le etichette usate come operandi,
per esempio anticipando la
CMPS
Depo01,ES:Depo02
con LEA SI,Depo01
e LEA DI,Depo02,
vedi esempio successivo). |
 | In questo è evidente una incongruenza con le
convenzioni Intel, per cui il registro indice
Sorgente per eccellenza è SI (Source
Index) e quello Destinazione è DI
(Destination Index): prendiamone
atto senza farci intimorire.... |
 | L'istruzione è particolarmente utile per
confrontare 2 stringhe o tabelle; per
trovare un determinato byte o carattere in una
stringa o in una tabella
è disponibile la SCAS che si basa sul
medesimo principio di funzionamento. |
 | Le sue caratteristiche sono riassunte nella
seguente tabella (leggi le
istruzioni
): |
CMPS
Destinazione, Sorgente
CMPS
DS:[SI], ES:[DI] |
Cambia le Flag simulando { DS:[SI]
- ES:[DI] } |
| |
|
Esempio di Applicazione |
Cicli di Clock |
Mem
Acces |
N°
Bytes |
Flag influenzate |
|
Mnemonico |
Operandi |
86 |
268 |
386 |
486 |
O |
D |
I |
T |
S |
Z |
A |
P |
C |
|
CMPS
|
Byte Ptr[SI],[DI]
|
22 |
8 |
10 |
8 |
2 |
1 |
# |
|
|
|
# |
# |
# |
# |
# |
|
CMPS
|
Word Ptr[SI],[DI]
|
30 |
8 |
10 |
8 |
2 |
1 |
# |
|
|
|
# |
# |
# |
# |
# |
 | La tabella evidenzia la tipologia degli
operandi: sono entrambi riferimenti a memoria e la cosa è decisamente
inconsueta; ciò è dovuto al suo particolare modo di funzionare, che va al di
là di un semplice confronto. Per questo sottolineiamo la sua capacità
gestionale:
 | Il dato prelevato dalle 2 locazioni di
memoria ha la dimensione di un byte,
di una word o
di una doubleword (ma solo con
80386/486,
nel qual caso i registri indice coinvolti sono ovviamente
ESI e EDI). |
 | il segmento
dell'area Sorgente (usata per puntare il sottraendo) è sempre
ES. |
 | il segmento
dell'area Destinazione (usata per puntare il minuendo) è per
default, DS, ma può essere forzata a
beneficio di un altro registro di segmento. |
 | dopo aver modificato le flag in funzione del
confronto aggiorna il valore dei registri di offset
(SI,DI
o ESI,EDI),
in funzione del valore della flag di direzione DF
(che va quindi
predisposta con certezza
prima di iniziare il confronto):
 | se DF=0
(direzione in avanti) ad entrambi i puntatori viene sommato 1 (cioè sono
incrementati, se l'operando è un byte),
2 (se è una
word) o 4 (se ha dimensione
doubleword). |
 | se DF=1
(direzione indietro) ad entrambi i puntatori viene sottratto 1 (cioè sono
decrementati, se l'operando è un byte),
2 (se è una
word) o 4 (se ha dimensione
doubleword). |
|
 | la presenza dei 2
puntatori operandi è richiesta dalla
sintassi per consentire all'assemblatore di capire la
dimensione dei dati da trattare; essi devono dunque essere
dichiarati con la specifica della dimensione dei dati a cui fanno
riferimento (Byte o
Word o Dword Ptr).
|
 | l'assemblatore compila comunque questa
istruzione con lo stesso codice operativo con cui tratta le istruzioni da
essa derivate, tutte prive di operando, cioè CMPSB,
se i dati manipolati sono bytes, CMPSW
se sono word, o CMPSD se doubleword.
|
 | in tutti i casi non va dimenticato che le
istruzioni di confronto stringhe
usano per default i puntatori
DS:SI e ES:DI,
per cui è assolutamente necessario inizializzarli (insieme alla flag
DF) prima di utilizzarle. |
|
 | Questa potente istruzione esegue con un solo
codice operativo il compito di ben 4 istruzioni (anche se a rigor di
logica dovremmo mettere in conto anche il salvataggio e il recupero delle flag,
dato che INC influisce su di loro), cioè
equivale all'esecuzione del seguente codice: |
MOV AL,DS:[SI]
CMP AL,ES:[DI]
PUSHF
INC SI
INC DI
POPF |
 | La figura seguente mostra alcuni modi
alternativi di scrivere questa istruzione: |
|
Addr |
|
Codifica Masm |
|
Istruzione |
|
0100
0132 |
|
0032 [.. 00..]
0032 [.. 00..] |
|
Depo01 DB 50 DUP (00H)
Depo02 DB 50 DUP (00H) |
|
---- |
|
---------------- |
|
------- |
---------------------- |
0164
0165
0166
0167
0168
0169
016B
016C
016E
0170
0172
0174
0176
0178
017A
017C |
|
A6
A6
A6
A7
A6
F3 A6
A6
2E A6
36 A6
26 A6
2E A6
36 A6
26 A6
2E A6
36 A6
26 A6 |
|
|
CMPS
[Depo01],ES:[Depo02]
CMPS Byte Ptr [SI],[DI]
CMPS Byte Ptr DS:[SI],ES:[DI]
CMPS Word Ptr DS:[SI],Word Ptr ES:[DI]
CMPS Depo01,ES:Depo02
CMPS Depo01,ES:Depo02
CMPS DS:Depo01,ES:Depo02
CMPS CS:Depo01,ES:Depo02
CMPS SS:Depo01,ES:Depo02
CMPS ES:Depo01,ES:Depo02
CMPS CS:[SI],ES:Depo02
CMPS SS:[SI],ES:Depo02
CMPS ES:[SI],ES:Depo02
CMPS CS:[DI],ES:Depo02
CMPS SS:[DI],ES:Depo02
CMPS ES:[DI],ES:Depo02 |
|
 | E' interessante osservare che, comunque sia scritta,
al netto dell'eventuale byte di
override, viene sempre codificata con il
byte A6 (se tratta
bytes) o A7 (se tratta
word). |
 | Prima di concludere è opportuno sottolineare che questa
istruzione può fruire dell'operatore di autoripetizione
REPE o REPNE: anteponendolo al
suo mnemonico il processo di confronto viene ripetuto automaticamente
CX volte su tutta l'area sotto test, a meno che non venga trovata
una coppia di valori uguali (E) o diversi (NE); per il corretto uso dei questo
prefisso è dunque necessario caricare preventivamente
CX con il numero di confronti da eseguire. |
 | Data l'utilità di questa tecnica viene proposto un
esercizio d'esempio: |
|
Addr |
|
Codifica Masm |
|
Istruzione |
|
0100
0132
-----
0164
0165
0168
016C
0170
0172
0176
0177
0179
017A
017B |
|
0032 [ ?? ]
0032 [ ?? ]
-----------
FC
B9 0032
8D 36 0100
8D 3E 0132
F3 A6
0F 85 0179
90
EB 02
4E
4F
90 |
|
Depo01
Depo02
----------------
;---------------
tutte_uguali:
;---------------
trovata_diversa:
continua: |
DB 50 DUP (?)
DB 50 DUP
(?)
-------------------------------
CLD
MOV CX,50
LEA SI,Depo01
LEA DI,Depo02
REPE CMPS Depo01,ES:Depo02
JNE
trovata_diversa
;---------------------------
;
servizio coppie uguali
NOP
JMP SHORT
continua
;------------------------------
DEC SI
DEC
DI
; servizio prima coppia diversa
;------------------------------
NOP |
|
|
|
|
|
 | L'analisi del codice suggerisce queste considerazioni:
 | prendiamo nota della tecnica con cui viene riservata memoria per le 2
aree da confrontare, con la pseudoistruzione
Dup. |
 | notiamo la presenza dell'istruzione CLD,
per imporre un'analisi in avanti. |
 | per inizializzare gli offset
dei 2 puntatori si è fatto uso l'uso dell'istruzione LEA. |
 | i segment si ritengono quelli di default, DS e
ES; notare la presenza dell'override
ES: nella sintassi dell'istruzione
di CMPS: se non si mette l'assemblatore
s'arrabia, credendo sia DS anche
per Depo02. |
 | il contatore CX è stato caricato con la dimensione di
entrambe le aree e il prefisso REPE provvederà a
ripetere automaticamente il confronto se i 2 dati assunti dalla coppia
di locazioni sono uguali tra loro, fino all'esaurimento di tutti gli
elementi. |
 | se le coppie sono tutte uguali
il processo ha termine regolarmente e, essendo E
la condizione d'uscita, l'istruzione JNE
non verrà eseguita e il programma
proseguirà subito sotto, nella zona di programma indicata
dall'etichetta tutte_uguali. |
 | se viene rilevata una coppia
diversa il processo verrà
immediatamente interrotto prima della fine e, essendo ora NE
la condizione d'uscita, l'istruzione JNE
verrà eseguita e il programma
proseguirà più in basso, nella zona di programma indicata
dall'etichetta trovata_diversa.: le
prime istruzioni da eseguire sono, in questo caso, il decremento dei
puntatori DI e SI,
così da favorire la localizzazione dei dati trovati diversi. |
|
©
2001-2010 - Studio Tecnico
ing. Giorgio OBER
Tutti i diritti sono riservati
|