• Aucun résultat trouvé

Traitement des tableaux et chaînes de caractères

N/A
N/A
Protected

Academic year: 2022

Partager "Traitement des tableaux et chaînes de caractères"

Copied!
41
0
0

Texte intégral

(1)

Traitement des tableaux et chaînes de caractères

Une chaîne de caractères ASCII est constiuée d’une suite de caractères terminée par le ‘$’. Ce type de caractères est utilisé par le MS DOS. Une chaîne de caratères ASCII se déclare à l’aide de la directive DB

Exemple:

mesg DB ‘bonjour$’

Message DB 'Bonjour$' est la même chose que Message DB 'B', 'o', 'n', 'j', 'o', 'u', 'r', '$' ou que Message DB 66, 111, 110, 106, 111, 119, 114, 36

La seule obligation est le caractère '$' qui indique la fin de la chaîne (sinon les octets situés à la suite du message en mémoire sont aussi affichés comme caractères).

Zone DB 30 DUP(?), ‘$’; chaîne de 30 caractères de valeur non définie Tamp DB 25 DUP (‘ ‘); chaîne de 25 espaces blancs

Ligne DB 10 dupl(‘ ‘); ‘*’, 20 dup (?), ‘$’

(2)

En assembleur, il n’existe pas de distinction entre une chaîne de caractères et un tableau de caractères. Ainsi, il est posible d’accéder à un élément quelconque de la chaîne.

;AL  zone[i]; i >= 0 mov SI, i

mov AL, zon[SI]

;Zone[i]  AL; i >= 0 mov DI, i

mov zone[DI], AL

Remarque: Les registres SI, DI, BX peuvent être utilisés indifférement pour accéder aux éléments d’une chaîne.

(3)

Exemple de parcours séquentiel d’une chaîne

;AX  nombre de lettres ‘L’

; SI registre d’index mov SI,0 MOV AX, 0

While1: CMP zone[SI], ‘$’; tester la fin de la chaîne le $ JA enwhile1

If1: CMP zone[SI], ‘L’

JNE endif1 INC AX Endif1: INC SI

JMP while1 Endwhile1:

(4)

Autre possibilité: utiliser SI comme pointeur

LEA SI,zone; SI contient l’adresse de début de zone

MOV AX, 0

While1: CMP byte PTR [SI], ‘$’; tester si la fin de la chaîne est atteint JA enwhile1

If1: CMP byte PTR [SI], ‘L’

JNE endif1 INC AX Endif1: INC SI

JMP while1 Endwhile1:

(5)

Les vecteurs

Vecteur d’entiers

Le principe est le même pour un vecteur d’entiers où chaque élément est stocké sur un entier. Pour un vecteur d’entiers stockés sur deux octets nous devons tenir compte de la longueur d’un élément du vecteur.

Exemple:

T dw 1, 4, 7,-1; vecteur de 4 entiers initialisés respectivement ; aux valeurs 1, 4, 7 et -1

T1 dw 100 dup (?); vecteur de 100 éléments non initialisés.

(6)

Implémentation en mémoire (un élément est sur 2 octets pour les mots) Indice 1 2 3 4

Déplacement 0 1 2 3 4 5 6 7 |---|

t | x x | x x | x x | x x | --- Fonction d’indicage: adresse de début de t

+ i * longueur d’un élément de t ---

(7)

• Exemple:

; AX  t[i]

lea SI, t

ADD SI,SI; SI = SI * 2 (longeur d’un élément de type mot) MOV AX, [SI]

; t[i]  AX lea SI, t ADD SI, SI MOV [SI], AX

(8)

Tableau à deux dimensions

La fonction d’indicage des tableaux à deux dimensions est plus complexe. Généralement, ces derniers sont rangés en mémoire ligne par ligne.

Exemple:

Ligne 1 x x x x x x x x Ligne 2 x x x x x x x x Ligne 3 x x x x x x x x Implémentation em mémoire

Ligne 1 ligne 2 ligne 3

x x x x x x x x x x x x x x x x x x x x x x x x

0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19 20 21 22 23 24

