COURS N° 3 - Les registres du microprocesseur

COURS N° 4 - Adressages mémoire

Cours n° 5 - Les chaînes de caractères

Ce chapitre vous montrera, de façon pratique, comment utiliser les différents modes d'adressage pour accéder à la mémoire vive.

Avant de commencer à travailler, je vous invite à lire le document suivant : La mémoire vive

L'exemple de code ci-dessous aura pour effet de remplacer certaines lettres du message "Hello World !" par le caractère étoile "*" code ASCII : 2Ah (42). La dernière boîte de message devrait faire apparaître le message sous la forme suivante : "*ell* *orld*!".



.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE

INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDE \masm32\include\user32.inc

INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\user32.lib

MesDonnees SEGMENT 'DATA'

Msg DB "Hello World !",0
TitleMsg DB "MsgBox.asm",0

MesDonnees ENDS

MonCode SEGMENT 'CODE'

    Main:

        ;
        ;Adressage indirect en utilisant le registre edx.
        ;Le code suivant change le caractère numéro 6
        ;(le septième) c'est-à-dire le "W" par le caractère étoile : "*".
        ;Le message affiché devrait être celui-là : "Hello *orld !".
        ;
        
        ; Adresse offset dans le registre edx.
        mov edx, OFFSET Msg

        ;Le registre al contient le caractère étoile.
        mov al, "*"

        ;Ajoute le décalage de 6 caractères.
        ;Ce qui me permet d'obtenir l'adresse offset de la lettre "W".
        add edx, 6

        ;Copie le caractère étoile à l'emplacement mémoire pointé par le registre edx.
        mov [edx], al

        ;
        ;Affichage du résultat
        ;
        push MB_OK ;Bouton Ok.
        push OFFSET TitleMsg ;Titre.
        push OFFSET Msg ;Message.
        push NULL ;hwnd dans ce cas 0.
        call MessageBox
        
        ;-----------------------------------------------------------------

        ;
        ;Adressage indirect indéxé en utilisant le registre ecx.
        ;Le caractère "o" de "Hello" sera remplacé par le caractère "*".
        ;Le message affiché devrait être celui-là : "Hell* *orld !".
        ;
        
        ;Adresse offset dans le registre ecx.
        mov ecx, OFFSET Msg

        ;Le registre al contient le caractère étoile.
        mov al, "*"

        ;Place le numéro du caractère devant changé : "o" de "Hello" dans le registre edx.
        mov edx, 4

        ;Copie le caractère étoile à l'emplacement mémoire pointé par les registres ecx et edx.
        mov [ecx+edx], al

        ;Fait le même travail que l'instruction précédente.
        ;C'est exactement la même instruction.
        ;Ce codage est montré uniquement pour être complet.
        ;Elle ne modifie en rien, le résultat.
        ;Cette notation "edx*1" sert uniquement lorsque l'on veut traiter
        ;des tableaux de type : Word, Dword.
        ;Le nombre (scale) placé après l'opérateur de multiplication doit être
        ;un multiple de la donnée que nous sommes en train de traiter.
        ;Pour un Byte c'est : 1, pour un Word c'est : 2 et pour un Dword c'est : 4.
        mov [ecx+edx * 1], al

        ;
        ;Affichage du résultat
        ;
        push MB_OK ;Bouton Ok.
        push offset TitleMsg ;Titre.
        push offset Msg ;Message.
        push NULL ;hwnd dans ce cas 0.
        call MessageBox
        
        ;-----------------------------------------------------------------

        ;
        ;Adressage indirect indéxé + décalage en utilisant le registre ebx.
        ;Le dernier espace " " de "Hello World !" sera remplacé par "*".
        ;Le message affiché devrait être celui-là : "Hell* *orld*!".
        ;
        
        ;Adresse offset dans le registre ebx.
        mov ebx, OFFSET Msg

        ;Le registre al contient le caractère étoile.
        mov al, "*"

        ;Place le numéro du caractère devant changé : " " de "World !" dans le registre edx.
        mov edx, 4

        ;Copie le caractère étoile à l'emplacement mémoire pointé par les registres ebx+edx+7 :
        ;Base+Index+Offset.
        mov [ebx+edx+7], al

        ;
        ;Affichage du résultat
        ;
        push MB_OK ;Bouton Ok.
        push OFFSET TitleMsg ;Titre.
        push OFFSET Msg ;Message.
        push NULL ;hwnd dans ce cas 0.
        call MessageBox
        
        ;-----------------------------------------------------------------

        ;Adressage direct.
        ;Le caractère "H" de "Hello World !" sera remplacé par "*".
        ;Le message affiché devrait être celui-là : "*ell* *orld*!".
        ;Il faut toujours préfixer le registre de segment DS suivi des deux points
        ;pour utiliser l'adressage direct.
        ;
        
        ;Le registre al contient le caractère étoile.
        mov al, "*"

        ;Copie le caractère étoile à l'adresse offset de 00404000h
        mov ds:[00404000h], al

        ;
        ;Affichage du résultat
        ;
        push MB_OK ;Bouton Ok.
        push OFFSET TitleMsg ;Titre.
        push OFFSET Msg ;Message.
        push NULL ;hwnd dans ce cas 0.
        call MessageBox
        
        ;
        ;Fin du programme
        ;
        push 0h
        call ExitProcess

