CODINGDEMONIAK ★ COURS d'ASSEMBLEUR par DEMONIAK (Mercredi 02 février 2005) ★

Partie 2 : La mémoire

Nous allons aborder dans ce chapitre, la gestion de la mémoire par le microprocesseur.
Ce qu'il est important d'avoir à l'esprit, c'est que le microprocesseur a besoin de mémoire pour travailler : c'est dans la mémoire qu'il va lire son programme, écrire des valeurs...

En gros, on peut considérer la mémoire comme une grande armoire, avec pleins de tiroirs.
Chaque tiroir correspond à une case de la mémoire, ou encore un octet (un groupement de 8 bits, comme nous l'avons vu dans le chapitre précédent). Voila, donc, notre microprocesseur se sert d'une grande armoire pour ranger tout pleins d'octets dans des tiroirs !

Ca peut paraître rigolo, mais il est très important d'avoir cette notion en tête pour la suite des choses...

Ensuite, pour faciliter les choses, chaque tiroir de l'armoire est numéroté, en commençant par 0.
On pourra ainsi demander à notre microprocesseur de nous donner la valeur stockée dans le tiroir 3454, par exemple...

Notre microprocesseur à besoin d'un programme pour fonctionner. C'est un peu lorsque quand on se trouve devant l'écran du CPC, il faut écrire un programme pour lui faire faire quelque chose !
Et donc, la mémoire sert à stocker le programme du microprocesseur. Nous verrons plus tard que le microprocesseur utilise des instructions particulières, qui peuvent être décrites par un octet.
Ainsi donc, chaque instruction est rangée dans une case mémoire particulière, et le microprocesseur les exécutera les unes à la suite des autres.

C'est pour cela qu'il est intéressant de connaître l'adresse d'une case mémoire.

Bon, faisons un petit exemple en basic...
Sous le basic, il existe deux instructions permettant l'accès à la mémoire :
PEEK qui permet de lire une case mémoire, et POKE qui permet d'écrire dans une case mémoire.
Ok, si nous tapons :

PRINT PEEK(40960)

normalement, nous avons la valeur 0 qui s'affiche.
Maintenant, tapons

POKE 40960,12

Puis de nouveau:

PRINT PEEK(40960)

Maintenant, c'est bien 12 qui s'affiche.
Magique non ?
Non, c'est tout simplement parce que nous avons écrit dans la RAM, que nous pouvons relire notre valeur.

La ROM et la RAM, c'est quoi donc ?
En effet, il existe en gros deux types de mémoire différente : la ROM et la RAM.
ROM signifie Read Only Memory (mémoire à lecture seule) et RAM signifie Random Acces Memory (mémoire à accès aléatoire).

L'accès aléatoire signifie que l'on peut à la fois lire et écrire.
Le microprocesseur ne distingue pas la mémoire ROM ou RAM.

Nous allons maintenant voir comment notre microprocesseur, le Z80 (c'est son nom !) peut lire et écrire dans la mémoire.

Disons qu'il dispose d'un compteur spécial, qui contient le numéro de case mémoire à lire ou écrire.
Ce compteur est représenté par 16 bits, donc, sa valeur peut évoluer de 0 à 65535 (ou de #0000 à #FFFF, en hexa !).

On dit aussi que le processeur peut "adresser" 65535 cases mémoires, ou adresses mémoires, ou encore octets.

Voila, nous savons donc maintenant que le microprocesseur Z80 est capable d'accéder à 65536 octets de mémoire différents.

Pour simplifier, nous dirons qu'il accède à 64 Kilo-octets de mémoire.
Mais, 65536, ça fait plutôt 65 Kilo-octets et des poussieres, non ?
Et bien, les informaticiens ayant plutôt un esprit tordu, on a décidé que le Kilo-Octet ne faisait pas 1000 Octets, mais 1024 Octets.

(En fait, ils ne sont pas si tordu que ça, 1024 étant tout simplement 2 à la puissance 10, et comme tout en informatique est basée sur la base 2...)

Oui, 1 Kilo-Octet est égal à 2 puissance 10 octets, soit 1024 Octets.
Donc, si nous faisons 64 * 1024, on retrouve bien nos 65536 octets de mémoire.
Je vous laisse deviner à quoi est égal 1 méga-octet... Non pas 1 million d'octets, mais 1048576 octets.
Pourquoi ? parce que 1 méga-octet = 2 puissance 20, ou encore 1024 Kilo-octets.
Bon... Laissons pour le moment ces histoires d'unités, et revenons à notre mémoire.
Nous disions donc que le Z80 est capable d'adresser 64 Kilo-Octets (que nous noterons Ko).
Sur ces 64 Ko, certaines parties sont de la ROM, d'autres de la RAM.
La ROM ne peut être que lue, donc n'est pas utilisable pour programmer.
Il nous reste que la RAM dans laquelle nous pouvons écrire nos programmes.
Bon, sachant que l'Amstrad CPC 464 dispose de 32Ko de ROM et de 64Ko de RAM,
comment fait notre bon vieux Z80 pour adresser un total de 32+64 = 96Ko de mémoire ?
Ben oui, comme le Z80 utilise un adressage sur 16 bits, cela nous donne que 64Ko accessibles, donc, en théorie, notre CPC 464 ne pourrait avoir que 32Ko de ROM et 32Ko de RAM.
Mais les ingénieurs qui ont conçus le 464 ont eu quelques idées de génie, en utilisant ce que l'on appelle le "bank-switching".

Encore un terme barbare ? Oui, si nous traduisons en français, cela donne "échangeur de banques".
Le CPC organise sa mémoire sous forme de "banques" de 16Ko chacunes (16Ko = 16 * 1024 octets = 16384 octets.)

Donc, on peut dire que le Z80 adresse 4 banques aux adresses suivantes :

banque 0 : début = adresse 0, fin = adresse 16383
banque 1 : début = adresse 16384, fin = adresse 32767
banque 2 : début = adresse 32768, fin = adresse 49151
banque 3 : début = adresse 49152, fin = adresse 65535

Utilisons maintenant les notions que nous avons vu dans le chapitre 1, à savoir, la représentation en hexadécimal...

banque 0 : début = adresse #0000, fin = adresse #3FFF
banque 1 : début = adresse #4000, fin = adresse #7FFF
banque 2 : début = adresse #8000, fin = adresse #BFFF
banque 3 : début = adresse #C000, fin = adresse #FFFF

C'est plus simple comme cela, non ?

Dans le CPC, il y a un composant, appelé Gate-array, qui gère entre autres le bank-switching.
En fait, la banque 0 peut contenir soit de la ROM, soit de la RAM. Il en va de même pour la banque 3.
C'est le gate-array qui permet "d'échanger" la banque 0 ou 3 soit avec la ROM, soit avec la RAM.
Donc, en fait, la banque 0 contient 16Ko de ROM ou 16Ko de RAM, les banques 1 et 2 contiennent chacune 16Ko de RAM, et la banque 3 contient 16Ko de ROM ou 16Ko de RAM.
Evidement, le "switching" ne permet pas d'avoir la ROM et la RAM en même temps. Pour se faire à l'idée de comment cela fonctionne, imaginons notre mémoire comme une grande armoire comme tout à l'heure.
Notre armoire est découpée en 4 parties (les banques). Ensuite, la partie située sur la banque 0 peut être alternée soit par un morceau de ROM, soit par un morceau de RAM.
Il en va de même pour la partie située sur la banque 3.
Donc, pour résumér, notre CPC 464 possède 64Ko de RAM, divisée en 4 banques et 32Ko de ROM, 16Ko de cette ROM pouvant être placée en banque 0 à la place de la RAM, et les autres 16Ko de ROM pouvant être placée en banque 3 à la place de la RAM.
La ROM qui peut être placée dans la banque 0 est appelée ROM inférieure, la ROM qui peut être placée dans la banque 3 est appelée ROM supérieure.

Pour le moment, nous pouvons nous contenter de dire que le CPC possède 64Ko de RAM, nous verrons le "bank-switching" par la suite...

Zone interdite.

Non, ce n'est pas le titre d'une émission, ou d'un film de science-fiction...
En fait, sur le CPC, on ne peut pas jouer avec les 64Ko de RAM comme on le veut...
Le CPC (et tous les micro-ordinateurs d'ailleurs...) a une organisation mémoire particulière.
Voici en résumé, le "mapping" mémoire du CPC :
(J'ai volontairement mis les adresses en hexadécimal, plus pratique pour parler d'adresses mémoires.)

de #0000 à #003F : réservé (copie de la ROM inférieure) (64 octets)
de #0040 à #016F : réservé basic (zone de saisie basic) (304 octets)
de #0170 à #A679 : zone libre pour programme basic ou autre (42 Ko)
de #A67A à #B8FA : zone réservée par le système (variables systèmes) (5Ko)
de #B900 à #BDFF : zone réservée par le système (vecteurs systèmes)
de #BE00 à #BE80 : zone réservée par l'Amsdos (si lecteur disquette présent)
de #BE80 à #BEFF : libre
de #BF00 à #BFFF : zone réservée par le système (pile)
de #C000 à #FFFF : zone de mémoire écran (16 Ko)

Nous pouvons donc en déduire que la zone utilisable pour le basic est comprise entre les adresses #0170 à #A679.
Ce qui nous donne à peu près 42Ko. Tiens ? Qu'est ce qu'il se passe lorsque l'on tape un PRINT FRE(0) ?
On obtiens (normalement...) 42249, soit 42Ko. Et tiens, #A679 - #170, ça fait justement 42249 octets...

Et oui, voila d'où provient ce chiffre lorsque l'on tape un PRINT FRE(0) sur un CPC...
Même sur un CPC 6128, disposant de 128Ko de ram, seuls 42Ko sont disponibles pour le Basic.
N'oublions pas que notre Z80 ne sait adresser que 64Ko à la fois...
Les 64Ko supplémentaires du CPC 6128 sont gérés eux aussi avec la technique du "bank-switching", et sont tous placés dans la banque 1.
Et là aussi, c'est notre cher gate-array qui permet de gérer les 64Ko supplémentaire du CPC 6128.

Voila, j'espère avoir été clair sur l'organisation de la mémoire, c'est aussi une base très importante pour comprendre la suite...

Page précédente : Cours d'assembleur par Demoniak - Partie 1 : Les bases de nombres

CPCrulez[Content Management System] v8.75-desktop/c
Page créée en 044 millisecondes et consultée 1233 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.