(9)

Soit n et m représentent le nombre de lignes et de colonnes, respectivement; et i et j les indices de ligne et de colonne:

Adresse de début du tableau t

+ i * m longueur d’un élément de t (sélection de la ligne) + j * longueur d’un élément de t (sélection de la colonne) ---

= addresse de l’élément t[i][j]

(10)

La matrice ci-dessous est déclarée comme suit:

M db 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12

Ou alors, pour plus de visibilité, comme suit:

M db 1, 2, 3, 4 db 5, 6, 7, 8 db 9, 10, 11, 12

La multidimentionnalité est gérée par le programmeur.

(11)

Exemple 8 : parcours d'un tableau

Ce programme passe une chaîne de caractères en majuscules. La fin de la chaîne est repérée par un caractère $. On utilise un ET logique pour masquer le bit 5 du caractère et le passer en majuscule (voir le code ASCII).

Title parcours

pile segment stack 100 dup (?) pile ends

data SEGMENT

tab DB 'Un boeuf Bourguignon', '$' data ENDS

code SEGMENT

ASSUME DS:data, CS:code debut: MOV AX, data

MOV DS, AX

MOV BX, offset tab ; adresse debut tableau repet: MOV AL, [BX] ; lit 1 caractère

AND AL, 11011111b ; force bit 5 à zero MOV [BX], AL ; range le caractère INC BX ; passe au suivant CMP AL, '$' ; arrive au $ final ?

JNE repet ; sinon recommencer MOV AH, 4CH

INT 21H ; Retour au DOS code ENDS

END debut

(12)

Trier un tableau

Étant donné un tableau de caractères, le problème consiste à les trier dans un ordre (ascendant ou descendant).

La stratégie utilisée est celle qui consiste à chaque itération de

l’algorithme à trouver le maximum ou minimum et à le déplacer au début de du tableau. Pour ce faire, on procède comme suit:

1. On utilise 3 registres: BX et CX et SI. BX servira d’indice de base pour accéder aux éléments du tableau, et SI l’indice relativement à BX pour accéder aux éléments. CX servira d’indice d’arrêt des itérations.

2. À chaque itération, la valeur de BX est augmentée dune unité, et celle de CX décrémentée d’une unité. Le processus peut être

arrêtée lorsque CX devient inférieur ou égal à 1. Pour accéder à un élément, dans une itération donnée, on le fait via le registre SI

(13)

Title Trier

pile segment stack 100 dup (?)

pile ends

sdata SEGMENT tab DB 100 dup (?) sdata ENDS

scode EGMENT

ASSUME DS:sdata, CS:scode

JMP debut

(14)

Tri proc near; trier une suite de caractères dans l’ordre ascendant etiquetri:

mov al, [bx]

mov di, 1 boucle:

cmp di, cx jg next_bx cmp al, [bx + di]

jle next_di xchg al, [bx + di]

mov [bx], al next_di:

inc di

jmp boucle next_bx:

inc bx

loop etiquetri Ret

Tri proc; fin de la fonction

(15)

DEBUT:

mov ax,sdata mov ds,ax

mov dx,offset tab

mov ah,0Ah; lecture d’une chaîne de caractères int 21h

mov DI, DX inc DI

mov CX, [DI]

DEC CX INC DI

MOV BX, DI

Call Tri

MOV AX, 4c00h;

Int 21h

SCODE ENDS

END DEBUT

(16)

Recherche dichotomique

À faire en classe

(17)

Manipulation de matrices

(18)

Transposé d’une matrice

Exemple; soit la matrice suivante:

M db 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12 La matrice N de M est alors

N db 1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12

D’une manière plus visuelle M db 1,2, 3, 4

db 5,6, 7, 8 db 9,10,11,12

La matrice transposée N est alors:

M db 1,5, 9 db 2,6,10 db 3,7,11 db 4,8,12

(19)

; ci-dessous n’est décrit que la partie qui effectue la transposition de M mov dx,offset M; M étant la matrice à tranposer

mov ah,0ah; lecture à partir du clavier d’une chaîne de caractères

