MOVS SCAS CMPS LODS STOS INS OUTS REPxxQueste 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 ripetizionenota: 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=0Durante 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] MOVSWDove 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 byteNota: 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] SCASWLa 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] CMPSWNOTA: 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] STOSWIl 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 wordNotate 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 LODSWIl 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 INSWIl 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 bufferSi 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 |
|