410 likes | 604 Views
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$’
E N D
Traitement des tableaux et chaînes de caractères Une chaîne decaractè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 (?), ‘$’ Djamal Rebaïne
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
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
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
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
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
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
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 Djamal Rebaïne
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
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
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
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: • 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. • À 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
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
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 Djamal Rebaïne
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 Djamal Rebaïne
Recherche dichotomique À faire en classe Djamal Rebaïne
Manipulation de matrices Djamal Rebaïne
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 … Djamal Rebaïne
; 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
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
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
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
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 • Le nombre d’itérations à effectuer doit être rangé dans le registre CX • 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 • Choisir le prefixe et l’instruction. Djamal Rebaïne
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
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. 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 Djamal Rebaïne
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
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
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
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 Djamal Rebaïne
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’à 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 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 Djamal Rebaïne
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 leprogramme sort de cette instruction. A noter ;qu’à chaque itération SI et DI sontautomatiquement 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
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. JNEPASSE ; 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
Palindrome • Comment le faire en utilisant les instructions de manipulation de chaînes de caractères ??? Djamal Rebaïne
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
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
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 Djamal Rebaïne
; 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
; 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
; 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 Djamal Rebaïne