MOVS
SCAS
CMPS
LODS
STOS
INS
OUTS
REPxx
Queste instruzioni lavorano più o meno tutte nello stesso modo, secondo la
seguente procedura:
1.Assicuratevi che il Flag di Direzione sia a posto:
se è 0 la stringa viene processata dal basso verso l'alto
se è 1 la stringa viene processata dall'alto verso il basso
(dove con alto e basso intendo le posizioni di memoria)
Le istruzioni per azzerare e settare il DF sono CLD e STD rispettivamente.
2.Caricate il numero di iterazioni nel registro CX.
3.Caricate l'indirizzo iniziale della stringa sorgente in DS:SI e quello
della stringa destinazione in ES:DI
4.Usate le istruzioni di ripetizione al posto giusto
(guardate la tabella seguente)
5.Mettete l'istruzione appropriata come operando dell'istruzione di
ripetizione
nota: preciso che "basso" indica le posizioni più basse di memoria e "alto" quelle
con indirizzi maggiori.
Vi riporto in una tabella le istruzioni con i prefissi che usano e su che tipo di operandi lavorano.
Istruzione Prefisso di rip. Sorg/Dest Registri ------------------------------------------------------------------------- MOVS REP Entrambi DS:SI,ES:DI SCAS REPE/REPNE Destinazione ES:DI CMPS REPE/REPNE Entrambi ES:DI,DS:SI LODS niente Sorgente DS:SI STOS REP Destinazione ES:DI INS REP Destinazione ES:DI OUTS REP Sorgente DS:SIQueste istruzioni hanno 2 tipi di sintassi:
[prefisso di ripetizione] istruzione [ES:[dest]],[sorgente]
[prefisso di ripetizione] istruzione < B|W|niente >
Dove B e W stanno per Byte e Word rispettivamente. Ad esempio, l'istruzione
MOVS può essere data con operandi (byte o word), oppure posso usare MOVSB
per spostare byte o MOVSW per spostare word.
REP - Ripete fino a quando CX=0
REPE o REPZ - Ripete mentre è uguale o fino a quando CX=0
REPNE o REPNZ - Ripete mentre è diverso o fino a quando CX=0
Durante l'esecuzione un'istruzione preceduta da uno di questi prefissi segue
il seguente algoritmo:
1.Controlla il valore di CX, se CX=0 esce. 2.Esegue l'operazione sulla stringa. 3.Aumente il valore di SI e/o DI (o diminuisce, dipende dal DF). L'incremento è 1 per le operazioni sui byte, 2 per quelle sulle word. 4.Decrementa CX 5.Se l'istruzione è SCAS o CMPS controlla lo ZF (Zero Flag) ed esce se la condizione è falsa. 6.Torna al punto 1.Ora che abbiamo visto in generale come funzionano vediamo a cosa servono e come si usano una ad una.
>MOVS
Questa serve per muovere una stringa da una locazione di memoria ad un altra.
La sintassi da usare è:
[REP] MOVS < destinazione >,< sorgente >
[REP] MOVSB
[REP] MOVSW
Dove i suffissi B e W stanno per Byte e Word.
.MODEL small
.DATA
source DB 10 DUP ('0123456789')
destin DB 10 DUP (?)
.CODE
mov ax,@data ;è un altro modo per caricare il segmento
mov ds,ax ;lo metto in DS
mov es,ax ;e anche in ES
...
...
...
cld
mov cx,10 ;imposto il numero di iterazioni
mov si,OFFSET source ;Carico l'ind. del sorgente
mov di,OFFSET destin ;Carico l'ind. della destinazione
rep movsb ;sposto 10 byte
Nota: ho a bella posta inserito una variazione nell'esempio di sopra.
Ve ne siete accorti? La direttiva:
source DB 10 DUP ('0123456789')
definisce 10 stringhe consecutive di 10 caratteri, invece di una stringa
di soli 10 car, che invece sarebbe definita tramite
source DB "0123456789"oppure
source DB '0123456789'Spesso è piu efficiente spostare le stringhe come word che non come byte effettuando cosi metà iterazioni. (Attenzione però al numero di byte che compongono la stringa: deve essere pari).
>SCAS
Questa istruzione è usata per cercare in una stringa uno specificato valore.
[REPE|REPNE] SCAS [ES:]< dest >
[REPE|REPNE] SCASB
[REPE|REPNE] SCASW
La stringa su cui operare deve essere all'indirizzo ES:DI e il valore da
cercare deve essere in AL o in AX (byte o word rispettivamente).
.DATA
stringa DB "Ken il guerriero"
lung EQU $-stringa ;lunghezza della stringa
pstringa DD stringa ;puntatore alla stringa
.CODE
...
...
cld ;direzione dx-->sx
mov cx,lung
les di,pstringa
mov al,'r' ;carattere da cercare
repne scasb ;cerco
jnz non_trovato ;se non lo trovo salto
... ;ES:DI-1 punta al carattere che cercavo
... ;in questo caso la prima r
...
...
non_trovato:
Anche qui una novità: la definizione
lung EQU $-stringa ;lunghezza della stringafa calcolare all'assemblatore la lunghezza di una stringa. In tal caso quindi lung rappresenta il valore 16. In che modo viene calcolata la lunghezza? $ rappresenta il puntatore far alla posizione corrente; anche stringa è un puntatore far (infatti l'istruzione seguente inizializza pstringa con questo valore). Perciò $-stringa è un'espressione dell'aritmetica dei puntatori che viene valutata dall'assemblatore. Chi conosce il C, sa bene che
puntatore-puntatore=numeroe il numero rappresenta in tal caso la lunghezza della stringa.
.DATA
stringa DB "Ken il guerriero"
io DB "Antonio"
lung EQU $-stringa
è tutto giusto, però lung rappresenta ora il valore 23 e non 17 (la somma
delle lunghezze delle due stringhe stringa e io).
Notate che la scasb decrementa DI ogni volta, anche quando imposta il flag di zero, perciò non è ES:DI che punta al carattere che cercavo, bensì ES:DI-1
>CMPS
Questa è usata per confrontare due stringhe.
[REPE|REPNE] CMPS < sorg >,[ES:]< dest >
[REPE|REPNE] CMPSB
[REPE|REPNE] CMPSW
NOTA: Attenzione che in CMPS il sorgente è l'operatore a sinistra !!!!Esempio:
.MODEL Large
.DATA
string1 DB "Ken il guerriero"
.FARDATA ;uso un altro segmento dati di tipo FAR
string2 DB "Ken il pippero"
lung EQU $-string2
.CODE
mov ax,@data ;carico i due segmenti in DS e ES
mov ds,ax
mov ax,@fardata
mov es,ax
...
...
cld
mov cx,lung
mov si,OFFSET string1
mov di,OFFSET string2
repe cmpsb ;confronto
jz sono_uguali ;se ZF=0 sono uguali, altrimenti...
dec di ;posiziono i puntatori sul carattere diverso
dec si
...
...
sono_uguali:
>STOS
[REP] STOS [ES:]< destinazione >
[REP] STOSB
[REP] STOSW
Il valore con cui riempire le stringhe va messo in AL o AX (byte o word risp.)
Esempio:
.MODEL small
.DATA
stringa DB 100 DUP(?)
.CODE
...
...
cld ;direzione dx-->sx
mov ax,'aa' ;valore con cui riempire
mov cx,50 ;numero di iterazioni
mov di,OFFSET stringa ;puntatore alla stringa
rep stosw ;riempio con word
Notate che usando la STOSW che riempie con word, facendo 50 iterazioni riempio
tutti i 100 byte !!!
>LODS
Questa serve per caricare un valore da una stringa ad un registro.
La sintassi:
LODS [seg:]< sorgente >
LODSB
LODSW
Il valore che carichiamo va a finire in AL o AX e la stringa deve essere
puntata da DS:SI.Esempio :
.DATA
numeri DB 0,1,2,3,4,5,6,7,8,9
.CODE
...
...
cld
mov cx,10 ;numero di iterazioni
mov si,OFFSET numeri
mov ah,2
prendi: lodsb
add al,'0' ;converte in ASCII
mov dl,al
int 21h ;lo visualizza
loop prendi ;torna a cercare
>OUTS, INS
OUTS DX,[seg:]< sorgente >
OUTSB
OUTSW
INS [ES:]< destinazione >,DX
INSB
INSW
Il numero della porta va specificato in DX e non puo' essere specificato per
valore.
Esempio:
.DATA
count EQU 100
buffer DB count DUP(?)
inport DW ?
.CODE
...
...
cld ;direzione
mov cx,count ;numero iterazioni
mov di,OFFSET buffer ;puntatore al buffer
mov dx,inport ;numero della porta
rep insb ;carica nel buffer
Si usa CX come contatore del numero di byte/word da trasferire.
Anche per stavolta avrei terminato, ho aggiunto al vostro bagaglio parecchie
nuove istruzioni molto utili per copiare spostare ... dati, che è poi la cosa
principale che un programma fa !!!
| Assembly Page di Antonio |
|