La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Assembleur. Djamal Rebaïne2 Niveaux de programmation circuit logiques 0/1 ---------------------------------------------------------------------------------

Présentations similaires


Présentation au sujet: "Assembleur. Djamal Rebaïne2 Niveaux de programmation circuit logiques 0/1 ---------------------------------------------------------------------------------"— Transcription de la présentation:

1 Assembleur

2 Djamal Rebaïne2 Niveaux de programmation circuit logiques 0/ unité de traitement micro-instructions (UAL, chemins de données) = suite de 0/1 (Unité de commande) micro-pgme = suite de micro-instructions Codop langage machine = suite de 0/ ADD A,20 assembleur = remplacer les codop JZ 13 par des mnémoniques

3 Djamal Rebaïne3 Structure dun programme assembleur 8086 TITLE nom ; donner un nom au programme PILE SEGMENT STACK ; déclaration dun segment de pile ; dont le nom est pile PILE ENDS ; fin de la déclaration de la pile DONNEE SEGMENT ; déclaration dun segment de données qui va ; contenir les variables DONNEE ENDS ; fin de la déclaration de données LECODE SEGMENT ; déclaration du segment de code qui va contenir ; le code Debut: ; étiquette dindication du point dentrée du code LECODE ENDS ; fin de la déclaration du code END Debut ; fin du point dentrée du code

4 Exemple Djamal Rebaïne4 TITLE prog2.asm: Exemple sur ROL, ; pour mettre un commentaire, on écrit ; Pile segment stack ; segemnt de pile dw 100 dup(?) Pile ends DATA segment ; segement de donnée DATA1DW5F97H COMPTEDB? DATA ends CODE segment; segment de code MAIN: ASSUME CS:CODE, DS:DATA MOV AX,DATA MOV DS, AX XOR BL, BL; Mettre BL à 0 (ou bien SUB) MOV DL, 16; rotation 16 fois MOV AX, DATA1 ENCORE: ROL AX, 1; Rotation a gauche (a droite aussi si on préfère) JNC PROCHAIN ; Test si CF=0 INC BL; Si CF = 1, incrémenter le compteur du nombre de 1 PROCHAIN: DEC DL; répéter 16 fois JNZ ENCORE; encore une fois si ce nest pas fini MOV COMPTE, BL; sauvegarder le résultat dans la case mémoire COMPTE MOV AH, 4Ch INT 21h MAIN ENDS END MAIN

5 Pourquoi les segments? À l'origine - Pour pouvoir adresser plus de 64 Ko de mémoire dans un programme car les registres sont sur 16 bits En pratique aujourd'hui - Permet de séparer clairement des zones mémoires selon leur rôle Exemple : la pile ne peut pas être écrasée par des données ou déborder sur des données / code Mais cela est contraignant... Djamal Rebaïne5

6 Suite Adressage sur 20 bits avec 2 registres 2 registres 16 bits : peut coder adresses sur 32 bits Pour uniquement 20 bits (car les bus dadresse sur les processeurs 8086 sont sur 20 bits): - Décale le premier registre de 4 bits et l'additionne au second - Adresse notée A:B - Adresse réelle : A * 16 + B Exemple (les nombres sont en hexa) 3100:27EE correspond à l'adresse EE = 337EE Décaler de 4 bits en binaire revient à décaler d'un chiffre en hexa Djamal Rebaïne6

7 Suite 2 Nous avons 4 segments d'adresses : CS, DS, SS, ES utiliser 2 registres pour adresser des mots mémoires - Le premier est le registre de segment - Le second un registre général On l'appelle l'offset (décalage) Addresse : segment:offset Exemples - CS:IP : adresse de la prochaine instruction à exécuter - DS:SI : adresse d'une donnée - SS:SP : adresse du haut de la pile Djamal Rebaïne7

8 8 Vos programme sources, écrits en assembleur, doivent avoir lextension.asm pour ASseMbler

9 Djamal Rebaïne9 Déclaration de variables Les variables se déclarent de la manière suivante: datas1 db ? ; datas1 est un byte non initialisé datas2 db 0FFh ; datas2 est un byte initialisé à FF (255 en hexadécimal) datas3 dw ? ; datas3 est un word (16 bits) non initialisé datas4 db 5 dup (?) ; datas4 est un tableau de 5 bytes non initialisés datas5 dw 10 dup (15) ; datas5 est un tableau de 10 byte initialisés chacun à 15 De manière générale: DB : 1 byte (8 bits) (Declare Byte) DW: 1 word (16 bits) (Declare Word) DD: 2 words (32 bits) (Declare Double) DF,DP : 6 bytes DQ: 8 bytes (64 bits) DT: 10 bytes Les constantes peuvent être écrites en: - décimal: 1, 2, 3, 123, 45 - hexadécimal : 1h,2h,3h,12h,0Fh,0AD4h (noter la présence du 0 quand le premier chiffre du nombre en hexadécimal commence par une lettre) - binaire : 1b,0b,1010b,111101b

10 Djamal Rebaïne10 Les entrées Sorties en assembleur Pour réaliser les opérations standards (affichage, saisie), le système dexploitation (ici DOS) fournit les fonctions pré-écrites suivantes: Affichage dun caratère: mov DL, A; caractère A est transfére dans DL mov AH, 2; fonction no. 2 int 21h ; appel au DOS Affichage dune chaine de caractères: mov DX, offset chaine; pointe vers ladresse du premier caractère de la chaîne de caractères chaine mov AH, 09h; fonction no. 9 int 21h ; donne la main au DOS Saisie dun caratère: mov AH, 1; fonction no. 1 (avec écho) int 21h ; résultat est mis dans AL

11 Djamal Rebaïne11 Saisie dun caractère mov AH, 7; fonction no. 7 (sans écho) int 21h ; résultat dans AL Arrêt de programme: mov AX, 4C00h; int 21h; À mettre à la fin de chaque fin programme; cest léquivalent du return (0) en C. Ces instructions ont pour effet de retourner au DOS

12 Djamal Rebaïne12 Léquivalent de quelques instructions du langage C en assembleur if then else Assembleur If ax =1 if: CMP AX, 1 bx = 10; JNZ Else else { bx = 0; Then: MOV BX,10 cx = 10; JMP endif } Else: MOV BX,0 MOV CX,10 endif:

13 Djamal Rebaïne13 … Instruction i Si condition alors Instructions j Sinon Instruction m Fin si Instructions k Instruction i Condition ? Instructions j Instructions k VRAI FAUX Instructions m

14 Djamal Rebaïne14 La boucle FOR Assembleur For (k=0; k<=10; k++) MOV BX,0 bx = bx + k; MOV CX,0 For: CMP CX,10 JA Endfor ADD BX,CX INC CX JMP For Endfor:

15 Djamal Rebaïne15 WHILE Assembleur bx = 5 MOV BX,5 while (bx >0) while: CMP BX,0 bx = bx -1; JLE Endwhile DEC BX JMP while Endwhile:

16 En règle générale while (a > b) while: cmp a,b { jle endwhile … … } jmp while … endwhile: … Djamal Rebaïne16

17 Djamal Rebaïne17 SWITCH Assembleur switch (n) { CMP n,1 case 1:....; break; JNE case2 case 2:.....; break; default:.....; JMP endswitch } case2: CMP n,2 JNE default JMP endswitch default: endswitch:

18 Djamal Rebaïne18 Écrire le code de linstruction En assembleur if (a>b) && (c <= d) if: cmp a, b { jng endif } cmp c, d jnle endif endif: Exercice: coder en assembleur les instructions suivantes: 1. if (a >b) || (c > d)) 2. for (i=1; i < 10; i++) { { } }

19 Djamal Rebaïne19 Liste des registres les plus utilisés A. Registres généraux AX (A pour accumulateur): joue le rôle dopérande implicite dans plusieurs opérations: MUL, DIV, INC, etc. CX (C pour compteur): est utilisé pour les boucles (instruction LOOP). DX: utilisé dans les multiplications et divisions comme registre dextension. SI (Source Index): souvent utilisé comme pointeur sur une adresse mémoire (exemple: MOV AL, [SI]). Il est très utilisée avec les instructions de traitement de chaînes de caractères (LODS). DI (Destination Index): pareil que SI (instruction STOS) BP (base pointeur): sert de pointeur sur la base de la pile, et permet datteindre nimporte quel élément de la pile (exemple: MOV AX,[BP+2]). SP (Stack pointer): pointe sur le sommet de la pile; son contenu est automatiquement changé par les instructions PUSH et POP.

20 Djamal Rebaïne20 B. Registres spéciaux IP (Instruction pointeur): contient ladresse de linstruction qui suit celle qui est en cours dexécution. DS (Data Segment): Pointe sur le début du segment qui contient les données CS (Code Segment): Pointe sur le segment qui contient le code du programme. ES (Extended Segment) : permet de pointer sur un segment supplémentaire défini par le programmeur. Il se charge par lintermédiaire de AX, comme pour DS. SS (Stack Segment): segment contenant la pile. C. Registre indicateur : utilisé pour sauvegarder des états particuliers du microprocesseur en référence à la dernière instruction exécutée. Quelques bits seulement de ce registre ont une signification sont nommés: CF (retenue), OF (débordement), etc.

21 Djamal Rebaïne21 La plupart des opérations de calculs donnent des informations sur le résultat dans le registre spécial flags. Les informations possibles sont : CF : 1 si le résultat a donné lieu à une retenue PF : 1 si l'octet de poids faible du résultat à un nombre pair de 1 AF : 1 si le résultat a donné lieu à une retenue sur le 3eme bit ZF : 1 si le résultat est zéro SF : 1 si le résultat est négatif IF : 1 si les interruptions peuvent arriver DF : 0 si la direction est incrémentée, 1 si elle est décrémentée OF : 1 si le résultat ne tient pas dans la destination

22 Djamal Rebaïne22 Format standard dune instruction Label: Mnémonique Opérandes ;commentaire Label: est un identificateur permettant de désigner un endroit dans le code source, soit une instruction, soit une donnée. Si le label est placé avant une instruction, on fait référence à ladresse de cette instruction. Si cest avant une donnée, on fait référence à ladresse de cette instruction. Le label de code doit se terminer par deux points (:). Il sert général comme destinations des instructions ou des retour de début des boucles de répétition. Le label de donnée ne contient pas les deux points(:) à la fin. Il sert dans ce cas là comme identificateur.