; qui se termine dès qu’on tape le retour chariot (touche entrée) int 21h

MOV SI, DX; récupère l’adresse de début de la chaine M

INC SI; on se place sur l’adresse du nombre de caractères de M effectivement lus

INC SI; on se place sur le premier caractère de M

Lea DI, N; récupère l’adresse de la matrice transpose N XOR CX,CX

Mov CL, c; nombre de colonnes de M Mov CH, r; nombre de lignes de M XOR AX,AX; initialiser AX à 0

MOV BX,SI

(20)

BoucleExterne:

MOV AL,0 BoucleInterne:

MOV [DI], [BX]

INC DI

ADD BX, CL INC AL

CMP AL,CL ; répéter c fois (nombre de colonnes) JL BoucleInterne

INC SI INC AH

CMP AH, CH ; répéter r fois (nombre de lignes) JL BoucleExterne

…..

(21)

Multiplication de deux matrices

Soient deux matrices A(n,p) et B(p,m). Le programme assembleur ci- dessous effectue la multiplication de ces deux matrices suivant l’algorithme ci-dessous:

for (i=1; i<=n; i++)

for (j=1; j<=m; j++){

C[i,j] = 0;

for (k = 1; k<= p; k++)

C[i,j] = C[i,j] + A[i,k]*B[k,j];

} // fin sur j

(22)

Les instructions de traitement de chaînes de caractères

Les principales instructions disponibles pour effectuer des traitements de chaines sont comme ci-desous. Ce jeu d’instructions permet de considérer des chaînes de caractères (1 octet) et de mots (2 octets).

MOVS recopier des chaînes

SCAS chercher un élément (octet, mot) dans une chaîne CMPS comparer deux chaînes

LODS charger un élément dans le registre accumulateur STOS ranger le registre accumulateur dans une chaîne

Les instructions de chaînes fonctionnent toutes selon le même principe suivant:

(23)

1. Le flag de direction du registre des codes-conditions indique le sens de traitement de chaines: s’il vaut zéro, les chaînes sont traitées par adresse croissante, sinon les chaînes sont traitées par adresse décroissante.

Rappelons que l’instruction CLD initialise le flag de direction à 0, et l’instruction STD le positionne à 1

2. Le nombre d’itérations à effectuer doit être rangé dans le registre CX

3. L’adresse de départ de la chaîne donnée est dans

l’ensemble des registres DS et SI. L’adresse de départ de la chaîne résultat (ou deuxième chaîne opérande) est dans le registre ES et DI

4. Choisir le prefixe et l’instruction.

(24)

Les préfixes disponibles sont:

• REP ou REPZ répète l’opération du nombre de fois contenu dans CX

• REPE ou REPZ répète l’opération tant que l’on a l’égalité et que CX est différent de 0

• REPNE ou REPNZ répète l’opération tant que l’on a différence et que CX est différent de 0

(25)

Résumé des instructions sur des chaînes de caractères pour effectuer des opérations avec des opérandes se trouvant dans des locations mémoire.

Instruction Mnémonique Destination Source Préfixe

Dep. Ch. Oct. MOVSB ES:DI DS:SI REP

Dep. Ch. Mot MOVSW ES:DI DS:SI REP

Sav. Ch. Oct. STOSB ES:SI AL REP

Sav. Ch. Mot STOSW ES:SI AX REP

Chg. Ch. Oct. LODSB AL DS:SI /

Chg. Ch. Mot LODSW AX DS:SI /

Cmp. Ch. Oct. CMPSB ES:DI DS:SI REPE/REPNE

Cmp. Ch. Mot CMPSW ES:DI DS:SI REPE/REPNE

Scn. Ch. Oct. SCASB ES:DI AL REPE/REPNE

Scn. Ch. Oct. SCASW ES:DI AX REPE/REPNE

DF (registre flag)  Incrémentation (DF=0) Décrémentation (DF=1) du pointeur utilisé pour les opérations

CLD  DF=0 STD  DF=1

(26)

Les instructions de gestion des chaînes d’octets