MonCode ENDS

END Main



Notes :

Le mode d'adressage direct ne peut pas être utilisé par le développeur. Il faut laisser l'éditeur de lien (LINK.exe) faire le calcul des adresses. Ce mode n'est montré que pour être complet et pédagogique. Si, par aventure, le développeur utilise cette façon de faire, il s'exposerait à de serieuses complications de maintenance !!!

L'usage d'une adresse offset calculée par le programmeur (adressage direct) ne peut être utilisée que sous le format suivant : RegistreSegment:[AdresseOffset]. Tel que montré dans l'exemple : ds:[00403000h]. Les crochets qui encadrent l'adresse offset sont obligatoires. Ils indiquent le déréférencement et permet d'entrer à l'intérieur de la case mémoire. Considérez les comme une clef qui ouvre une porte d'une pièce.

Avec le mode d'adressage indirect (usage des registres) il n'est pas nécessaire de préfixer l'adresse offset par un registre de segment. Car tous les registres sont relatifs aux registres de segments. Le cours consacré aux registres indique cette particularité.


Vous avez pu découvrir par ces différents exemples comment accéder à la mémoire.

Le prochain cours, qui traitera des instructions de chaînes, nous permettra de voir de façon plus approfondie le traitement des cases mémoires en lecture et écriture. Le traitement des chaînes constitue une part importante de la programmation assembleur mais également de tout système de développement tel que : C++, VB, JAVA etc...

Eh oui ! Car afficher une valeur numérique à l'écran nécessite que l'on utilise un programme qui permet de la convertir en une chaîne de caractères ASCII.

A l'issue de l'ensemble des cours relatifs aux chaînes on aura constitué un fichier source regroupant l'ensemble des fonctionnalités de traitement des chaînes de caractères ASCII.

Je viens de parler de chaînes ASCII mais il faut savoir qu'en assembleur, une chaîne n'est pas forcément une chaîne de caractères ASCII. Une chaîne n'est ni plus ni moins qu'une suite d'octets, de words ou de dwords. Pour être clair, tout tableau contenant n'importe quel type de donnée.

Afin d'enlever toute ambiguïté, lorsque je parlerai de chaîne se sera de chaîne ASCII. Pour tout autre type de donnée se sera le terme tableau que j'emploierai.


Questions :

  1. Est-ce que l'instruction suivante est correcte ?
    mov al, [00400000h]
  2. Quel est le maximum de mémoire que l'on peut adresser ?
  3. Si je copie un caractère situé à l'emplacement 00408000h, est-ce que je peux utiliser la suite d'instructions suivantes ?
    mov eax, 00408000h
    mov cl, [eax]
  4. Quel est la directive qui permet au lieur de calculer l'adresse offset d'une donnée ?
  5. En mode 32 bits, peut-on placer une adresse offset dans le registre bx ?
  6. Si j'exécute les instuctions suivantes, que se passe-t-il ?
    Msg DB "Bonjour, homme du monde."

    mov eax, OFFSET Msg
    mov edx, [eax]
  7. L'instruction suivante est-elle valide ?
    mov al, [ebx+edx+ecx]

Réponses