23 Djamal Rebaïne23 Mnémonique (des instructions): il sert à identifier une instruction donnée. Quelques instructions de base sont résumées dans la prochaine section. Opérandes: une instruction assembleur peut avoir de 0 à 3 opérandes. Chaque opérande peut être le nom dun registre, un opérande mémoire, une expression constante ou le nom dun périphérique entrée/sortie. Commentaire: précédé du point-virgule (;). Il sert à à ajouter des informations explicatives au sujet du fonctionnement du programme ou de linstruction correspondante.

24 Djamal Rebaïne24 Quelques instructions de base-1 Affectations ; Registres <-- Valeurs MOV AX, 65535; (décimal) MOV Cl, 01101b; (binaire) MOV DH, 0FAh; (hexa) ; Entre registres MOV AX, BX MOV CL, DH ; Entre Registres et Variables MOV CX, variable_de_deux_octets MOV variable_de_un_octet, DL ;Registres <-- Adresses Mémoire Mov AX, Offset variable; AX <- adresse de variable Mov CX, [ 5Ah ]; CX <- valeur à l'adresse 5A en hexa

25 Djamal Rebaïne25 Quelques instructions de base- 2 Arithmétique ; Incrémentation INC AX; AX <- AX + 1 Inc ma_variable ; Décrémentation DEC AX Dec ma_variable ; Addition ADD AX, 5; AX <- AX + 5 ADD BH, toto; BH <- BH + toto Add toto, Cx ; toto <- toto + Cx ; Soustraction SUB AX, 5; AX <- AX – 5 SUB BH, toto; BH <- BH – toto SUB toto, CX ; toto <- toto - CX

26 Djamal Rebaïne26 Quelques instructions de base-3 Logique ; AND bit à bit MOV AH, 0101b; AH <- 5 MOV BH, 1001b; BH <- 9 AND AH, BH; AH <- AH AND BH; AH vaut 0001b, soit 1 ; OR bit à bit MOV AH, 0101b; AH <- 5 MOV BH, 1001b; BH <- 9 Or AH, BH; AH <- AH OR BH; AH vaut 1101b, soit 13 (8+4+1) ; XOR bit à bit MOV AH, 0101b; AH <- 5 MOV BH, 1001b; BH <- 9 XOR Ah, BH; AH <- AH XOR BH; AH vaut 1100b, soit 12 (8+4) ; NOT bit à bit MOV AH, 0101b; AH <- 5 Not AH; AH <- NOT AH; AH vaut 1010b, soit 10 (8+2)

27 Djamal Rebaïne27 Quelques instructions de base-4 Comparaisons : Toutes les comparaisons se font à l'aide de l'instruction CMP. On utilise ensuite les instructions de saut conditionnel: Jump if Equal, JMP if Greater,... Il faut définir des labels (étiquettes): les endroits dans le programme où va sauter si le test est vérifié (comme les GOTO en Fortran). ; Egalité (Jump if Equal) CMP AX, 5 JE label_1 ; Différence (Jump if Not Equal) CMP AX, ma_variable JNE label_2 ;Inférieur, Supérieur, Inf. ou égal, Sup. ou égal ; (Jump if Lower, Greater, Lower or Equal, Greater or Equal) CMP CH, 0 JL label_1 CMP DH, Ah JG label_2 CMP AL, 01001b JLE label_3

28 Djamal Rebaïne28 CMP variable, 65 JGE label_4 Label_1: instructions... Label_2: instructions... Label_3: instructions... Label_4: instructions... ; Saut non conditionnel : JMP label_1 Remarque: CMP est identique à linstruction SUB, mais ne produit pas de résultat. Il positionne cependant les flags. Il permet de sauter à un label qui est à une adresse de 16 bits. Les sauts à un label sont toujours courts (à peu prés de 127octets). Il faut donc prendre garde que ce label puisse être atteint.

29 Djamal Rebaïne29

30 Djamal Rebaïne 30 JZ Saut si zéro. ZF = 1 JNZ JESaut si égal.JNE JC Saut si Retenue (inférieur). CF = 1 JNC JB Saut si inférieur. JNB JNAESaut si ni supérieur ni égal.JAE JSSaut si signe négatif. SF = 1JNS JOSaut si débordement. OF = 1JNO JPE Saut si parité paire. PF = 1JPO JPSaut si parité. JNZ Saut si pas zéro. ZF = 0 JZ JNESaut si différent.JE JNC Saut si pas de retenue. CF = 0 JC JNB Saut si pas inférieur. JB JAESaut si supérieur ou égal.JNAE JNSSaut si aucun signe (positif). SF = 0JS JNOSaut si pas de débordement. OF = 0JO JPO Saut si parité impaire. PF = 0 JPE JNPSaut si pas de parité.JP

31 Un Warm-up Quelques exemples de programmes en assembleur

32 Impression dune chaine de caractères TITLE Mon_premier_programme_assembleur PILE SEGMENT STACK; DW 100 DUP (?) PILE ENDS; DATA SEGMENT; chaine db 'Bienvenue au monde de l',39,'assembleur!','$ ; remarquez le $ pour marquer la fin de la chaîne de caractères DATA ENDS Djamal Rebaïne32

33 Djamal Rebaïne33 MAIN SEGMENT ASSUME DS:DATA, CS:MAIN; pour linstant on fait comme ça sans ; trop se poser de question. DEBUT: MOV AX, DATA ; Initialiser le registre DS pour récupérer ; ladresse du segment de donnée MOV DS, AX MOV DX, offset chaine ; Afficher une chaine de caractères MOV AH, 09h ; fonction 9 pour imprimer sur écran une ;chaine de caratères à partir dune adresse; un $ doit terminer cette ;chaine pour marquer l,arrêt de limpression. INT 21h MOV AX, 4C00h ; léquivalent de return(0) en C-C++ INT 21h; MAIN ENDS END debut

34 Djamal Rebaïne34 Quelques notes utiles La déclaration dune chaîne de caractères est mise en '' '' ou ' '. Le caractère '$' indique la fin dune chaîne de caractères. Son omission implique que les octets en mémoire qui viennent après cette chaîne sont aussi affichés comme des caractères. Lassembleur ne fait pas de différence entre une majuscule et une minuscule dans lécriture de ses instructions et la notation des registres. La directive ASSUME permet d'indiquer à l'assembleur où se situe le segment de données et le segment de code. Puis il s'agit d'initialiser le segment de données à lintérieur du segment de code: MOV AX, nom_du_segment_de_donnees MOV DS, AX

35 Djamal Rebaïne35 Les données sont regroupées dans une zone de la m é moire appelée segment de données, tandis que les instructions se situent dans un autre segment qui est le segment d'instructions. Le registre DS (Data Segment) contient le segment de données, tandis que le registre CS (Code Segment) contient le segment d'instructions. C'est la directive ASSUME qui permet d'indiquer à l'assembleur où se situe le segment de données et le segment de code. Puis il s'agit d'initialiser le segment de données: MOV AX, nom_du_segment_de_donnees MOV DS, AX La même procédure est faite quand viendra le moment d utiliser le segment de pile

36 Maximum entre deux nombres TITLE Exercice 3 ; Écrire un programme en assembleur 8086 qui calcule le maximum ; de deux nombres A et B. PILE SEGMENT STACK; DW 100 DUP (?) PILE ENDS; DATA SEGMENT; n1 db (?) n2 db (?) DATA ENDS MAIN SEGMENT ASSUME DS:DATA, CS:MAIN DEBUT: MOV AX, DATA ; Initialise le registre DS pour récupérer ladresse du segment de MOV DS,AX ; donnée MOV AH, 1h ; Lire un nombre à partir du clavier INT 21h MOV n1, AL MOV AH, 1h ; Lire un deuxième nombre à partir du clavier INT 21h MOV n2, AL Djamal Rebaïne36

37 CMP AL, n1 JG AFFICHER_N2 JL AFFICHER_N1 JMP AFFICHER_EGAL AFFICHER_N1 : MOV DL, N1 ; afficher n1 mov AH, 02h int 21h JMP RETURN AFFICHER_N2 : MOV DL, N2 ; afficher n2 mov AH, 02h int 21h JMP RETURN Djamal Rebaïne37

38 AFFICHER_EGAL : MOV DL, '=' ; afficher "=" mov AH, 02h int 21h JMP RETURN RETURN: MOV AX, 4C00h ; return 0 INT 21h; MAIN ENDS END debut Djamal Rebaïne38

39 Djamal Rebaïne39 Modes dadressage pour accéder aux données Un mode d'adressage est un moyen qui permet au microprocesseur d'avoir accès à une donnée. Cette donnée peut être un nombre quelconque dont on aura besoin dans le programme, un nombre qui se trouve déjà dans un registre, ou encore un nombre qui se trouve écrit quelque part en mémoire. La connaissance des principaux modes d'adressage est nécessaire car elle permet d'écrire les programmes de la façon la plus courte, la plus simple et la plus lisible possible.