a) L ’instruction MOVSB (« Move String Byte ») Syntaxe : MOVSB

Description : Copie l’octet adressé par DS:SI à l’adresse ES:DI. Si DF = 0, alors DI et SI sont

ensuite incrémentés, sinon ils sont décrémentés.

Remarque : Pour copier plusieurs octets, faire

REP MOVSB (« Repeat Move String Byte »). Le nombre d’octets à copier doit être transmis dans CX de même que pour un LOOP.

Exemple :

(27)
(28)

b) l’instruction SCASB (« Scan String Byte ») Syntaxe : SCASB

Description : Compare l’octet adressé par ES:DI avec AL. Les résultats sont placés dans le registre des indicateurs. Si DF = 0, alors DI est ensuite incrémenté, sinon il est décrémenté.

Remarque : Pour comparer plusieurs octets, faire “REP SCASB” ou

“REPE SCASB” (« Repeat until Egal »), ou encore “REPZ SCASB”

(« Repeat until Zero »). Ces trois préfixes sont équivalents.

Le nombre d’octets à comparer doit être transmis dans CX. La boucle ainsi créée s’arrête si CX = 0 ou si le caractère pointé par ES:DI est le même que celui contenu dans AL (i.e. si ZF = 1). On peut ainsi rechercher un caractère dans une chaîne.

Pour répéter au contraire la comparaison jusqu’à ce que ZF = 0, c’est-à-dire jusqu’à ce que AL et le caractère adressé par ES:DI diffèrent, utiliser REPNE ou REPNZ.

(29)
(30)

c) l’instruction LODSB (« Load String Byte ») Syntaxe : LODSB

Description : Charge dans AL l’octet adressé par DS:SI. Si DF = 0, alors SI est ensuite incrémenté, sinon il est décrémenté.

Remarque : Possibilité d’utiliser les préfixes de répétition, de même que pour MOVSB.

d) l’instruction STOSB (« Store String Byte ») Syntaxe : STOSB

Description : Stocke le contenu de AL dans l’octet adressé par ES:DI. Si DF

= 0, alors DI est ensuite incrémenté, sinon il est décrémenté.

Remarque : Possibilité d’utiliser les préfixes de répétition, de même que pour LODSB.

e) l’instruction CMPSB (« Compare String Byte ») Syntaxe : CMPSB

Description : Compare l’octet adressé par DS:SI et celui adressé par ES:DI. Si DF = 0, alors SI et DI sont ensuite incrémentés, sinon ils sont décrémentés.

Remarque : Possibilité d’utiliser les préfixes de répétition, de même que pour

(31)

Exemple: REP, MOVSB et CLD

TITLE PROG3_12.asm ;Transférer un bloc de 20 octets en mémoire pile segment stack

dw 100 dup (?) pile ends

data segment

DATA_S DB ‘AQWERTTYUIOPLJKHGFDS’

DATA_D DB 20 DUP(?) data ends

Code segment

assume CS:Code, ES:data, DS:data MAIN

MOV AX,DATA

MOV DS,AX ; Initialiser le segment de données MOV ES,AX ; Initialiser le segment Extra

CLD ; DF=0  Auto-incrémentation des pointeurs SI et DI MOV SI,OFFSET DATA_S ; Charger le pointeur source

MOV DI,OFFSET DATA_D ; Charger le pointeur destination MOV CX, 20 ; Charger le compteur

REP MOVSB; Déplacer les octets pointés par SI vers des locations pointés par DI ; et répète jusqu’à CX  0, sachant qu’a chaque itération SI et DI sont ; automatiquement incrémentés

MOV AH,4CH

INT 21H ; DOS Code ENDS

END MAIN

(32)

TITLE Exemple:LODSB , REP STOSW et CLD pile segment stack

dw 100 dup (?) pile ends

data segment

DATA_S DB ‘AQWERTTYUIOPLJKHGFDS’

DATA_D DB 20 DUP(?)

MESSAGE DB ‘ Mémoire défectueuse’

ESP_MEM DB 100 DUP(?) data ends

CODE segment

