1 M. Rebaudengo, M. Sonza Reorda Politecnico di Torino Dip. di Automatica e Informatica M. Rebaudengo - M. Sonza Reorda L’Assembler 8086 Istruzioni per la Manipolazione delle Stringhe
2 M. Rebaudengo, M. Sonza Reorda Istruzioni per la manipolazione delle stringhe L’8086 possiede un gruppo di istruzioni per la manipolazione di stringhe, ossia di sequenze contigue di byte o word. Le operazioni che possono essere effettuate sono: la copiatura da una stringa sorgente ad una stringa destinazione; il confronto tra due stringhe; la ricerca di un valore all’interno di una stringa; la modifica del contenuto di una stringa.
3 M. Rebaudengo, M. Sonza Reorda Istruzioni per la manipolazione di stringhe (segue) Tutte le istruzioni per la manipolazione delle stringhe hanno alcune caratteristiche comuni: possono lavorare su una o due stringhe; i due registri utilizzati come indici all’interno delle due stringhe vengono automaticamente aggiornati al termine dell’operazione elementare, in modo da puntare ciascuno all’elemento successivo all’interno della rispettiva stringa; ciascuna delle istruzioni di manipolazione esegue una singola operazione: l’assembler 8086 fornisce un meccanismo per la ripetizione di tali operazioni per un numero prefissato di volte o fino al verificarsi di una determinata condizione.
4 M. Rebaudengo, M. Sonza Reorda Preparazione dei registri Tutte le istruzioni per la manipolazione delle stringhe richiedono che: la stringa sorgente si trovi nel segmento di dato puntato da DS ; il registro SI memorizza l’indirizzo di offset dell’elemento da processare all’interno della sequenza. l’eventuale stringa destinazione si trovi nel segmento extra di dato puntato da ES ; il registro DI memorizza l’indirizzo di offset dell’elemento da processare.
5 M. Rebaudengo, M. Sonza Reorda Extra e data segment coincidenti Se i dati sono contenuti in un unico segmento di dato, le operazioni da fare per predisporre i registri per la manipolazione di stringhe sono le seguenti: copiare il contenuto del registro DS nel registro ES in modo da far coincidere i due segmenti; copiare gli offset delle due stringhe nei registri SI e DI. Esempio LUNGEQU 100.DATA STR1 DBLUNG DUP (?) STR2 DBLUNG DUP (?).CODE... PUSHDS POPES LEA SI, STR1 LEA DI, STR2
6 M. Rebaudengo, M. Sonza Reorda Extra e data segment separati La condizione di default prevista è quella di avere la stringa sorgente nel segmento di dato e la stringa destinazione nel segmento dati extra. In questo caso per caricare i registri SI e DI basta eseguire l’istruzione di LEA..MODEL COMPACT ; 1 segm. di codice, più segm. di dato.FARDATADSEG STR1 DB 100 DUP (?).FARDATAESEG STR2 DB 100 DUP (?).CODE... ASSUME DS:DSEG, ES:ESEG MOV AX, DSEG MOV DS, AX MOV AX, ESEG MOV ES, AX LEA SI, STR1 LEA DI, STR2
7 M. Rebaudengo, M. Sonza Reorda Stringa destinazione nel segmento di dato Nel caso in cui la stringa destinazione si trovi nel segmento di dato ed il segmento extra sia usato per memorizzare un diverso segmento di dati, occorre far coincidere temporaneamente il contenuto dei registri DS ed ES. Le operazioni da eseguire sono le seguenti: salvare il contenuto di ES copiare il contenuto di DS in ES eseguire l’istruzione di manipolazione di stringhe ripristinare il contenuto del registro ES.
8 M. Rebaudengo, M. Sonza Reorda Esempio.MODEL COMPACT LUNGEQU100.FARDATA ESEG STR1 DB LUNG DUP (?) STR2 DB LUNG DUP (?) STRADD DD STR2....CODE... PUSHES; salvataggio di ES LEA SI, STR1; caricamento di SI LES DI, STRADD; caricamento di DI e ES... ; istruzioni di manipolazione POP ES; ripristino di ES
9 M. Rebaudengo, M. Sonza Reorda La ripetizione delle istruzioni per la manipolazione di stringhe Ogni istruzione per la manipolazione di stringhe opera su un singolo elemento della stringa (byte o word) per volta. Per processare l’intera stringa occorre eseguire un ciclo che permetta di ripetere l’istruzione di manipolazione per tutti gli elementi della stringa.
10 M. Rebaudengo, M. Sonza Reorda La ripetizione delle istruzioni per la manipolazione di stringhe (segue) Il processore mette a disposizione una classe di istruzioni utili per implementare i cicli per la manipolazione delle stringhe: REP REPE REPNE. Queste istruzioni vengono utilizzate in abbinamento con una delle istruzioni di manipolazione ed appaiono sulla stessa riga del codice.
11 M. Rebaudengo, M. Sonza Reorda La ripetizione delle istruzioni per la manipolazione di stringhe (segue) Formato REPxxxstring_istr Funzionamento Questo statement ripete l’esecuzione dell’istruzione string_istr per un numero di volte pari al contenuto del registro CX.
12 M. Rebaudengo, M. Sonza Reorda La ripetizione delle istruzioni per la manipolazione di stringhe (segue) Le istruzioni REPE e REPNE sono due varianti che possono essere utilizzate abbinate alle istruzioni di confronto e di ricerca. L’istruzione REPE ripete il ciclo finché il registro CX ha un valore diverso da 0 e le parole confrontate sono uguali. L’istruzione REPNE ripete il ciclo finchè il registro CX ha un valore diverso da 0 e le parole confrontate sono diverse.
13 M. Rebaudengo, M. Sonza Reorda La ripetizione delle istruzioni per la manipolazione di stringhe (segue) Per utilizzare le istruzioni REP, REPE e REPNE occorre dunque caricare il registro CX con la dimensione della stringa. Analogamente a quanto avviene nel caso dell’istruzione LOOP, ad ogni esecuzione dell’istruzione il contenuto del registro CX viene decrementato di una unità. La differenza sostanziale tra l’istruzione LOOP e l’istruzione REP è che l’istruzione REP permette la ripetizione di un’unica istruzione di manipolazione di stringhe, mentre la LOOP permette di ripetere una generica sequenza di istruzioni.
14 M. Rebaudengo, M. Sonza Reorda Esempio LUNGEQU100.DATA STR1DB LUNG DUP (?); stringa sorgente STR2DBLUNG DUP (?); stringa destinaz.....CODE... PUSHDS POP ES LEA SI, STR1 LEA DI, STR2 MOV CX, LUNG REPMOVSB...
15 M. Rebaudengo, M. Sonza Reorda Esempio (II) LUNGEQU100.DATA STR1DB LUNG DUP (?) STR2DBLUNG DUP (?)....CODE... PUSHDS POP ES LEA SI, STR1 LEA DI, STR2 MOV CX, LUNG ciclo:MOVSB LOOPciclo... Equivalente al precedente
16 M. Rebaudengo, M. Sonza Reorda Aggiornamento del contenuto dei registri indice Le istruzioni per la manipolazione delle stringhe prevedono che i registri SI e DI contengano l’offset delle parole da processare. Quando si esegue ripetutamente una stessa istruzione di manipolazione, il contenuto dei registri è automaticamente aggiornato per indirizzare la parola successiva nella stringa.
17 M. Rebaudengo, M. Sonza Reorda Aggiornamento del contenuto dei registri indice (segue) Il contenuto dei registri SI e DI è aggiornato automaticamente dalla stessa istruzione di manipolazione, in base al valore del flag di direzione ( DF ): se il flag DF vale 0, dopo ogni esecuzione dell’istruzione di manipolazione il contenuto dei registri di indice è incrementato di una unità per le stringhe di byte e di due unità per le stringhe di word. se il flag DF vale 1, dopo ogni esecuzione dell’istruzione di manipolazione il contenuto dei registri di indice è decrementato di una unità per le stringhe di byte e di due unità per le stringhe di word.
18 M. Rebaudengo, M. Sonza Reorda Aggiornamento del contenuto dei registri indice (segue) A seconda del valore del flag DF le operazioni sulle stringhe vengono quindi eseguite in avanti con DF = 0 (forward) oppure all’indietro con DF = 1 (backword). Il valore del flag DF è modificato mediante le due istruzioni STD e CLD. L’istruzione STD forza il flag DF ad 1, mentre l’istruzione CLD forza il flag DF a 0. È bene ricordarsi di aggiornare sempre il valore del flag DF prima di eseguire un ciclo di manipolazione di stringhe, in quanto il processore non garantisce di mantenere costante il valore di DF tra due cicli di manipolazione.
19 M. Rebaudengo, M. Sonza Reorda Scansione in avanti LUNGEQU100.DATA STR1DB LUNG DUP (?) STR2DBLUNG DUP (?)....CODE PUSH DS POP ES LEA SI, STR1 LEA DI, STR2 MOV CX, LUNG CLD; flag DF = 0 REP MOVSB...
20 M. Rebaudengo, M. Sonza Reorda Scansione all’indietro LUNGEQU100.DATA STR1DB LUNG DUP (?) STR2DBLUNG DUP (?)....CODE PUSH DS POP ES LEA SI, STR1 + SIZE STR1 - TYPE STR1 LEA DI, STR2 + SIZE STR2 - TYPE STR2 MOV CX, LUNG STD; flag DF = 1 REP MOVSB...
21 M. Rebaudengo, M. Sonza Reorda Riepilogo delle operazioni necessarie per la manipolazione delle stringhe Preparazione dei registri caricamento del registro CX con il numero di elementi della stringa aggiornamento del flag DF esecuzione dell’istruzione REP (o REPE o REPNE ), abbinata all’opportuna istruzione di manipolazione.
22 M. Rebaudengo, M. Sonza Reorda Istruzioni per la Manipolazione delle Stringhe e Interrupt Al termine di ogni istruzione primitiva i registri indice ed eventualmente CX (se vi è un prefisso) sono aggiornati; nel caso esista un prefisso, IP non viene aggiornato se non al termine dell'iterazione. In questo modo il processore può rilevare e servire richieste di interrupt senza attendere il termine dell'istruzione, che può essere ripresa dal punto in cui era stata interrotta.
23 M. Rebaudengo, M. Sonza Reorda Copiatura di una stringa Le istruzioni MOVSB e MOVSW permettono di copiare una stringa da un indirizzo sorgente ad un indirizzo destinazione. Formato MOVSB MOVSW Funzionamento L’istruzione MOVSB copia il byte avente indirizzo DS:SI nella locazione di memoria ES:DI. L’istruzione MOVSW copia la word avente indirizzo DS:SI nella locazione di memoria ES:DI. Al termine dell’esecuzione dell’istruzione vengono aggiornati entrambi i registri di indice.
24 M. Rebaudengo, M. Sonza Reorda Esempio: scalamento di una stringa di 5 posizioni LUNG EQU100.DATA STRDBLUNG DUP (?) DB5 DUP (?)....CODE PUSH DS POP ES LEA SI, STR LEA DI, STR + 5 MOV CX, LUNG CLD; scansione in avanti REP MOVSB... ERRORE !
25 M. Rebaudengo, M. Sonza Reorda Esempio: scalamento di una stringa di 5 posizioni LUNGEQU100.DATA STRDBLUNG DUP (?) DB5 DUP (?)....CODE... PUSH DS POP ES LEA SI, STR + SIZE STR - TYPE STR LEA DI, STR + SIZE STR - TYPE STR + 5 MOV CX, LUNG STD; scansione all’indietro REP MOVSB... VERSIONE CORRETTA
26 M. Rebaudengo, M. Sonza Reorda Confronto tra stringhe Le istruzioni CMPSB e CMPSW permettono di confrontare due stringhe tra loro. Formato CMPSB CMPSW Funzionamento L’istruzione CMPSB lavora con stringhe di byte, mentre l’istruzione CMPSW lavora con stringhe di word. Ad ogni esecuzione dell’istruzione CMPSB / CMPSW viene effettuato il confronto tra la locazione di memoria avente indirizzo DS:SI e la locazione di memoria avente indirizzo ES:DI. Al termine dell’esecuzione dell’istruzione vengono aggiornati entrambi i registri di indice.
27 M. Rebaudengo, M. Sonza Reorda Confronto tra stringhe L’istruzione di confronto viene tipicamente usata congiuntamente alle istruzioni REPE e REPNE, ed in particolare: si usa REPE se si vuole verificare se due stringhe sono uguali; si usa REPNE se si vuole verificare se due stringhe sono diverse. Il ciclo di confronto termina al verificarsi di una delle seguenti condizioni: la stringa è terminata (il registro CX ha valore nullo) è stata trovata una disuguaglianza (con REPE ) od una uguaglianza (con REPNE ).
28 M. Rebaudengo, M. Sonza Reorda Esempio LUNGEQU100.DATA STR1DBLUNG DUP (?) STR2DBLUNG DUP (?)....CODE... PUSHDS POP ES LEA SI, STR1 LEA DI, STR2 MOV CX, LUNG CLD REPE CMPSB...
29 M. Rebaudengo, M. Sonza Reorda Confronto tra stringhe (segue) Ogni esecuzione dell’istruzione di confronto aggiorna i flag. È possibile analizzare lo stato del flag ZF per verificare se la condizione di uguaglianza è stata verificata oppure no. Questa operazione può essere eseguita mediante un’istruzione di salto condizionato. All’uscita del ciclo è normalmente utile conoscere quale parola ha causato la terminazione. Tale informazione è contenuta nel registro SI. Poiché il registro SI è aggiornato alla fine di ciascun confronto, all’uscita del ciclo il registro SI contiene l’offset della parola successiva a quella che ha causato la terminazione.
30 M. Rebaudengo, M. Sonza Reorda LUNGEQU100.DATA STR1DBLUNG DUP (?) STR2DBLUNG DUP (?).CODE … PUSH DS POP ES LEA SI, STR1 LEA DI, STR2 MOV CX, LUNG CLD REPE CMPSB JElab1; stringhe uguali ? DEC SI ; No: decrementa SI MOV AL, [SI]; primo carattere diverso JMP lab2 lab1: MOV AL, 0 lab2:… Esempio Confronta due stringhe e scrive in AL: 0, se sono uguali il primo carattere diverso, se non lo sono.
31 M. Rebaudengo, M. Sonza Reorda Scansione di una stringa Le istruzioni SCASB e SCASW permettono di scandire una stringa per ricercare un valore specifico. Formato SCASB SCASW Funzionamento L’istruzione SCASB lavora con stringhe di byte, mentre l’istruzione SCASW lavora con stringhe di word. L’istruzione SCASB usa i registri AL e DI, mentre l’istruzione SCASW usa i registri AX e DI. I registri AL e AX contengono il valore da confrontare, mentre DI contiene l’offset della stringa da scandire. Al termine dell’esecuzione dell’istruzione viene aggiornato il contenuto del registro DI.
32 M. Rebaudengo, M. Sonza Reorda Scansione di una stringa (segue) Ad ogni esecuzione dell’istruzione SCASB / SCASW viene effettuato il confronto tra il contenuto della locazione ES : DI ed il contenuto del registro accumulatore. Anche le istruzioni SCASB e SCASW utilizzano le istruzioni REPE e REPNE per generare il ciclo. per cercare un valore diverso dal contenuto dei registri AL ed AX si usa l’istruzione REPE, per cercare un valore coincidente al contenuto dei registri AL ed AX si usa l’istruzione REPNE.
33 M. Rebaudengo, M. Sonza Reorda Scansione di una stringa (segue) Il ciclo di scansione termina al verificarsi di una delle seguenti condizioni: la stringa è terminata (il registro CX ha valore nullo). è stata trovata una disuguaglianza tra il contenuto del registro accumulatore e la stringa indirizzata da DI (con REPE ), oppure è stata trovata una uguaglianza tra il contenuto del registro accumulatore e la stringa indirizzata da DI (con REPNE ).
34 M. Rebaudengo, M. Sonza Reorda Esempio Si realizzi un frammento di programma che scandisca una stringa di caratteri e che visualizzi il primo carattere diverso dal carattere spazio. #include main() { int i; char string[25]; strcpy(string," Fatti non foste a viver come bruti..."); for (i=0 ; i<25 ; i++) if (string[i] != ' ') {printf("%c",string[i]); break; }... }
35 M. Rebaudengo, M. Sonza Reorda Soluzione Assembler.MODEL small.STACK.DATA STRING DB " Fatti non foste a viver come bruti" LUNG EQU $-STRING ST_ADD DD STRING....CODE... MOV AL, " " LES DI, ST_ADD MOV CX, LUNG CLD REPE SCASB JE esci DEC DI MOV DL, [DI] MOV AH, 02H; visualizza INT 21H esci:...
36 M. Rebaudengo, M. Sonza Reorda Inizializzazione di una stringa Le istruzioni STOSB e STOSW permettono di inizializzare tutti gli elementi di una stringa ad un determinato valore. Formato STOSB STOSW Funzionamento L’istruzione STOSB lavora con stringhe di byte, mentre l’istruzione STOSW lavora con stringhe di word. L’istruzione STOSB usa i registri AL e DI, l’istruzione STOSW usa i registri AX e DI. I registri AL e AX contengono il valore con cui viene inizializzata la stringa, DI contiene l’offset della stringa da inizializzare.
37 M. Rebaudengo, M. Sonza Reorda Inizializzazione di una stringa (segue) Al termine dell’esecuzione dell’istruzione viene aggiornato il contenuto del registro DI. L’effetto delle istruzioni STOSB / STOSW è di copiare il valore contenuto nei registri AL (od AX ) nella locazione di memoria avente indirizzo ES : DI.
38 M. Rebaudengo, M. Sonza Reorda Esempio Si vuole realizzare un frammento di programma che scriva il carattere spazio in tutti gli elementi di una stringa. main() { int i; char str[26];... for (i=0 ; i<25 ; i++) str[i] = ' '; str[25] = '\0';... }
39 M. Rebaudengo, M. Sonza Reorda Soluzione Assembler LUNGEQU 25.MODEL small.STACK.DATA STR DBLUNG DUP(?) ST_ADD DD STR....CODE... MOVAL, " " LESDI, ST_ADD MOV CX, LUNG CLD REP STOSB...
40 M. Rebaudengo, M. Sonza Reorda Elaborazione di una stringa Le istruzioni LODSB e LODSW permettono di copiare un elemento di una stringa nei registri accumulatore. Formato LODSB LODSW Funzionamento L’istruzione LODSB lavora con stringhe di byte, mentre l’istruzione LODSW lavora con stringhe di word. L’istruzione LODSB usa i registri AL e SI, l’istruzione LODSW usa i registri AX e SI.
41 M. Rebaudengo, M. Sonza Reorda Elaborazione di una stringa (segue) L’effetto delle istruzioni LODSB e LODSW è quello di copiare il contenuto della locazione di memoria avente indirizzo DS : SI nei registri AL o AX.
42 M. Rebaudengo, M. Sonza Reorda Esercizio Conteggio del numero di spazi bianchi in una stringa di caratteri. main() { char sorg[100]; int i, count = 0;... for (i=0 ; i<100 ; i++) if (sorg[i] == ' ') count++;... }
43 M. Rebaudengo, M. Sonza Reorda Soluzione Assembler LUNG EQU 100.MODEL small.STACK.DATA SORG DB LUNG DUP (?)....CODE... LEA SI, SORG MOV CX, LUNG MOV BX, 0 CLD ciclo: LODSB CMPAL, ' '; AL = ' ' ? JNEnext; No: va a next INC BX next: LOOP ciclo... ; Sì: fine
44 M. Rebaudengo, M. Sonza Reorda Elaborazione di una stringa (segue) Le istruzioni LODSB e LODSW sono utili in coppia con le istruzioni STOSB / STOSW per elaborare il contenuto di una stringa, ossia per eseguire la stessa operazione su tutte le parole di una stringa. Per elaborare una stringa: si copia l’offset della stringa sorgente in SI ; si copia l’offset della stringa destinazione in DI ; si copia la lunghezza della stringa in CX ; si aggiorna il flag DF ; per ogni parola della stringa sorgente: si copia la parola nel registro accumulatore si elabora il contenuto del registro si copia il contenuto accumulatore nella stringa destinazione.
45 M. Rebaudengo, M. Sonza Reorda Esempio Si vuole realizzare un frammento di programma che trasferisca un vettore di interi da una zona di memoria ad un’altra, con la condizione che i termini negativi siano trasformati in termini di valore nullo. main() { int sorg[100], dest[100], i;... for (i=0 ; i<100 ; i++) if (sorg[i] < 0) dest[i] = 0; else dest[i] = sorg[i];... }
46 M. Rebaudengo, M. Sonza Reorda Soluzione Assembler LUNGEQU 100.MODELsmall.STACK.DATA SORG DW LUNG DUP (?) DEST DW LUNG DUP (?) ST_ADD DD DEST....CODE... LEA SI, SORG LES DI, ST_ADD
47 M. Rebaudengo, M. Sonza Reorda MOV CX, LUNG CLD ciclo: LODSW CMP AX, 0 JNL lab MOV AX, 0 lab: STOSW LOOP ciclo...
48 M. Rebaudengo, M. Sonza Reorda Esercizio Si vuole realizzare un frammento di programma che trasferisca una stringa di caratteri da un’area di memoria sorgente ad un’area di memoria destinazione, eseguendo la conversione da caratteri minuscoli a caratteri maiuscoli. main() { char sorg[100], dest[100]; int i;... for (i=0 ; i<100 ; i++) if ((sorg[i] = 'a')) dest[i] = sorg[i] + 'A'- 'a'; else dest[i] = sorg[i]; }
49 M. Rebaudengo, M. Sonza Reorda Soluzione Assembler LUNGEQU100.MODELsmall.STACK.DATA SORG DB LUNG DUP (?) DEST DB LUNG DUP (?) ST_ADD DD DEST.CODE... LEA SI, SORG LES DI, ST_ADD
50 M. Rebaudengo, M. Sonza Reorda MOV CX, LUNG CLD ciclo: LODSB CMPAL, 'z' JNLEcopia CMPAL, 'a' JNGEcopia ADD AL, 'A'-'a' copia: STOSB LOOP ciclo...
51 M. Rebaudengo, M. Sonza Reorda Strlen, Strcpy, Strcat Come esempio di uso delle istruzioni per la manipolazione di stringhe si riporta il codice generato dal compilatore Microsoft C 6.0 per le procedure standard C strlen, strcpy e strcat.
52 M. Rebaudengo, M. Sonza Reorda Strlen PUSH BP MOV BP,SP MOV DX,DI; salva DI MOV AX,DS MOV ES,AX MOV DI,Word Ptr [BP+04]; puntatore alla stringa XOR AX,AX MOV CX,0FFFFH REPNE SCASB; cerca la fine NOT CX DEC CX XCHG AX,CX; valore di ritorno MOV DI,DX POP BP RET
53 M. Rebaudengo, M. Sonza Reorda Strcpy PUSH BP MOVBP,SP MOVDX,DI MOVBX,SI MOVSI,Word Ptr [BP+06] MOVDI,SI MOVAX,DS MOVES,AX XOR AX,AX MOVCX,FFFF REPNESCASB NOTCX MOVDI,Word Ptr [BP+04] MOVAX,DI TEST AL,01 JZ LAB MOVSB DECCX LAB:SHRCX,1 REPMOVSW ADCCX,CX REPMOVSB MOVSI,BX MOV DI,DX POPBP RET
54 M. Rebaudengo, M. Sonza Reorda Nota Se si deve calcolare il numero d'ordine k dell'elemento di un blocco, che ha causato l'uscita dal ciclo di ripetizione, si usano le istruzioni MOVCX,FFFF; CX N REPNE SCASB; CX N-k NOTCX; CX N-(N-k)=k Infatti, eseguire l'istruzione NOT significa sottrarre l'operando al valore massimo rappresentabile (N=FFFF).
55 M. Rebaudengo, M. Sonza Reorda Strcat PUSHBP MOVBP,SP MOVDX,DI MOVBX,SI MOVAX,DS MOVES,AX MOVDI,Word Ptr [BP+04] XORAX,AX MOVCX,FFFF REPNESCASB; ricerca fine prima stringa LEASI,Word Ptr [DI-01] MOVDI,Word Ptr [BP+06] MOVCX,FFFF REPNESCASB; ricerca fine seconda stringa NOTCX
56 M. Rebaudengo, M. Sonza Reorda Strcat (II) SUB DI,CX XCHG DI,SI MOV AX,Word Ptr [BP+04] TEST SI,0001 JZ LAB MOVSB DEC CX LAB:SHR CX,1 REP MOVSW; copiatura ADC CX,CX REP MOVSB MOV SI,BX MOV DI,DX POP BP RET