40 Djamal Rebaïne40 1. Adressage immédiat : l'opérande est une constante mov ah,10h ; 2. Adressage direct : l'opérande est une case mémoire (registre ds est par défaut) mov al,[10h]; [ds:10h] mov ax,[es:10h]; [ici le segment est ES 3. Adressage basé : l'opérande est une case mémoire dont l'adresse est donnée par BX (Si ou Di, avec ds par défaut) ou bp (avec ss par défaut) mov AH,[BX] ; mov AH,[DS:BX] mov AL,[bp] ; mov AL,[ss:bp] BX,BP,SI,DI peuvent servir de registre pointeur Modes dadressage pour accéder aux données

41 Djamal Rebaïne41 4. Adressage indexé : l'opérande est une case mémoire dont l'adresse est donnée par si ou di (avec ds par défaut, sauf mnemonic spécique) mov ah,[si] ; mov ah,[ds:si] 5. Adressage basé et indexé mov ah,[bx+di] ; mov ah,[ds:bx+di] mov [bp+si],ah ; mov [ss:bp+si],ah Les couples possibles sont BP-DI,BP-SI, BX-DI, BX-SI 6. Adressage basé avec déplacement mov ah,[bx+123h] ; mov ah,[ds:bx+123h]

42 Djamal Rebaïne42 7. Adressage indexé avec déplacement mov ah,[di+123h] ; mov ah,[ds:di+123h] 8. Adressage basé et indexé avec déplacement mov ah,[bx+si+123h] ; mov ah,[ds:bx+si+123h]

43 Remarques 1.Si aucun registre de segment n'est précisé, c'est le segment par défaut qui est utilisé : CS pour IP; DS pour BX et SI; ES pour DI, SS pour BP et SP. 2. Ce nest pas toutes les combinaisons registres de segment / registres d'index qui sont possibles; les combinaisons les plus communément utilisées sont: DS:BX, DS:SI, ES:DI, SS:BP, CS:BX Djamal Rebaïne43

44 Djamal Rebaïne44 Un petit mot sur linstruction de transfert MOV reg, reg (registre à registre) reg, mem (registre à mémoire) mem, reg (mémoire à registre) reg, imed (registre à valeur) mem, imed (mémoire à valeur) NOTE: Pas de transfert de mémoire à mémoire

45 Djamal Rebaïne45 Applications de quelques instructions sur des exemples

46 Djamal Rebaïne46 Compar e Opérand es CFCF ZF Dest. > Src. 00 Dest. = Src. 01 Dest. < Src. 10 Instruction CMP (Comparer)CMP destination, source Linstruction CMP affecte les indicateurs AF, OF, SF, PF, CF et ZF mais seuls CF et ZF sont utilisés. Lopérande destination peut être dans un registre ou dans une mémoire. Lopérande source peut être dans un registre, dans une mémoire, ou en mode immédiat. Les opérandes (destination et source) ne changent pas. DATA1DW235FH … MOV BX, 7888H ; 7888Hh BX MOV CX, 9FFFH CMP BX, CX ; BX < CX CF=1 JNC est exécutée PASSE JNCPASSE ; Note: les contenus de (BX, et CX) ne changent pas après CMP ADDBX, 4000H PASSE:ADDCX, DATA1 ; mais CF est toujours vérifié pour ( ). Pour (=) on utilise ZF. TEMPDB? … MOV AL, TEMP ; TEMP AL CMP AL, 99 ; TEMP = 99?. Avec (SUB AL, 99), la même chose mais 0 AL JZPROCHAIN ; Si ZF=1 (TEMP=99), Saute a PROCHAIN: INCBX ; Sinon incrémente BX PROCHAIN: MOVAH, 4Ch INT21h ; Arrêt du programme

47 Djamal Rebaïne47 TITLE prog1.asm: Exemple sur CMP, Trouver loctet le plus grand parmi 5 notes délèves PILE segment stack dw 100 dup(?) PILE ends ; DATA segment NOTESDB18, 06, 19, 11, 08 PLUS_GDB? DATA ends ; CODE segment main: assume CS:CODE, DS:data ; génération de ladresse du segment de code et de données MOV AX, DATA ; Initialiser le registre DS pour récupérer ladresse du segment de donnée MOV DS, AX MOV CX, 5; compteur de boucle MOV BX, OFFSET NOTES ; BX pointe vers les données NOTES XORAL, AL; Initialise AL à 0; va héberger la plus grande note ENCORE: CMP AL, [BX]; compare la note prochaine à la note la plus élevée JA PROCHAIN; Sauter si AL est encore la note la plus élevée MOV AL, [BX]; sinon AL retient la plus élevée PROCHAIN:INC BX; pointe vers la prochaine note LOOP ENCORE ; CX décrémente jusquà 0 pour sortir de la LOOP MOV PLUS_G, AL; sauvegarde de la note la plus élevée dans PLUS_G ; MOVAH, 4Ch INT21h MAINENDS ENDMAIN

48 Djamal Rebaïne48 Operateur offset: renvoie ladresse à laquelle est située un label de donnée Exemple: …… Bvaldb ? Wval1dw ? Wval2 dd ? … … Si Bval se trouve à ladresse offset (hexa), lopérateur offset renvoie les valeurs suivantes: MOV AX, offset bval ; AX = MOV AX, offset Wval1 ; AX = MOV AX, offset Wval2 ; AX = Noter que lopérateur offset utilise un registre de 16 bits.

49 Djamal Rebaïne49 TITLE prog2.asm: Exemple sur ROL, Trouver le nombre de 1 dans un mot Pile segment stack ; déclaration dun segment de pile – pas nécessaire dans notre cas dw 100 dup(?) Pile ends ; DATA segment DATA1DW5F97H COMPTEDB? DATA ends ; CODE segment MAIN: ASSUME CS:CODE, DS:DATA MOV AX,DATA MOV DS, AX XOR BL, BL; Mettre BL à 0 (ou bien SUB) MOV DL, 16; rotation 16 fois MOV AX, DATA1 ENCORE: ROL AX, 1; Rotation a gauche (a droite aussi si on préfère) JNC PROCHAIN ; Test si CF=0 INC BL; Si CF = 1, incrémenter le compteur du nombre de 1 PROCHAIN: DEC DL; répéter 16 fois JNZ ENCORE; encore une fois si ce nest pas fini MOV COMPTE, BL; sauvegarder le résultat dans la case mémoire COMPTE ; MOV AH, 4Ch INT 21h MAIN ENDS END MAIN

50 Djamal Rebaïne50 ; Segment de donn é es dataSEGMENT chaineDB 'Hello world*' dataENDS ; Segment de code codeSEGMENT ASSUME DS:data, CS:code main:; Initialisation du registre de segment de donn é es MOV AX,data MOV DS,AX ; Chargement de l'adresse de la cha î ne dans BX ; Il s'agit de l'adresse relative au d é but du segment MOV BX,offset chaine ; Initialisation compteur MOV CX,0 Repeter:MOV AL,[BX] CMP AL,*; Test de fin de cha î ne JZ finito INC BX; va de lavant dans la chaine INC CX; Incrémentation compteur JMP repeter finito: ; Retour au DOS MOV AH,4CH INT 21H code ENDS END main; Adresse de lancement

51 Djamal Rebaïne51 Quelques explications sur litération Litération: On peut également transcrire une boucle à laide de linstruction LOOP nécessitant lutilisation implicite du registre CX. MOV CX, unevaleur Boucle: …… ; le corps de la boucle LOOP Boucle Cela signifie que le corps de la boucle est exécuté tant que la valeur de CX nest pas nulle. A chaque itération, CX est décrémenté dune unité. Attention: si CX est nul au premier tour, alors il décrémenté et sa valeur devient 65535, et on va attendre un bon bout de temps pour arriver à la valeur nulle et sortir de la boucle

52 Djamal Rebaïne52 for (cx=5; cx>0; cx--) ax = ax + cx MOV AX,0 MOV CX,5 ; CX est le compteur de boucle for: ADD AX,CX ; fait le calcul LOOP for ; décrémente dune unité CX. ; si CX > 0 fait le saut à for

53 Djamal Rebaïne53 On peut aussi utiliser LOOPE/LOOPZ/LOOPNE/LOOPNZ pour signifier : a.LOOPE (« Loop while Equal ») Monlabel Décrémente CX, puis, si CX <> 0 et ZF = 1, fait un saut à MonLabel. Mnémonique équivalent : LOOPZ b. LOOPNE (« Loop while not Equal ») Monlabel Décrémente CX, puis, si CX <> 0 et ZF = 0, fait un saut à MonLabel.

54 Djamal Rebaïne54 Buffer DB 8 DUP(0) …….. Boucle: MOV AH,1 ;lecture INT 21h MOV [BX], AL; rangement de quon vient de lire INC BX CMP AL, 0Dh; a-t-on lu le retour chariot? LOOPNE Boucle; sinon on continue jusquà CX = 0 ????

55 Djamal Rebaïne55 Décalage et rotation SHL (Shift Left; SHR: shift right): effectue un décalage à gauche des bits. Si le deuxième opérande est une valeur, alors seule la valeur 1 est acceptée. Le bit de poids fort se retrouve dans CF; un 0 est introduit dans le bit de poids faible. SHL AL, 1 Une façon plus élégante consiste à utiliser CL dans son rôle de compteur: MOV CL, 4 SHL AX,CX Pareil pour les instructions SAR, ROR, RCR et leurs équivalents à gauche.

56 Djamal Rebaïne56 Manipulation de données 1.Operateur offset: renvoie ladresse à laquelle est située un label de donnée Exemple: …… Bvaldb ? Wval1dw ? Wval2 dd ? … … Si Bval se trouve à ladresse offset (hexa), lopérateur offset renvoie les valeurs suivantes: MOV AX, offset bval ; AX = MOV AX, offset Wval1 ; AX = MOV AX, offset Wval2 ; AX = Operateur PTR: Permet de passer outre la taille déclarée au départ pour un opérande. Par exemple, … double dd h … MOV AX, double; erreur Mais si on insère la directive WORD PTR, on peut copier le mot de poids faible (5678h) dans AX; cest-à-dire MOV AX WORD PTR double

57 Djamal Rebaïne57 Un mot sur les macros Étant donné que certaines instructions se répètent constamment dans un programme, lécriture de macro-fonctions (ou macros) est un moyen pratique de rendre votre code source plus lisible. Il est possible de choisir pour certaines suites dinstructions un nom qui les représente. Lorsque lassembleur rencontrera ce nom dans votre code source, il le remplacera par les lignes de code quil désigne. Ces lignes forment une « macro ».

58 Djamal Rebaïne58 Les macros, à la différence des procédures et des fonctions, nont aucune signification pour la machine. Seul lassembleur comprend leur signification. Elles ne sont quun artifice mis à la disposition du programmeur pour clarifier son programme. Lorsque lassembleur rencontre le nom dune macro dans votre code, il le remplace par le code de la macro. Tout se passe exactement comme si vous aviez tapé vous-même ce code à la place du nom de la macro. Ainsi, si vous appelez quinze fois une macro dans votre programme, le compilateur écrira quinze fois le code de cette macro. Cest toute la différence avec les fonctions qui ne sont écrites quune seule fois mais peuvent être appelées aussi souvent quon veut à laide dun CALL (quon verra plus tard dans ce cours).

59 Djamal Rebaïne59 Linstruction pour définir une macro est: nom MACRO [paramètres,...] ENDM ; pour End Macro

60 Djamal Rebaïne60 Exemple de macro Toto MACRO p1, p2, p3 –MOV AX, p1 –MOV BX, p2 –MOV CX, p3 ENDM ; et dans dans le segment de code, on peut faire ceci Toto 1, 2, 3 Toto 4, 5, DX À laide de la macro Toto, le programme ci-dessous met dabord 1, 2 et 3 dans AX,BX et CX, respectivement. Ensuite, il met 4, 5 et DX dans AX,BX et CX, respectivement.

61 Djamal Rebaïne61 affiche macro chaine ; sauvegarder le contenu de DX, par ; exemple, en utilisant le registre AX Mov Ax, dx ; sauvegarde de dx dans AX mov dx,offset chaine mov ah, 09h int 21h Mov dx,Ax; restauration de dx endm ;fin de la macro Lexemple suivant sert à écrire un message à lécran.

62 Djamal Rebaïne62 Lassembleur se chargera alors de la remplacer par les instructions comprises entre la première et la dernière ligne de cet exemple, en prenant le soin de remplacer le mot chaine par le message fourni en paramètre. Supposons à présent que lon veuille écrire à lécran le message « Coucou ! Ceci est un essai » et revenir à la ligne à laide de notre macro affiche La syntaxe suivante : affiche Coucou ! Ceci est un essai !, 10, 13, $ 10, 13 est léquivalent de endln en C-C++

63 Djamal Rebaïne63 Présentation dautres exemples

64 Djamal Rebaïne64 TITLE ex3_somme; somme de deux nombres dont la somme est < 10 PILE SEGMENT STACK; déclaration de pile. ; Pour cet exemple, la pile nest pas nécessaire. DW 100 DUP (?) PILE ENDS affiche macro chaine ; macro pour afficher une chaîne de ; caractères MOV DX,offset chaine ; offset renvoie ladresse de début de chaine MOV AH, 09h ; fonction qui affiche une chaîne de caractères INT 21h ENDM; fin de la macro DATA SEGMENT; déclaration de variables val1 db 0 val2 db 0 recup_val1 db 10,13,'veuillez taper la valeur1',10,13,'$' ; 10 et 13=endl du C++ recup_val2 db 10,13,'veuillez taper la valeur2',10,13,'$ aff_resu db 10,13,'la valeur saisie est:',32,'$' ; $ caractère de fin de chaine DATAENDS

65 Djamal Rebaïne65 SCODE SEGMENT ; zone de code ASSUME CS:SCODE, DS:DATA ; génération de ladresse du segment de code et de données DEBUT: ; entrée du code MOV AX, DATA ; Initialiser le registre DS pour récupérer ladresse du MOV DS, AX ; segment de donnée ; à partir dici on peut placer nos lignes de code affiche recup_val1; appel de macro pour afficher un message contenu ; dans recup_val1 MOV AH,1 ; faire une lecture au clavier grâce à la fonction 1 le caractère ; tapé sera placé dans AL INT 21h MOV val1,AL affiche recup_val2; appel de la macro pour afficher un message sur écran MOV AH,1 ; faire une lecture au clavier INT 21h ADD AL,val1 ; AL = AL + val1 MOV val2,AL

66 Djamal Rebaïne66 affiche aff_resu; appel de la macro pour afficher un message sur écran SUB val2,30h ; les valeurs lues tantôt sont en ascii; exemple : ; si on tape les valeurs 1 et 2, ; le programme récupère 31 et 32, valeurs ; hexadécimales des caractères 1 et 2. ; Donc = 63. et 63 nest pas la valeur hexa ; du caractère 3. Sa valeur est 33 ; autrement dit, on doit retirer 30 en hexa ou 48 en ; décimal. MOV AH,2 ; afficher la valeur saisie grâce à la fonction 2 INT 21h ; qui affiche le contenu de DL MOV DL,val2 MOV AH, 4Ch ; on termine le programme avec la fonction MOV AL, 0 ; 4c en hexa. On place une valeur >=0 pour dire INT 21h ; que lexécution sest déroulée correctement. ; Équivalent en c de return 0 SCODE ENDS; fin du segment de code END DEBUT

67 Djamal Rebaïne67 TITLE ex4_max ; détermine et affiche le maximum de deux nombres < 10 ; introduits à travers le clavier PILE SEGMENT STACK DW 100 DUP (?) ; déclaration dune pile de 100 éléments PILE ENDS affiche macro chaine ; à la compilation, lassembleur recopie lensemble ; de instructions de cette macro mov dx,offset chaine ; pointe vers le début de la chaîne chaine mov ah, 09h ; pour afficher une chaîne de caractères à partir de ; ladres de début de chaine int 21h Endm DATA SEGMENT temp db 0; initialisation de temp à 0 val1 db 0 val2 db 0 recup_val1 db 10,13,'veuillez taper la valeur1',10,13,'$' ; 10 et 13=endl du c++ recup_val2 db 10,13,'veuillez taper la valeur2',10,13,'$' aff_resu db 10,13,'le maximun est :',32,'$' ; $ caractère de fin de chaîne DATA ENDS

68 Djamal Rebaïne68 SCODE SEGMENT ASSUME CS:SCODE, DS:DATA ; génération dadresses pour les segments de code et de données DEBUT: ; entrée du code ; Initialiser le registre DS par ladresse du segment de donnée générée par ; la directive ASSUME MOV AX, DATA MOV DS, AX affiche recup_val1 ; permet dafficher le message contenu dans recup_val1 MOV val1,AL MOV AH,1 ;faire une lecture au clavier dun caractère INT 21h affiche recup_val2 ; afficher un message MOV AH,1 ; faire une lecture au clavier int 21h MOV val2,AL CMP AL,val1 JG grand

69 Djamal Rebaïne69 MOV DL,val1 JMP sortie grand: MOV DL,val2 sortie: MOV temp,DL affiche aff_resu ; afficher un message MOV DL temp; ces trois instructions servent à ; afficher le contenu du registre dl MOV AH,2 INT 21h ; Terminer le programme en retournant vers le DOS MOV AH, 4Ch MOV AL, 0 INT 21h SCODE ENDS ; fin du segment de code END DEBUT ; fin de lentrée du code

70 Djamal Rebaïne70 Exemple 5: que fait cette portion de code? MOV BX, offset Alphabet ;alphabet étant une chaîne de caractères MOV CL, 26 MOV [BX], CL ; 26 caractères MOV AL, 65h ; 65h = 'A' dans AL MaBoucle: INC BX MOV [BX], AL ; écrit dans le tableau INC AL ; AL = caractère suivant DEC CL ; affecte lindicateur ZF JNZ MaBoucle ; test lindicateur ZF = 0 XOR BX, BX ; permet de mettre BX à 0 MOV BX,offset alphabet MOV CL,26 Boucle: INC BX MOV DL, alphabet[bx] MOV AH,2 INT 21h MOV DL, ; permet dafficher un blanc MOV AH, 2 INT 21h DEC CL JNZ Boucle

71 Djamal Rebaïne71 Exemple 6 : que fait la portion de code ci-dessous ? MOV BX, offset Chose ; Met ladresse de début du tableau Chose ; dans BX MOV DI, 0 ; Index nul MOV AX, 1 MOV CX, 11 ; 11 éléments dans le tableau MaBoucle: MOV [BX+DI], AX ; écrit dans le tableau SHL AX, 1 ; AX = AX * 2 ADD DI, 2 ; Chose est un tableau de Words -> 2 octets DEC CX JNZ MaBoucle Remarque 1 : Lors de la saisie dune chaîne de caractères au clavier, les deux premiers termes sont réservés: le premier étant la dimension et le deuxième est le nombre effectif de caractères. Remarque 2 : Les registres SI, DI, BX peuvent être utilisés pour les indices de tableaux indifféremment.

72 Djamal Rebaïne72 TITLE sommedetroixnombres ; ce programme fait la somme des trois premiers nombres entiers i.e : PILESEGMENT STACK DW 100 DUP (?) PILEENDS affiche macro chaine; déclaration de macro mov dx,offset chaine mov ah, 09h int 21h endm; fin de la macro DATASEGMENT temp db 0 val1 db 3 val db 0 aff_resu db 10,13,'la somme des termes jusqu a 3 est:',32,'$' ; $ caractère de fin de chaîne DATAENDS

73 Djamal Rebaïne73 SCODESEGMENT ASSUME CS:SCODE, DS:DATA DEBUT:; Initialiser le registre DS MOV AX, DATA MOV DS, AX MOV AX,0 so: CMP AH,val1 JGE psorte INC AH ADD AL,AH JMP so psorte: ADD AL,30h MOV temp,AL affiche aff_resu; affichage à laide de la macro MOV AL,temp MOV DL, AL MOV AH,2 ; afficher la valeur saisie INT 21h ; Terminer le programme MOV AH, 4Ch MOV AL, 0 INT 21h SCODEENDS END DEBUT

74 Djamal Rebaïne74 Exemple 7: Exemple sur ROL, Trouver le nombre de 0 dans un double-mot

75 Djamal Rebaïne75 TITLE programme.asm: Exemple sur ROL, Trouver le nombre de 0 dans un double-mot PILESEGMENT STACK DW 100 DUP (?) PILEENDS DATA SEGMENT DATA1DD0ABCD5F97H COMPTEDB? DATA ENDS CODE SEGMENT ASSUME CS:SCODE, DS:DATA ; Initialiser le registre DS MOV AX, DATA MOV DS, AX XOR CX, CX ; Mettre CX à 0 (ou bien SUB) MOVDX, 1010h ; mettre 16 dans DH et DL; en binaire MOVAX, WORD PTR DATA1; pointer vers le premier mot MOVBX, WORD PTR DATA1 + 2; pointe vers le deuxième mot ENCORE1: ROL AX, 1; Rotation à gauche (à droite aussi si on préfère) JC PROCHAIN1 Test si CF=1 INCCL; Si CF = 0, incrémenter le compteur du nombre de 0 PROCHAIN1: DEC DL; répéter 16 fois JNZ ENCORE1; encore une fois si ce nest pas fini MOV AL, CL; sauvegarder le résultat dans AL, en sortant de la boucle, le contenu de AX ; nous importe peu, donc en écrasant le premier mot nest pas grave ENCORE2: ROL BX, 1; Rotation à gauche JC PROCHAIN2 ; Test si CF=1 INC CH; Si CF = 0, incrémenter le compteur du nombre de 0 PROCHAIN2: DEC DH ; répéter 16 fois JNZ ENCORE2; encore une fois si ce nest pas fini MOV AH, CH; sauvegarder le résultat dans AH. Même remarque quen haut ADDAH, AL; Additionner les nombres de 0 trouvés séparément dans les 2 mots MOV COMPTE, AH; et sauvegarder le résultat dans COMPTE MOV AH, 4Ch ; retour au DOS INT21h Code ENDS ENDMAIN

76 Djamal Rebaïne76 Conversion Minuscule en Majuscule L Hex Binaire A B …………. Y Z5A L Hex Binaire a b …………. y z7A

77 Djamal Rebaïne77 TITLE prog8.asm ; Conversion MINUSCULE MAJUSCULE dun texte PILESEGMENT STACK DW 100 DUP (?) PILE ENDS DATA SEGMENT TEXTE1DBmOn Nom eST REBainE, 13,10, $ TEXTE2 DB21 DUP(?) ; CODE SEGMENT ASSUME CS:SCODE, DS:DATA ; Initialiser le registre DS MOV AX, DATA MOV DS, AX MAIN : MOVSI, OFFSET TEXTE1 ; SI pointe sur le texte original MOVBX, OFFSET TEXTE2; BX pointe sur le texte en MAJUSCULE MOV CX, 21; compteur de boucle ARRIERE:MOV AL, byte ptr t[SI]; prochain caractère CMPAL, 61H; Si < a (61H est le code ASCII de a) JBPASSE; donc pas besoin de convertir CMPAL, 7AH; Si > z (7AH est le code ASCII de z) JAPASSE; donc pas besoin de convertir ANDAL, B; masque le bit 5 pour convertir en MAJUSCULE PASSE:MOV [BX], AL ; sauvegarde le caractère MAJUSCULE INCSI; incrémente le pointeur vers le texte original INCBX; incrémente le pointeur vers le texte en MAJUSCULE LOOP ARRIERE ; Continuer à boucler tant que CX > 0 ; MOV AX, 4C00h INT 21h CODE ENDS ENDMAIN

78 Djamal Rebaïne78 Exemple 9: lit une chaîne de caractères et laffiche à lenvers Programme palin

79 Djamal Rebaïne79 title palin pile segment stack dw 100 dup(?) pile ends data segment reponse db 255 dup('$') enter db 10,13,'$ ; endln en C++ temp db 0 data ends scode segment assume cs:scode, ds:data entree: mov ax,data mov ds,ax ; on écrit le code à partir de là mov dx,offset reponse mov ah,0ah ; lecture à partir du clavier dune chaîne de caractères ; qui se termine dès quon tape le retour chariot (touche entrée) int 21h mov si,dx mov cx,si

80 Djamal Rebaïne80 Deb: cmp BL,0dh; comparer à la touche entrée 13 en ascii car la fin de reponse contient ce caractère je finsearch inc SI mov BL,byte ptr[si] jmp deb finsearch: dec SI inc CX mov DX,offset enter mov AH,09h int 21h fs: cmp SI,CX je fin_s mov DL,byte ptr[si] mov AH,02h int 21h dec SI jmp fs fin_s: mov ax,4c00h int 21h scode ends end Deb

81 Djamal Rebaïne81 Une autre manière de le faire ;debut: xor dx,dx mov DL,[si+1] ; récupération du nombre de caractères lus ; la taille à récupérer est obtenue par lobjet de destination ; car [si+1] na pas de taille spécifique donc obligation de la ; récupérer avec la destination ; ici DL donc récupération de 8bits ; si DX récupération de 16bits ; la destination décide de la taille à récupérer mov si,dx inc si mov cx,1 f_s: cmp si,cx jle fin_s mov dl,reponse[si] mov ah,02h int 21h dec si jmp f_s fin_s: mov ax,4c00h int 21h scode ends end

82 Djamal Rebaïne82 Une troisième manière de le faire debut: xor DX,DX mov DX,reponse[si] ; récuperation du nombre de caractères lus ; la taille à récupérer est obtenue par lobjet de destination ; ici DL donc récupération de 8bits si DX récupération de 16bits ; la destination décide de la taille à récupérer mov SI,DX inc SI mov CX,1 fs: cmp SI,CX jle fins mov DL,reponse[si] mov AH,02h int 21h dec SI jmp fs fins: mov AX,4c00h int 21h scode ends end

83 MUL, IMUL, DIV, IDIV Djamal Rebaïne83 1 seul opérande = REG ou mémoire REG : AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP. Les instructions MUL et IMUL affectent uniquement les flags CF et OF : lorsque le résultat est plus grand que la taille de l'opérande ces flags sont placés à 1, lorsque la taille de l'opérante est ajustée ces flags sont placés à 0. Pour DIV et IDIV les flags ne sont pas définis. MUL - Multiplication non signée : –byte : AX = AL * opérande. –word : (DX AX) = AX * opérande. IMUL - Multiplication signée : –byte : AX = AL * opérande. –word: (DX AX) = AX * opérande. DIV - Division non signée : –byte : AL = AX / opérande; AH = reste (modulo)… –word : AX = (DX AX) / opérande; DX = reste (modulo)… IDIV - Division signée : –byte : AL = AX / opérande; AH = reste (modulo)… –word : AX = (DX AX) / opérande; DX = reste (modulo)…

84 Djamal Rebaïne 84 MULTIPLICATION ET DIVISION SIGNÉE (IMUL / IDIV) reg. (ou mém.) Note: Dans les manuels dIntel IMUL et IDIV pour Integer MULtiplication et DIVision (X et / des nombres entiers) mais au fait il sagit de Multiplication et Division des nombres signées. MULTIPLICATION ET DIVISION SIGNÉE (IMUL / IDIV) reg. (ou mém.) Note: Dans les manuels dIntel IMUL et IDIV pour Integer MULtiplication et DIVision (X et / des nombres entiers) mais au fait il sagit de Multiplication et Division des nombres DIVISION SIGNEENUM. (> ou <)DENOM. (> ou <)QUOTIENTRESTE Octet/OctetAL = Octet CBWReg. ou mem.ALAH Mot/MotAX = Mot CWDReg. ou mem.AXDX Mot/OctetAX = MotReg. ou mem.AL (Erreur si –128>AL>+127)AH DoubleMot/MotDXAX = DoubleMotReg. ou mem.AX (Erreur si –32768>AX>+32767)DX MULTIPLICATION SIGNEE OPERANDE 1 (> ou <) OPERANDE 2 (> ou <) RESULTAT Octet/OctetALReg. ou mem.AX (CF=OF=1 si AH possède une partie du résultat, mais si celui-ci nest pas large pas besoin de AH, le bit de signe est copié aux bits non utilisés de AH et la CPU force CF=OF=0 pour lindiquer) Mot/MotAXReg. ou mem.DXAX(CF=OF=1 si DX possède une partie du résultat, mais si celui-ci nest pas large pas besoin de DX, le bit de signe est copié aux bits non utilisés de DX et la CPU force CF=OF=0 pour lindiquer) Mot/OctetAL = Octet CBWReg. ou mem.DXAX (même remarque que précédemment) DoubleMot/Mot

85 Djamal Rebaïne85 Note sur les multiplications et divisions En base deux, les multiplications et les divisions par des multiples de 2 peuvent (devraient!!!) se faire avec RCL et RCR (Rotate Left/Right with Carry), SAL et SAR (arithmetic left/right shift), ou ROL et ROR (ROtate Left/Right). Schéma de RCL, RCR, SAL, SAR, ROL et ROR pour une rotation de 1 bit:

86 Djamal Rebaïne86 Title exemple pour trouver la moyenne dun ensemble de nombres PILE segment stack dw 100 dup (?) PILE ends DATA segment SIGN_DAT DB +13,-10,+19,+14,-18,-9,+12,-9,+16 MOYENNE DW ? RESTE DW ? DATA ends CODE segment ASSUME CS:CODE, DS:DATA MOV AX,DATA MOV DS,AX MAIN: MOV CX,9 ; Charger le compteur XOR BX,BX ; Mettre a 0 le registre BX, utilisé comme accumulateur MOV SI,OFFSET SIGN_DAT ; SI SIGN_DAT ARRIERE: MOV AL,[SI] ; Un octet de donnée AL CBW ; Extension du signe AX ADD BX,AX ; BX+AX BX INC SI ; SI+1 SI LOOP ARRIERE ; Boucler tant que CX > 0 MOV AL,9 ; Le nombre totales des températures AL CBW ; Extension du signe AX MOV CX,AX ; Sauvegarder le DENOMINATEUR dans CX MOV AX,BX ; LA somme des températures AX ; EXEMPLE DUTILISATION DE IDIV TROUVER LA TEMPERATURE MOYENNE CWD ; Extension du signe AX IDIV CX ; Trouver la moyenne des températures (AX/CX) MOV MOYENNE,AX ; Sauvegarder la moyenne (QUOTIENT) MOV REMAINDER,DX ; Sauvegarder le reste MOV AH,4CH INT 21H ;Retourner au DOS MAIN ENDP END MAIN

87 Djamal Rebaïne Data segment X dw ? A dw ? B dw ? C dw ? D dw ? Data ends Arithmetique proc near MOV AX, 2;établir la constante IMUL A;DX:AX = A*2 MOV BX,DX; MOV CX,AX;BX:AX = A *2 MOV AX,B IMUL C;DX:AX = B*C ADD AX,CX;AX = AX + CX ! faites attention, il peut y avoir une retenue ici ADC DX,BX ;DX:AX = A*2+B*C + la retenue sil y a lieu avec ADC MOV CX, D SUB CX,3 ; cx = D -3 IDIV CX ; AX =(A*2 + B*C)/(D-3) MOV X,AX ; X = ax (A*2 +B*C)/(D-3) stocker le résultat RET Arithmetique endp ; fin de la procedure Expression arithmétique X = (A*2 + B*C)/(D-3)

88 Djamal Rebaïne88 Conversion dune chaine de caractères en une valeur décimale Toute information introduite via le clavier est considérée comme une chaîne de caractères. Ainsi, si on introduit le nombre 827, il sera considéré par lassembleur comme la chaîne de caractères 827. Pour avoir sa valeur numérique, il y a lieu de la convertir suivant lalgorithme suivant:

89 Djamal Rebaïne89 Algorithme de conversion nbre = nombre de caractère lus Nombre = 0 Repeter chiffre = caractère lu nombre = nombre *10+chiffre nbre = nbre -1 Si nbre > 0 aller à repeter

90 Djamal Rebaïne90 Exemple 827 nombre = 0 Chiffre = 8 nombre = nombre * 10 +chiffre =0*10+8 = 8 Chiffre = 2 nombre = nombre * = 8* = 82 Chiffre = 7 Nombre = nombre * = 82*10+7 = 827

91 Djamal Rebaïne91 Pour lire une chaîne de caractères, appeler 21h fonction 0Ah qui installe les caractères tapés dans une zone repérée par DS:DX (buffer déclaré dans DS, le segment de données). La fonction de lecture se termine quand un return (touche entrée) est détecté. Le buffer contient alors les informations suivantes: byte contenu 0 nombre maximum de caractères à lire 1 nombre de caractères lus (sans compter le retour chariot). cette valeur est installée par la fonction. 2 À partir de cette position, on trouve les caractères lus

92 Djamal Rebaïne92 En assembleur, on aura quelque chose comme ci-dessous TITLE caracteresversnombre SPILE SEGMENT STACK DW 100 DUP(?) SPILE ENDS SDATA SEGMENT chaine db 255 dup('$') SDATA ENDS SCODE SEGMENT ASSUME CS:SCODE,DS:SDATA DEBUT: mov AX,sdata mov DS,AX mov DX,offset chaine; permet de se positioner au début de la zone chaine mov AH,0Ah; la fonction 0Ah permet dintroduire une suite de caractères dans le tableau chaine int 21h mov SI,1 mov AX,0 xor CX,CX mov CL,chaine[si] inc SI repeter: mov DX,10 mul DX mov DL,chaine[si] sub DL,48; ou bien 30h, cest pareil. Cest pour rendre le caractère lu comme une valeur numérique mov DH,0 add AX,DX inc SI loop repeter MOV AX,4C00H INT 21H SCODE ENDS END DEBUT

93 Djamal Rebaïne93 Conversion dune valeur décimale en une chaîne de caractères Toute information affichée sur écran est considérée comme un caractère. Ainsi, pour afficher la valeur 827, il faut dans un premier temps avoir tous le chiffres qui la composent; ensuite convertir chacun de ces chiffres en leur équivalent ascii et ensuite passer à laffichage proprement dit. Ainsi, si on veut afficher le 827, on doit dabord récupérer les chiffres 8, 2 et 7 par une succesion de divisions par dix (ces chiffres seront récupérés dans lordre inverse). Ensuite, les convertir en ASCII en ajoutant la valeur 30h, et enfin passer à laffichage proprement dit dans lodre inverse pour avoir le bon ordre. Lalgorithme, récupérant les chiffres dans lordre inverse, peut être comme suit:

94 Djamal Rebaïne94 Algorithme k = 0 do quotient = nombre / 10; reste = nombre % 10; tab[k] = reste; nombre = quotient; k++ while (quotient != 0)

95 Djamal Rebaïne95 ; on suppose que le registre AX contient le nombre à afficher mov result,AX ; déclarer result dans le segment de données mov dx,offset enter ; retour chariot 10, 13 dans le segment de données mov ah,09h int 21h mov ax,result mov SI, offset tabconv ; ne pas oublier de déclarer tabconv dans le segment ; de données mov start, offset tabconv ; start sert à sauvegarder ladresse de début du tableau mov BX,0 mov BL,10 division: ; on suppose que la division se fait sur des nombres de 16 bits div BL cmp AL,0 je fin_div add AH,48 mov byte ptr[si],AH mov AH,0 inc SI jmp division Dans ce programme, les chiffres composant le nombre contenu dans AX est affiché dans le bon ordre

96 Djamal Rebaïne96 fin_div: add AH,48 mov byte ptr[si],AH ;tabconv contient le nombre converti à lenvers xor BX,BX mov BX, offset tabsortie; à declarer dans le segment ; de données xor AX,AX st_bcl: cmp SI,start jb fin_bcl mov AH, byte ptr[si] mov byte ptr[bx], AH dec si inc bx jmp st_bcl

97 Djamal Rebaïne97 fin_bcl: mov byte ptr[bx],10 inc BX mov byte ptr[bx],13 inc BX mov byte ptr[bx],'$' mov dx,offset tabsortie mov ah,09h int 21h MOV AX,4C00H INT 21H SCODE ENDS END DEBUT

98 Djamal Rebaïne98 La directive EQU La directive EQU a un rôle voisin de celui des macros. Elle permet de remplacer un simple mot par dautres plus complexes. Son intérêt est quelle peut être invoquée en plein milieu dune ligne.

99 Djamal Rebaïne99 Quelques exemples Longueur EQU (fin – debut) Message EQU Bonjour messieurs ! Comment allez-vous ?, $ Version EQU 2 Quitter EQU ret Quitter2 EQU int 20h Mettre_dans_AH EQU mov ah Interruption_21h EQU int 21h

100 Djamal Rebaïne100 Les piles

101 Djamal Rebaïne101 Utilité d'une pile Une pile est une zone de mémoire dans laquelle on peut stocker temporairement des registres. Il s'agit d'un moyen d'accéder à des données en les empilant, telle une pile de livre, puis en les dépilant pour les utiliser. Ainsi il est nécessaire de dépiler les valeurs stocker au sommet (les dernières à avoir été stockées) pour pouvoir accéder aux valeurs situées à la base de la pile. En réalité il s'agit d'une zone de mémoire et d'un pointeur qui permet de repérer le sommet de la pile. La pile est de type LIFO (Last In First Out), c'est-à-dire que la première valeur empilée sera la dernière sortie (Si vous empilez des livres, il vous faudra les dépiler en commençant par enlever les livres du dessus. Le premier livre empilé sera donc le dernier sorti!). Les instructions PUSH et POP Les instructions PUSH et POP sont les instructions qui servent à empiler et dépiler les données. - PUSH registre met le contenu du registre dans la pile (empilement) - POP registre récupère le contenu de la pile et le stocke dans le registre (dépilage

102 Djamal Rebaïne102 Ainsi, l'instruction PUSH BX empile le contenu du registre BX, et l'instruction POP AX récupère le contenu du sommet de la pile et le transfère dans AX.

103 Djamal Rebaïne103 Utilisation de la pile sur un exemple Dans l'exemple suivant, que l'on imaginera au milieu d'un programme, on stocke les valeurs contenues dans AX et BX pour pouvoir utiliser ces deux registres, puis une fois l'opération accomplie on remet les valeurs qu'ils contenaient précédemment...

104 Djamal Rebaïne104 PUSH AX PUSH BX MOV AX, [0140] ADD BX, AX MOV [0140], BX POP BX POP AX

105 Djamal Rebaïne105 Les registres SS et SP Les registres SS et SP sont deux registres servant à gérer la pile: SS (Stack Segment, dont la traduction est segment de pile) est un registre 16 bits contenant l'adresse du segment de pile courant. Il doit être initialisé au début du programme SP (Stack Pointer, littéralement pointeur de pile) est le déplacement pour atteindre le sommet de la pile (16 bits de poids faible).

106 Djamal Rebaïne106 SP pointe vers le sommet, c'est-à-dire sur le dernier bloc occupé de la pile. Lorsque l'on ajoute un élément à la pile, l'adresse contenue dans SP est décrémentée de 2 octets (car un emplacement de la pile fait 16 bits de longueur). En effet, lorsque l'on parcourt la pile de la base vers le sommet, les adresse décroissent. Par contre l'instruction POP incrémente de 2 octets (16 bits) la valeur de SP.

107 Djamal Rebaïne107 PUSH: SP <- SP - 2 POP: SP <- SP + 2 Ainsi, lorsque la pile est vide SP pointe sous la pile (la case mémoire en-dessous de la base de la pile) car il n'y a pas de case occupée. Un POP provoquera alors une erreur...

108 Djamal Rebaïne108 Déclarer une pile Pour pouvoir utiliser une pile, il faut la déclarer, c'est-à-dire réserver un espace mémoire pour son utilisation, puis initialiser les registres avec les valeurs correspondant à la base de la pile, ainsi que son sommet (rappel: situé sous la pile lorsque celle-ci est vide). Ainsi pour définir une pile, il s'agit tout d'abord de la déclarer grâce à la directive SEGMENT stack.

109 Djamal Rebaïne109 Déclaration d'une pile Pour utiliser une pile en assembleur, il faut déclarer un segment de pile, et y réserver un espace suffisant. Ensuite, il est nécessaire d'initialiser les registres SS et SP pour pointer sous le sommet de la pile. Voici la déclaration d'une pile de 200 octets : segment_pile SEGMENT stack ; mot clef stack pour pile DW 100 dup (?) ; réserve espace base_pile EQU this word ; etiquette base de la pile segment_pile ENDS Noter le mot clef ``stack '' après la directive SEGMENT, qui indique à l'assembleur qu'il s'agit d'un segment de pile. Afin d'initialiser SP, il faut repérer l'adresse du bas de la pile; c'est le rôle de la ligne base_pile EQU this word (voir figure suivante).

110 Djamal Rebaïne110

111 Djamal Rebaïne111 Suite aux déclarations, il faut écrire une séquence d'initialisations: ASSUME SS:segment_pile ; génère une adresse pour lemplacement de la ; pile MOV AX, segment_pile MOV SS, AX ; initialise le segment de pile MOV SP, base_pile ; copier l'adresse de la base de la pile dans SP Remarquez quil n'est pas possible de faire directement MOV SS, segment_pile car cette instruction n'existe pas!

112 Djamal Rebaïne112 Les procédures-fonctions La notion de procédure - fonctions En langage assembleur, on appelle procédure un sous- programme qui permet d'effectuer un ensemble d'instructions par simple appel de la procédure. Cette notion de sous-programme est généralement appelée fonction dans d'autres langages. Les fonctions et les procédure permettent d'exécuter dans plusieurs parties du programme une série d'instruction, cela permet une simplicité du code et donc une taille de programme minimale. D'autre part, une procédure peut faire appel à elle-même, on parle alors de procédure récursive (il ne faut pas oublier de mettre une condition de sortie au risque sinon de ne pas pouvoir arrêter le programme...).

113 Djamal Rebaïne113

114 Djamal Rebaïne114 La déclaration d'une procédure Etant donnée qu'une procédure est une suite d'instructions, il s'agit de regrouper les instructions composant la procédure entre des mots clés. L'ensemble de cette manipulation est appelée déclaration de procédure. Ces mots clés permettant la déclaration de la procédure sont le une étiquette (qui représente le nom de la fonction) précédant le mot clef PROC marquant le début de la procédure, suivi de near (qui signale que la procédure est située dans le même segment que le programme appelant) et RET désignant la dernière instruction, et enfin le mot-clé ENDP qui annonce la fin de la procédure. Ainsi une déclaration de procédure ressemble à ceci:

115 Djamal Rebaïne115 Etiquette PROC near instruction1 instruction2... RET Etiquette ENDP

116 Djamal Rebaïne116 Appel d'une procédure C'est l'instruction CALL qui permet l'appel d'une procédure. Elle est suivie soit d'une adresse 16 bits, désignant la position du début de la procédure, ou bien du nom de la procédure (celui de l'étiquette qui précède le mot clé PROC).

117 Djamal Rebaïne117 Comment l'appel et la fin de la procédure fonctionnent? Lorsque l'on appelle une procédure, la première adresse de la procédure est stocké dans le registre IP (pointeur dinstruction), le processeur traite ensuite toutes les lignes d'instructions jusqu'à tomber sur le mot clé RET, qui va remettre dans le registre IP l'adresse qui y était stocké avant l'appel par PROC. Cela paraît simple mais le problème provient du fait que les procédures peuvent être imbriqués, c'est-à-dire que de saut en saut, le processeur doit être capable de revenir successivement aux adresses de retour. En fait, à chaque appel de fonction via l'instruction CALL, le processeur empile l'adresse contenue dans le registre IP (il pointe alors sur l'instruction suivant l'instruction CALL) avant de la modifier, à l'appel de l'instruction RET (qui ne prend pas d'arguments) le contenu de la pile est dépilé puis stocké dans le registre IP.

118 Djamal Rebaïne118

119 Djamal Rebaïne119 Voici un exemple dutilisation des procédures aussi simple que possible : ce programme appelle 12 fois une procédure qui écrit un message à lécran et rend la main au DOS. Remarque : Les codes ASCII 10 et 13 représentent respectivement la fin de ligne et le retour chariot. Grâce à eux, on revient à la ligne chaque fois quon a écrit le message.

120 Djamal Rebaïne120 Title les procédures Pile segment stack dw 100 dup (?) Basedepile equ thisword Pile ends data segement message db bonjour, monde!, 10,13, $ data ends code segment assume cs:code, ds:code, ss:pile debut: MOV AX, data MOV DS, AX MOV AX, Pile MOV SS, AX ; initialise le segment de pile MOV SP, basedepile MOV CX,12 boucle: call ecritmessage; appel de procédure LOOP boucle ; décrementer CX de une unité et aller à ; boucle si CX est différent de 0 ; terminer le programme ici par le retour au DOS mov AX, 4C00h INT 21H

121 Djamal Rebaïne121 ecritmessage proc near ;notre fonction mov ah, 09h move dx,offset message int 21h ret ecritmessage endp ; fin de la procédure/fonction code ends ; fin du segment de code end debut ; fin de la porte dentrée

122 Djamal Rebaïne122 Le passage de paramètres Une procédure effectue généralement des actions sur des données qu'on lui fournit, toutefois dans la déclaration de la procédure il n'y a pas de paramètres (dans des langages évolués on place généralement les noms des variables comme paramètres entre des parenthèses, séparés par des virgules). Il existe toutefois deux façons de passer des paramètres à une procédure: Le passage des paramètres par registre: on stocke les valeurs dans les registres utilisés dans la procédure Le passage des paramètres par pile: on stocke les valeurs dans la pile avant d'appeler la procédure, puis on lit le contenu de la pile dans la procédure. Le passage de paramètres par registres C'est une méthode simple pour passer des paramètres: Elle consiste à écrire une procédure en faisant référence à des registres dans les instructions, et de mettre les valeurs que l'on désire dans les registres juste avant lappel de la fonction...

123 Djamal Rebaïne123 Le passage des paramètres par registre Cette manière de procéder est très simple à mettre en oeuvre mais elle est très limité, car on ne peut pas passer autant de paramètres que l'on désire, à cause du nombre limité de registres. On lui préfèrera le passage des paramètres par pile. Le passage de paramètres par pile Cette méthode de passage de paramètres consiste à stocker les valeurs des paramètres dans la pile avant l'appel de procédure (grâce à l'instruction PUSH), puis de lire le contenu de la pile grâce à un registre spécial (BP: Base pointer) qui permet de lire des valeurs dans la pile sans les dépiler, ni modifier le pointeur de sommet de pile (SP).

124 Djamal Rebaïne124 L'appel de la procédure se fera comme suit: PUSH parametre1 ; où parametre1 correspond à une valeur ou une adresse PUSH parametre2 ; où parametre1 correspond à une valeur ou une adresse CALL procedure La procédure commencera par l'instruction suivante: MOV BP, SP ;permet de faire pointer BP sur le sommet de la pile Puis pourra contenir des instructions du type: MOV AX, [BP] ;Stocke la valeur contenue dans le sommet de ;la pile dans AX, sans dépiler MOV BX, [BP+2] ;Stocke la valeur contenue dans le mot suivant de la ;pile dans BX (un mot fait 2 octets), sans dépiler

125 Djamal Rebaïne125 On va écrire une procédure ``SOMME'' qui calcule la somme de 2 nombres naturels de 16 bits. Convenons que les entiers sont passés par les registres AX et BX, et que le résultat sera placé dans le registre AX. La procédure s'écrit alors très simplement : Exemple avec passage par registre

126 Djamal Rebaïne126 SOMME PROC near ; AX <- AX + BX ADD AX, BX RET SOMME ENDP et son appel, par exemple pour ajouter 6 à la variable Truc : MOV AX, 6 MOV BX, Truc CALL SOMME MOV Truc, AX

127 Djamal Rebaïne127 Exemple avec passage par la pile Cette technique met en oeuvre un nouveau registre, BP (Base Pointer), qui permet de lire des valeurs sur la pile sans les dépiler ni modifier SP. Le registre BP permet un mode d'adressage indirect spécial, de la forme : MOV AX, [BP+6]; cette instruction charge le contenu du mot mémoire d'adresse BP+6 dans AX. Ainsi, on lira le sommet de la pile avec : MOV BP, SP ;BP pointe sur le sommet MOV AX, [BP] ;lit sans dépiler et le mot suivant avec : MOV AX, [BP+2] ;2 car 2 octets par mot de pile. L'appel de la procédure ``SOMME2'' avec passage par la pile est : PUSH 6 PUSH Truc CALL SOMME2

128 Djamal Rebaïne128 ; passage de paramètres push AX push BX push CX push DX call soubroutine ; branchement vers la procédure ; Contineur traitement soubroutine proc near mov BP,SP ; pointe vers le sommet de pile move AX, [BP+2] ; acquérir dernier paramètre (DX) sans dépiler; pourquoi? move AX, [BP+4] ; acquérir 3ème paramètre (CX) sans dépiler move AX, [BP+6] ; acquérir 2ème paramètre (BX) sans dépiler move AX, [BP+8] ; acquérir premeir paramètre (AX) sans dépiler ret soubroutine ends

129 Djamal Rebaïne129 Emplacement de sous-programmes En général, les sous-programmes sont mis à la fin du programme principal. Mais, on peut aussi les mettre dans la partie du segment de code. Seulement,il faudra sassurer que la première instruction de code exécutée soit celle du programme principal. Pour cela, il suffit juste de mettre un JMP juste avant la déclaration du sous-programme.

130 Djamal Rebaïne130 Exemple: le calcul de PGCD de plusieurs nombres TITLE PGCDdeplusieursnombres SPILE SEGMENT STACK DW 100 DUP(?) SPILE ENDS SDATA SEGMENT valeurs DB 10,30,40,76,32,52 resultat DB 3 dup(?) tab_sortie db 7 dup('$') tab_conv db 7 dup('$') start dw 0 SDATA ENDS SCODE SEGMENT ASSUME CS:SCODE,DS:SDATA JMP debut PGCD proc near ; déclaration de la fonction repet: MOV AL,CL MOV AH,0 IDIV CH; CMP AH,0 JE dfin MOV CL, CH MOV CH, AH JMP repet dfin: RET ;le PGCD est dans CH PGCD ENDP ;fin de la procédure PGCD

131 Djamal Rebaïne131 DEBUT: mov ax,sdata mov ds,ax mov SI,0; sert dindice tableau MOV BX, 5; compteur de nombre à manipuler mov CH, valeurs[SI] INC SI repeter: CMP BX,0 JE fin mov CL, valeurs[SI] Call PGCD INC SI DEC BX JMP repeter Fin: ; le PGCD de tous les nombres est dans CH

132 Djamal Rebaïne132 xor ax,ax ; tout ce qui suit sert à afficher les chiffres contenus dans le PGCD qui est dans CH mov al,ch mov si, offset tab_conv mov start, offset tab_conv ;start sert à garder le début du tableau mov bx,0 mov bl,10 division: ; on suppose que la division se fait sur des nombre de 16 bits div bl cmp al,0 je fin_div add ah,48 mov byte ptr[si],ah mov ah,0 inc si jmp division fin_div: add ah,48 mov byte ptr[si],ah ; tab_conv contient le nombre converti à lenvers xor bx,bx mov bx, offset tab_sortie xor ax,ax

133 Djamal Rebaïne133 st_bcl: cmp si,start jb fin_bcl mov ah, byte ptr[si] mov byte ptr[bx], ah dec si inc bx jmp st_bcl fin_bcl: mov byte ptr[bx],10 inc bx mov byte ptr[bx],13 inc bx mov byte ptr[bx],'$' mov dx,offset tab_sortie mov ah,09h int 21h Sortie: MOV AX, 4c00h; Int 21h SCODE ENDS END DEBUT

134 Djamal Rebaïne134 Le compilateur se chargera alors de la remplacer par les instructions comprises entre la première et la dernière ligne de cet exemple, en prenant le soin de remplacer le mot chaine par le message fourni en paramètre. Supposons à présent que lon veuille écrire à lécran le message « Je suis bien content » et revenir à la ligne à laide de notre macro affiche La syntaxe suivante : affiche Coucou ! Ceci est un essai !, 10, 13, $

135 Djamal Rebaïne135 Traitement des tableaux et chaînes de caractères Une chaîne de caractères ASCII est constiuée dune 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 à laide 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 caratères de valeur non définie Tamp DB 25 DUP ( ); chaîne de 25 espaces blancs Ligne DB 10 dupl( ); *, 20 dup (?), $

136 Djamal Rebaïne136 En assembleur, il nexiste pas de distinction entre une chaîne de caractères et un tableau de caractères. Ainsi, il est posible daccé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 dune chaîne.

137 Djamal Rebaïne137 Exemple de parcours séquentiel dune chaîne ;AX nombre de lettres L ; SI registre dindex 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:

138 Djamal Rebaïne138 Autre possibilité: utiliser SI comme pointeur lea SI,zone; SI contient ladresse 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:

139 Djamal Rebaïne139 Les vecteurs Vecteur dentiers Le principe est le même pour un vecteur dentiers où chaque élément est stocké sur un entier. Pour un vecteur dentiers stockés sur deux octets nous devons tenir compte de la longueur dun é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.

140 Djamal Rebaïne140 Implémentation en mémoire (un élément est sur 2 octets) Indice Déplacement | | t | x x | x x | x x | x x | Fonction dindicage: adresse de début de t + i * longueur dun élément de t adresse du i ème élément de t

141 Djamal Rebaïne141 Exemple: ; AX t[i] mov SI,i ADD SI,SI; SI = SI * 2 (longeur dun élément) MOV AX, t[SI] ; t[i] AX MOV SI, i ADD SI, SI MOV t[SI], AX

142 Djamal Rebaïne142 Tableau à deux dimensions La fonction dindicage 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

143 Djamal Rebaïne143 Soit n et m 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 dun élément de t (sélection de la ligne) + j * longueur dun élément de t (sélection de la colonne) = addresse de lélément t[i][j]

144 Djamal Rebaïne144 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, b ; 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

145 Djamal Rebaïne145 Les instructions de traitement de chaînes de caractères Les instructions disponibles pour effectuer des traitement de chaines sont comme ci-desous. Ce jeu dinstructions 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:

146 Djamal Rebaïne146 1.Le flag de direction du registre des codes-conditions indique le sens de traitement de chaines: sil 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 linstruction CLD initialise le flag de direction à 0 que linstruction STD le positionne à 1 2.Le nombre ditérations à effectuer doit être rangé dans le registre CX 3.Ladresse de départ de la chaîne donnée est dans lensemble des registres DS et SI. Ladresse 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 linstruction.

147 Djamal Rebaïne147 Les préfixes disponibles sont: REP ou REPZ répète lopération du nombre de fois contenu dans CX REPE ou REPZ répète lopération tant que lon a légalité et que CX est différent de 0 REPNE ou REPNZ répète lopération tant que lon a différence et que CX est différent de 0

148 Djamal Rebaïne148 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. InstructionMnémoniqueDestinationSourcePréfixe Dep. Ch. Oct.MOVSBES:DIDS:SIREP Dep. Ch. MotMOVSWES:DIDS:SIREP Sav. Ch. Oct.STOSBES:SIALREP Sav. Ch. MotSTOSWES:SIAXREP Chg. Ch. Oct.LODSBALDS:SI/ Chg. Ch. MotLODSWAXDS:SI/ Cmp. Ch. Oct.CMPSBES:DIDS:SIREPE/REPNE Cmp. Ch. MotCMPSWES:DIDS:SIREPE/REPNE Scn. Ch. Oct.SCASBES:DIALREPE/REPNE Scn. Ch. Oct.SCASWES:DIAXREPE/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

149 Djamal Rebaïne149 Les instructions de gestion des chaînes doctets a) linstruction MOVSB (« Move String Byte ») Syntaxe : MOVSB Description : Copie loctet adressé par DS:SI à ladresse 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 doctets à copier doit être transmis dans CX de même que pour un LOOP. Exemple :

150 Djamal Rebaïne150

151 Djamal Rebaïne151 b) linstruction SCASB (« Scan String Byte ») Syntaxe : SCASB Description : Compare loctet 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é. Remarques : 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 doctets à comparer doit être transmis dans CX. La boucle ainsi créée sarrê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, cest-à-dire jusquà ce que AL et le caractère adressé par ES:DI diffèrent, utiliser REPNE ou REPNZ. Exemple :

152 Djamal Rebaïne152

153 Djamal Rebaïne153 c) linstruction LODSB (« Load String Byte ») Syntaxe : LODSB Description : Charge dans AL loctet adressé par DS:SI. Si DF = 0, alors SI est ensuite incrémenté, sinon il est décrémenté. Remarque : Possibilité dutiliser les préfixes de répétition, de même que pour MOVSB. d) linstruction STOSB (« Store String Byte ») Syntaxe : STOSB Description : Stocke le contenu de AL dans loctet adressé par ES:DI. Si DF = 0, alors DI est ensuite incrémenté, sinon il est décrémenté. Remarque : Possibilité dutiliser les préfixes de répétition, de même que pour LODSB. e) linstruction CMPSB (« Compare String Byte ») Syntaxe : CMPSB Description : Compare loctet 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é dutiliser les préfixes de répétition, de même que pour SCASB.