Assume CS:CODE, DS:data, ES: data MAIN:

MOV AX,DATA

MOV DS,AX ; Initialiser le segment de données MOV ES,AX ; Initialiser le segment Extra

CLD ; DF=0  Auto-incrémentation des pointeurs SI et DI

MOV CX, 50 ; Charger le compteur avec 50 (50 mots = 100 octets) MOV DI,OFFSET ESP_MEM ; Charger le pointeur destination MOV AX, 0CCCCH ; le pattern qui servira de test

REP STOSW ; Placer AAAAH dans 50 locations mémoires pointées par DI (jusqu’à CX0) ; sachant qu’a chaque itération DI est automatiquement incrémenté

MOV SI,OFFSET ESP_MEM ; Charger le pointeur source MOV CX, 100 ; Charger le compteur avec 100 (100 octets) ENCORE: LODSB ; Charger de DS:SI vers AL (pas de REP)

XOR AL, AH ; Est ce que le pattern est est le même, sachant que dans AL et AH se trouve CCh JNZ PASSE ; Sortir du programme si c’est différent  mémoire défectueuse

LOOP ENCORE ; continue jusqu’a CX0 JMP SORTI

PASSE: MOV DX, OFFSET MESSAGE ; Afficher un message sur écran MOV AH,09H ; le message est ‘Mémoire défectueuse’

INT 21H ; DOS SORTIR:MOV AH,4CH

INT 21H ; DOS CODE ENDS

END MAIN

(33)

Exemple: REPE CMPSB et CLD

TITLE PROG11.asm; Vérifier l’orthographe d’un mot et afficher un message PILE SEGMENT stack

DW 100 DUP (?) PILE ENDS

Data SEGMENT

MOT_EXACT DB ‘CHICOUTIMI’

MOT_TAPEE DB ‘CIHCOUTIMI’

MESSAGE1 DB ‘L’orthographe est juste’ , ‘$’

MESSAGE2 DB ‘L’orthographe est fausse’ , ‘$’

DATA ENDS CODE SEGMENT

ASSUME CS:code, DS:data, ES: data MAIN:

MOV AX,DATA

MOV DS,AX ; Initialiser le segment de données MOV ES,AX ; Initialiser le segment Extra

CLD ; DF=0  Auto-incrémentation des pointeurs SI et DI

MOV SI,OFFSET MOT_EXACT ; Charger le pointeur source MOV DI,OFFSET MOT_TAPEE ; Charger le pointeur destination

MOV CX, 10 ; Charger le compteur avec 10 (10 lettres ou octets) REPE CMPSB ; Répéter tant que les deux lettres soient égales ou C= 0.

;Si c’est différent le programme sort de cette instruction. A noter ;qu’à chaque itération SI et DI sont automatiquement incrémentés.

JE PASSE ; Si ZF=1 afficher le message 1 (égalité)

MOV DX,OFFSET MESSAGE2 ; Si ZF=0 afficher le message 2 (différence) JMP AFFICHAGE

PASSE: MOV DX, OFFSET MESSAGE1

AFFICHAGE: MOV AH,09H ; le message est ‘Mémoire défectueuse’

INT 21H ; DOS CODE ENDS

END MAIN

(34)

Exemple: REPNE SCASB et CLD

TITLE PROG12.asm ; Balayer une chaîne de caractère et Remplacer une lettre particulière par une autre Pile segment stack

dw 100 dup(?) Pile ends

Data segment

CHAINE DB ‘Mr. Gones’ , ‘$’

Data ends Code segment

MAIN: assume CS:code, DS:Data, ES:Data MOV AX,DATA

MOV DS,AX ; Initialiser le segment de données MOV ES,AX ; Initialiser le segment Extra

CLD ; DF=0  Auto-incrémentation des pointeurs SI et DI MOV DI, OFFSET CHAINE ; Charger le pointeur destination ES:DI

MOV CX, 9 ; Charger le compteur avec 9 (la taille de la chaîne de caractères) MOV AL, ‘G’ ; le caractère a scanner (balayer)

