Zoom Icon

Lavorare con le Stringhe

From UIC

Lavorare con le Stringhe

Contents


Infos
Author: b0nu$
Email: bonus@numerica.it
Website:
Date: 01/01/2001 (dd/mm/yyyy)
Level: No brain needed
Language: Italian Image:Flag_Italian.gif
Comments:



Introduzione

Con il termine stringa non mi riferisco solo alla definizione classica di sequenza di caratteri, ma intendo una qualsiasi sequenza di byte, word,... Le istruzioni che analizzeremo sono:

        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

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:SI

Queste 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 con l'istruzione MOVS può essere data con operandi(byte o word), oppure posso usare MOVSB per spostare byte o MOVSW per spostare word. I prefissi di ripetizione controllano il valore di CX e le eventuali condizioni specificate:

        REP  -  Ripete fino a quando CX=0
        REPE o REPZ  -  Ripete mentre è uguale o fino a quando CX=0
        REPNE o REPNZ  -  Ripente 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 dui bye 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.


Le Istruzioni

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. Al solito ecco un esempio del loro utilizzo:

.MODEL small
.DATA
source DB 10 DUP ('0123456789')
destin DB 10 DUP (?)
.CODE
mov ax,@data ;è un altro modo per carica 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 desinazione
rep movsb ;sposto 10 byte

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 scritta: deve essere pari).

SCAS

Questa istruzione è usata per cercare in una stringa uno specificato valore.
Sintassi:

        [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). Quando trova il valore cercato viente settato lo ZF.
Esempio:

.DATA
stringa DB "Ken il guerriero"
lung EQU $-stringa ;lunghezza della stringa
pstringa DD string ;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 punta al carattere che cercavo
... ;in questo caso la prima r
...
...

non_trovato:

CMPS

Qeuesta è usata per confrontare due stringhe.
Sintassi:

        [REPE|REPNE]    CMPS    < sorg >,[ES:]< dest >
        [REPE|REPNE]    CMPSB
        [REPE|REPNE]    CMPSW

NOTA: Attenzione che in CMPS il sorgente è l'operatore a sinistra !!!! CMPS lavora confrontando uno ad uno i valori puntati da DI con quelli puntati da SI, se sono uguali viene settato lo ZF.
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

Questa serve per riempire una stringa con un determinato valore.
Sintassi:

        [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,'aà ;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. Al contrario delle altre istruzioni LODS non è usata con i prefissi, non avrebbe molto senso!
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 e INS

Queste istruzioni servono per trasferire stringa dalle/alle porte.
La loro sintassi:

        OUTS DX,[seg:]< sorgente >
        OUTSB
        OUTSW

        INS  [ES:]< destinazione >,DX
        INSB
        INSW

Il numero della porta va specificato in DX e non può 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 buffe
mov dx,inport ;numero della porta
rep insb ;carica nel buffer

Si usa CX come contatore del numero di byte/word da trasferire.


Note Finali

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 !!!


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevoli e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.