154 Djamal Rebaïne154 Exemple: REP MOVSB et CLD TITLE PROG3_12.asm;Transfert un bloc de 20 octets dans la 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 qua chaque itération SI et DI sont ; automatiquement incrémentés MOV AH,4CH INT 21H ; DOS Code ENDS END MAIN

155 Djamal Rebaïne155 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(?) MESSAGEDB 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 qua 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 cest différent mémoire défectueuse LOOP ENCORE; continue jusqua 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

156 Djamal Rebaïne156 Exemple: REPE CMPSB et CLD TITLE PROG11.asm; Vérifier lorthographe dun 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 Lorthographe est juste, $ MESSAGE2 DB Lorthographe 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 cest 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

157 Djamal Rebaïne157 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 CHAINEDB 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 jusqua 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 sest 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

158 Djamal Rebaïne158 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 de 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 ladresse de chaine1 REP STOSB

159 Djamal Rebaïne159 ; afficher chaine1 MOV CX,2000 LEA SI,chaine1 MOV AH,2 ;fonction DOS affichage dun caractère Boucle: LODSB MOV DL,AL INT 21H LOOP Boucle ; recopier dans chaine2 les 100 premiers caractères de chaine1 MOV CX,100 LEA SI,chaine1 LEA DI,chaine2 REP MOVSB

