Assemblaggio - Stringhe
Abbiamo già utilizzato stringhe di lunghezza variabile nei nostri esempi precedenti. Le stringhe di lunghezza variabile possono avere tanti caratteri quanti sono necessari. Generalmente, specifichiamo la lunghezza della stringa in uno dei due modi:
- Memorizzazione esplicita della lunghezza della stringa
- Usando un personaggio sentinella
È possibile memorizzare la lunghezza della stringa in modo esplicito utilizzando il simbolo del contatore $ posizione che rappresenta il valore corrente del contatore posizione. Nell'esempio seguente:
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
$ punta al byte dopo l'ultimo carattere della variabile stringa msg . Perciò,$-msgdà la lunghezza della stringa. Possiamo anche scrivere
msg db 'Hello, world!',0xa ;our dear string
len equ 13 ;length of our dear string
In alternativa, è possibile memorizzare stringhe con un carattere sentinella finale per delimitare una stringa invece di memorizzare esplicitamente la lunghezza della stringa. Il carattere sentinella dovrebbe essere un carattere speciale che non compare all'interno di una stringa.
Ad esempio:
message DB 'I am loving it!', 0
Istruzioni per le stringhe
Ogni istruzione stringa può richiedere un operando di origine, un operando di destinazione o entrambi. Per i segmenti a 32 bit, le istruzioni stringa utilizzano i registri ESI e EDI per puntare rispettivamente agli operandi di origine e di destinazione.
Per i segmenti a 16 bit, tuttavia, i registri SI e DI vengono utilizzati per puntare rispettivamente alla sorgente e alla destinazione.
Sono disponibili cinque istruzioni di base per l'elaborazione delle stringhe. Sono -
MOVS - Questa istruzione sposta 1 byte, parola o doppia parola di dati dalla posizione di memoria a un'altra.
LODS- Questa istruzione viene caricata dalla memoria. Se l'operando è di un byte, viene caricato nel registro AL, se l'operando è una parola, viene caricato nel registro AX e una doppia parola viene caricata nel registro EAX.
STOS - Questa istruzione memorizza i dati dal registro (AL, AX o EAX) alla memoria.
CMPS- Questa istruzione confronta due elementi di dati in memoria. I dati potrebbero essere di dimensioni in byte, parola o doppia parola.
SCAS - Questa istruzione confronta il contenuto di un registro (AL, AX o EAX) con il contenuto di un elemento in memoria.
Ciascuna delle istruzioni precedenti ha una versione di byte, parola e doppia parola e le istruzioni di stringa possono essere ripetute utilizzando un prefisso di ripetizione.
Queste istruzioni utilizzano la coppia di registri ES: DI e DS: SI, dove i registri DI e SI contengono indirizzi di offset validi che si riferiscono a byte archiviati in memoria. SI è normalmente associato a DS (segmento dati) e DI è sempre associato a ES (segmento extra).
I registri DS: SI (o ESI) ed ES: DI (o EDI) puntano rispettivamente agli operandi di origine e di destinazione. Si presume che l'operando di origine si trovi in DS: SI (o ESI) e l'operando di destinazione in ES: DI (o EDI) in memoria.
Per gli indirizzi a 16 bit, vengono utilizzati i registri SI e DI, mentre per gli indirizzi a 32 bit vengono utilizzati i registri ESI e EDI.
La tabella seguente fornisce varie versioni delle istruzioni di stringa e lo spazio presunto degli operandi.
Istruzioni di base | Operandi in | Byte Operation | Operazione con le parole | Operazione a doppia parola |
---|---|---|---|---|
MOVS | ES: DI, DS: SI | MOVSB | MOVSW | MOVSD |
LODS | AX, DS: SI | LODSB | LODSW | LODSD |
STOS | ES: DI, AX | STOSB | STOSW | STOSD |
CMPS | DS: SI, ES: DI | CMPSB | CMPSW | CMPSD |
SCAS | ES: DI, AX | SCASB | SCASW | SCASD |
Prefissi di ripetizione
Il prefisso REP, se impostato prima di un'istruzione stringa, ad esempio - REP MOVSB, provoca la ripetizione dell'istruzione in base a un contatore posto nel registro CX. REP esegue l'istruzione, diminuisce CX di 1 e controlla se CX è zero. Ripete l'elaborazione dell'istruzione fino a quando CX è zero.
Il Flag di direzione (DF) determina la direzione dell'operazione.
- Utilizzare CLD (Clear Direction Flag, DF = 0) per eseguire l'operazione da sinistra a destra.
- Utilizzare STD (Set Direction Flag, DF = 1) per eseguire l'operazione da destra a sinistra.
Il prefisso REP ha anche le seguenti varianti:
REP: È la ripetizione incondizionata. Ripete l'operazione fino a quando CX è zero.
REPE o REPZ: è una ripetizione condizionale. Ripete l'operazione mentre il flag zero indica uguale / zero. Si ferma quando ZF indica non uguale / zero o quando CX è zero.
REPNE o REPNZ: è anche una ripetizione condizionale. Ripete l'operazione mentre il flag zero indica non uguale / zero. Si ferma quando ZF indica uguale / zero o quando CX viene decrementato a zero.