Introduction à la notion de pointeur
Pile
2/10/2019
note: ce document n'est pas un cours de langage évolué, il introduit les concepts nécessaires à la compréhension de ce qui est utilisé en langage machine pour accéder à un tableau.
Notion de tableau
Un tableau est une zone de mémoire réservée à l'usage exclusif d'un ensemble de données semblables accédées par un rang.
Toutes les données sont du même type, elles sont rangées consécutivement dans cette zone de mémoire les unes derrière les autres, sans espaces.
Par exemple, on a un tableau de 32 données d'un octet, on peut accéder à chacun des octets en précisant où l’élément se situe dans le tableau par son rang. Le premier élément du tableau a le rang 0 et le dernier a le rang (Taille_du_tableau - 1).
En langage évolué
char tab[32]; // déclaration d'un tableau de caractère ... tab[2] = 'A'; // On valorise le troisième octet avec le caractère A
En assembleur
segment byte at: 80-FF ‘RAM0’
tab ds.b 32 ; declaration d'un tableau de caractere
...
segment byte at: 8080-FFFF ‘FLASH’
...
LD A,#$41
LD {tab+2},A ; On valorise le troisième octet avec le caractère A
Notion de pointeur
Par définition un pointeur est une variable contenant une adresse.
En langage évolué (C), un pointeur est caractérisé par le type de la valeur pointé; cela est fait dans sa déclaration.
char* pchar; // pointeur de caractère int* pint; // pointeur d'entier signé unsigned int* puint; //pointeur d'entier non signé char tab[32]; // déclaration d'un tableau de caractère char ch1; // déclaration d'une variable contenant un caractère int in2; // Déclaration d'un entier
En assembleur, un pointeur est une zone mémoire réservée qui contient une adresse ( long ou extended), il ne lui est pas associé de type (ATTENTION DANGER!) et est défini par une étiquette.
Par exemple en se limitant à l'espace d'adressage long.
segment byte at: 80-FF ‘RAM0’
...
pchar ds.w ; pointeur en adressage long (2octets)
pint ds.w ; pointeur en adressage long
...
Référencement
En tant que variable, un pointeur peut être affecté d'une valeur ou on peut en lire sa valeur.
pchar = &ch1; // L'opérateur & produit l'adresse de l'opérande qui est rangé dans le pointeur pchar = &tab[0]; // On valorise pchar avec l'adresse du premier élément du tableau pchar = tab; // Simplification d'écriture tab <=> &tab[0] pchar2 = pchar; // On peut affecter un pointeur avec la valeur d'un autre pointeur de même type pint = (int*) pchar; // Exceptionnellement On peut contourner la protection de type en transtypant
L'opérateur "&" permet d'obtenir l'adresse de l'opérande ( cela s’appelle le référencement).
En assembleur, on charge le pointeur dans un registre d'index (X) et on utilise ensuite l'adressage indexé.
segment byte at: 8080-FFFF ‘FLASH’
...
LDW X,#tab ; on charge X avec l'adresse de tab
LDW pchar,X ; On le range dans la variable pointeur
LDW pint,X ; Et malheureusement on peut ecraser un pointeur d'entier par un pointeur de caractere
Déréférencement
Le pointeur permet d'obtenir la valeur pointée ou de la modifier, pour cela il est défini en C l'opérateur de déréférencement "*".
*pchar = 'A'; *pchar2 = *pchar;
En assembleur c'est très simple.
segment byte at: 8080-FFFF ‘FLASH’
...
LDW X,pchar ; *pchar = 'A'; => on charge X avec la valeur du pointeur
LD A,#$41 ; On charge 'A' dans A
LDW (X),A ; Et on ecrit dans l'emplacement pointe
...
LDW X,pchar ; *pchar2=*pchar => on charge X avec la valeur du pointeur
LD A,(X) ; On charge *pchar
LDW X,pchar2
LD (X),A ; Et on ecrit dans l'emplacement pointe
Incrémentation et décrémentation
Enfin les pointeurs disposent deux opérateurs spécifiques l'incrémentation "++" et la décrémentation "--".
En langage évolué, l'incrémentation augmente la valeur du pointeur de la taille d'un élément pointé et réciproquement la décrémentation diminue la valeur du pointeur de la taille d'un élément pointé.
unsigned int tuint[12]; unsigned int* puint; ... puint = &tuint[6]; puint++; // maintenant puint pointe tuint[7] printf( "%u", *puint); // impression de tuint[7] puint--; // retour sur tuint[6]
En assembleur on va incrémenter l'index après l'avoir chargé de la valeur du pointeur
LDW X,#{tuint+12} ; puint = &tuint[6]; => on charge X avec l'adresse du septieme element
LDW puint,X ; on range X dans le pointeur
...
LDW X,puint ; puint++;
ADDW X,#$0002 ; on incremente X de la longueur d'un element pointe
LDW puint,X ; on range X dans le pointeur