160 Djamal Rebaïne160 ; rechercher un caractère dans une chaîne MOV CX,100 LEA DI,chaine1 MOV AL,B ;caractère à rechercher REPNE SCASB JNE non_trouve MOV DL,O JMP aff1 non_trouve: MOV DL,N aff1: MOV AH,2 INT 21H

161 Djamal Rebaïne161 ; comparer deux chaînes MOV CX,100 LEA SI,chaine1 LEA DI,chaine2 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

162 Djamal Rebaïne162 La récursivité Définition: Une procédure est dite récursive si, et seulement si, elle fait appel à elle-même, soit directement soit indirectement

163 Djamal Rebaïne163 Fonctionnement dune fonction récursive Création dune pile pour la sauvegarde entre autres des paramètres dappels de la procédure et la ladresse de retour.

164 Djamal Rebaïne164 Calculer le factoriel de n, noté n! Le problème est: Calculer le factoriel d'un nombre entier donné en entrée. En entrée: Nous avons n nombre entiers qui sont plus grands ou égaux à 0. Sortie: Nous avons un nombre entier qui représente le factoriel de n.

165 Djamal Rebaïne165 Fonction principale entier n nfact lire n si (n < 0) alors écrire entrée négative: n sinon nfact factoriel(n) écrire la factorielle de n est nfact où factoriel satisfait le prototype entier factoriel(entier)