REPNE SCASB ; Répéter le balayage tant que les deux lettres ne sont pas égales ou jusqu’a C= 0.

JNE PASSE ; Saut si ZF=0 afficher le message 1 (égalité)

DEC DI ; Décrémenter DI (a la lettre G) car entre autre DI s’est automatiquement incrémenté MOV BYTE PTR[DI], ‘J’ ; Remplacer ‘G’ par ‘J’

PASSE: MOV DX, OFFSET CHAINE

AFFICHAGE: MOV AH,09H ; le message correcte est affiche: ‘Mr. Jones’

INT 21H ; DOS Code ENDS

END MAIN

(35)

Palindrome

• Comment le faire en utilisant les

instructions de manipulation de chaînes de

caractères ???

(36)

Longueur d’une chaîne de caractères

• Étant donnée une chaîne de caractères - Déjà en mémoire,

- À lire,

Déterminer le nombre de caractères qu’elle contient.

Comment le faire?

(37)

Répétition d’une sous-chaine dans une chaine de caractères

• Étant donnée une chaîne de caractères, on désire savoir combien de fois est

répétée dans cette chaine une sous- chaîne donnée de caractères.

Comment le faire ???

(38)

Donnee SEGMENT

chaine1 db 2000 dup(?) chaine2 db 100 dup(?) Donnee ENDS

CODE SEGMENT

ASSUME CS:CODE, DS:Donnee, ES:Donnee MOV AX, Donnee

MOV DS,AX MOV ES,AX ENTREE:

; initialiser sens du transfert

CLD ; adresse croissante

;initialiser chaine1 avec 200 caractères ‘A’

MOV AL, ‘A’ ; caractères de remplissage MOV CX,2000 ; longueur de la chaîne LEA DI,chaine1 ; DI recoit l’adresse de chaine1 REP STOSB

(39)

; afficher chaine1 MOV CX,2000 LEA SI,chaine1

MOV AH,2 ;fonction DOS affichage d’un caractère CLD

Boucle: LODSB MOV DL,AL INT 21H

LOOP Boucle

; recopier dans chaine2 les 100 premiers caractères de chaine1 CLD

MOV CX,100 LEA SI,chaine1 LEA DI,chaine2 REP MOVSB

(40)

; rechercher un caractère dans une chaîne MOV CX,100

LEA DI,chaine1

MOV AL,’B’ ;caractère à rechercher CLD

REPNE SCASB JNE non_trouve MOV DL,’O’

JMP aff1 non_trouve:

MOV DL,’N’

aff1: MOV AH,2 INT 21H

(41)

; comparer deux chaînes MOV CX,100

LEA SI,chaine1 LEA DI,chaine2 CLD

REPE CMPSB

JNE non_identique MOV DL,’O’

JMP aff2 non_identique:

MOV DL,’N’

aff2:

MOV AH,2 INT 21H MOV AX,4C00H INT 21H

CODE ENDS

END ENTREE

Références

Documents relatifs

Exercice 4: Écrire une fonction qui supprime la première occurrence d’un caractère motif dans une chaîne de caractères source,2. void supp (char motif,

Complétez ce code de sorte à ce qu’il vous permette de découvrir où est stocké le paramètre t de la fonction fct, par rapport à la position en mémoire où le tableau tmp

En C++, les chaînes de caractères sont stockées dans des variables de type string : string prenom = &#34;Robert&#34;; // string pour les chaînes de caractères.. Les chaînes

(e) Écrire une fonction jeu() qui définit une chaine de caractères secrete en utili- sant la fonction combinaison_aleatoire , appelle la fonction saisie , affiche le nombre

Écrire un programme qui permette à l'utilisateur de saisir une chaîne de caractères et qui affiche ensuite la taille de la chaîne entrée. On pourra également afficher de nouveau

Lecture fichier binaire : données stockées dans une chaîne de caractères... 3.2 str : chaîne d’octets (pas

On perd une partie

• Le traitement de liste est souvent réalisé à l’aide de fonctions récursives (il n’existe pas d’équivalent fonctionnel direct des boucles). • Calcul de la longueur