Tous les processeurs modernes comportent une unité mémoire (MMU) qui permet de manipuler des adresses virtuelles, ie. de faire un renommage, transparent pour l'utilisateur, entre les adresses virtuelles du programme et les adresses réelles en mémoire.
Cela permet à chaque programme de choisir ses adresses indépendamment des autres programmes (qui peuvent être exécutés en même temps sur la même machine avec les mêmes adresses virtuelles mais des adresses réelles différentes).
Du point de vue de l'utilisateur, la mémoire est un (grand) tableau dont les indices sont les adresses. Généralement, la plus petite unité adressable dans la mémoire est l'octet (8 bits) ou byte. Mais la taille naturelle des entiers manipulés par le processeur, c'est à dire la taille des entiers contenus dans les registres, mais aussi la taille des adresses, est plus grande, typiquement 32 ou 64 bits (soit 4 ou 8 octets). On notera donc que sur un processeur 32 bits, les adresses des mots mémoires successifs sont croissantes de 4 en 4. Les accès à la mémoire non-alignés, c'est à dire ceux qui ne correspondent pas à des adresses multiples de la taille en octets de la valeur accédée, sont soit interdits soit pénalisés. Par exemple, pour le MIPS, l'instruction générique de lecture d'un mot en mémoire lw exige des adresses multiples de 4.
La mémoire (virtuelle) d'un programme est partagée en zones. Il s'agit là, plus que d'une convention, d'un principe du système d'exploitation (ici Unix), organisateur de l'exécution des programmes.
Des adresses hautes vers les adresses basses :
Stack
↓
↑
Données
allouées dynamiquement
Données statiques
modifiables
Texte (programme)
non écrivable
Réservé au système
On distingue donc (du haut vers le bas) :
•La pile (Stack). Il s'agit d'une zone mémoire utilisées par les fonctions du programme entre autres pour leurs variables locales.
•Un trou qui va de la fin de la pile au début de zone suivante. Ce trou est énorme et ne correspond à aucune case mémoire valide. Si l'on tente d'y accéder, le système d'exploitation déclenchera une erreur. Toutefois, l'accès illégal peut être provoqué par un accès un peu en deçà de la limite basse de la zone allouée initialement pour la pile. Le système d'exploitation pourra alors réagir en augmentant la zone mémoire dédiée à la pile et ne pas faire échouer le programme. Ainsi l'espace de la pile peut croître dynamiquement en fonction des besoins du programme.
•Les données allouées dynamiquement par le programme. Cette zone est étendue explicitement (vers le haut cette fois) par le programme, cf. l'allocation explicite new en Pascal et Java, malloc en C, allocation implicite de Caml.
•Les données allouées statiquement par le programme. C'est le compilateur qui alloue cette zone car contrairement à la précédente, sa taille est connue lors de la compilation. Typiquement on y trouvera les variables globales du programme.
•Le texte, c'est à dire le code du programme. On ne peut pas écrire dans cette zone. Essentiellement, cela accélère la lecture en mémoire des instructions à travers un cache, qui est une mémoire d'accès rapide contenant une copie d'une partie de la « vraie » mémoire. En effet, le contenu d'une case du cache ne peut alors jamais différer du contenu de la case mémoire cachée.
Le simulateur SPIM, va émuler cette vision de la mémoire (dans une zone par lui allouée). Dans une machine sans mémoire virtuelle on a généralement une organisation similaire, mais sans la protection contre l'écriture et la lecture dans les zones interdites.