166 Djamal Rebaïne166 Fonction factoriel int factoriel(entier n) { si (n < 1) retourner 1 retourner n * factoriel(n-1) }

167 Djamal Rebaïne167 Comment le faire en assembleur? On a besoin dune pile! En effet, à chaque appel récursif, la valeur du paramètre n est sauvegardée dans la pile de travail. Ce processus dempilement est répété jusquà ce que le paramètre actuel (de lappel) n atteigne la valeur un. Cela correspond à la fin de lexécution de la fonction appelante. Ensuite, commence le dépilement, et lexécution de la prochaine instruction de la fonction appelante est entamée. Ce processus de dépilement est répété jusquà ce quon atteigne la valeur de départ du paramètre n.

168 Djamal Rebaïne168 Cela se traduit par le programme assembleur suivant TITLE factoriel PILE segment stack dw 100 dup(?) Basdepile equ this word PILE ends Data segment N dw 4 fact dw ? Data ends Code segment assume CS:code, DS:Data, SS:Pile Debut: MOV AX,Data MOV DS,AX MOV AX,Pile MOV SS, AX ; initialise le segment de pile MOV SP, basdepile ; copier l'adresse de la base de la pile dans SP mov BX,n; sauvegarde la valeur de n mov ax,bx call factoriel Fin: pop AX; le résultat calculé par la fonction factoriel est dans AX mov fact, AX mov AX,4c00h int 21h

169 Djamal Rebaïne169 factoriel proc near push ax Continuer: CMP AX,1 JLE dépiler; déplier jusquà ce n = 1 dec AX push AX JMP continuer Depiler: POP AX POP CX mul CX Push AX CMP BX,CX Ja depiler ret factoriel endp ; fin de la procédure code ends end debut ; fin du programme code


Télécharger ppt "Assembleur. Djamal Rebaïne2 Niveaux de programmation circuit logiques 0/1 ---------------------------------------------------------------------------------"

Présentations similaires


Annonces Google