Djamal Rebaïne 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éfinieTamp DB 25 DUP (‘ ‘); chaîne de 25 espaces blancsLigne DB 10 dupl(‘ ‘); ‘*’, 20 dup (?), ‘$’
Djamal Rebaïne 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.
Djamal Rebaï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:
Djamal Rebaïne 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:
Djamal Rebaïne 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.
Djamal Rebaïne 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
-----------------------------------------------
adresse du i ème élément de t
Djamal Rebaïne 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
Djamal Rebaïne 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 x0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19 20 21 22 23 24
Djamal Rebaïne 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]
Djamal Rebaïne 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.
Djamal Rebaïne 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
Djamal Rebaïne 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
Djamal Rebaïne 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
Djamal Rebaïne 14
Tri proc near; trier une suite de caractères dans l’ordre ascendant etiquetri: mov al, [bx]
mov di, 1boucle:
cmp di, cx jg next_bxcmp al, [bx + di] jle next_dixchg al, [bx + di]mov [bx], al
next_di: inc dijmp boucle
next_bx: inc bx
loop etiquetriRetTri proc; fin de la fonction
Djamal Rebaïne 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 21hSCODE ENDS END DEBUT
Djamal Rebaïne 16
Recherche dichotomique
À faire en classe
Djamal Rebaïne 17
Manipulation de matrices
Djamal Rebaïne 18
Transposé d’une matriceExemple; soit la matrice suivante:
M db 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12La 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
…
Djamal Rebaïne 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
Djamal Rebaïne 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
…..
Djamal Rebaïne 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
Djamal Rebaïne 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:
Djamal Rebaïne 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.
Djamal Rebaïne 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
Djamal Rebaïne 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érationsCLD DF=0 STD DF=1
Djamal Rebaïne 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 :
Djamal Rebaïne 27
Djamal Rebaïne 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.
Exemple :
Djamal Rebaïne 29
Djamal Rebaïne 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
SCASB.
Djamal Rebaïne 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,DATAMOV DS,AX ; Initialiser le segment de donnéesMOV ES,AX ; Initialiser le segment ExtraCLD ; DF=0 Auto-incrémentation des pointeurs SI et DIMOV SI,OFFSET DATA_S ; Charger le pointeur sourceMOV DI,OFFSET DATA_D ; Charger le pointeur destinationMOV CX, 20 ; Charger le compteurREP 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ésMOV AH,4CHINT 21H ; DOS
Code ENDS END MAIN
Djamal Rebaïne 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 endsCODE segmentAssume 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’à CX0) ; 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 CX0 JMP SORTIPASSE: MOV DX, OFFSET MESSAGE ; Afficher un message sur écran MOV AH,09H ; le message est ‘Mémoire défectueuse’ INT 21H ; DOSSORTIR:MOV AH,4CH INT 21H ; DOSCODE ENDS END MAIN
Djamal Rebaïne 33
Exemple: REPE CMPSB et CLDTITLE PROG11.asm; Vérifier l’orthographe d’un mot et afficher un messagePILE SEGMENT stack DW 100 DUP (?)PILE ENDSData SEGMENT MOT_EXACT DB ‘CHICOUTIMI’ MOT_TAPEE DB ‘CIHCOUTIMI’ MESSAGE1 DB ‘L’orthographe est juste’ , ‘$’ MESSAGE2 DB ‘L’orthographe est fausse’ , ‘$’DATA ENDSCODE SEGMENT ASSUME CS:code, DS:data, ES: dataMAIN: 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
Djamal Rebaïne 34
Exemple: REPNE SCASB et CLD
TITLE PROG12.asm ; Balayer une chaîne de caractère et Remplacer une lettre particulière par une autrePile segment stack dw 100 dup(?)Pile endsData segment CHAINE DB ‘Mr. Gones’ , ‘$’Data endsCode segmentMAIN: 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
Djamal Rebaïne 35
Palindrome
• Comment le faire en utilisant les instructions de manipulation de chaînes de caractères ???
Djamal Rebaïne 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?
Djamal Rebaïne 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 ???
Djamal Rebaïne 38
Donnee SEGMENT chaine1 db 2000 dup(?) chaine2 db 100 dup(?)Donnee ENDSCODE SEGMENT ASSUME CS:CODE, DS:Donnee, ES:Donnee MOV AX, Donnee MOV DS,AX MOV ES,AXENTREE:
; 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
Djamal Rebaïne 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
Djamal Rebaïne 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
Djamal Rebaïne 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 21HCODE ENDS END ENTREE
Top Related