<-Précédent Retour à l'accueil Contact : etienne"point"sauvage"at"gmail.com Suivant->
  1. De la mémoire vive
  2. De la taille
  3. Des périphériques
  4. De la cartographie
  5. De la pratique
  6. De la bonne exécution de nos basses oeuvres

    Assembleur : une carte de la mémoire

    Il faut maintenant dessiller nos yeux : nous avons un nano système d'exploitation. Quoique "nano" ne signifie pas "naze", il faut reconnaître qu'il ne remplit pas vraiment les services qu'on en attend. Néanmoins, il permet de taper quelques caractères, et donc d'exploiter un ordinateur : c'est un système d'exploitation. Normalement, à cet instant, la poitrine se gonfle d'orgueil et on court ajouter "développeur système" sur son CV. N'allons pas jusque là, mais ne boudons pas notre plaisir en nommant notre système d'exploitation. Je propose KarlOS, calembour source de calembours. Car l'OS ainsi nommé représente l'exploitation de l'ordinateur par l'ordinateur, principe cher à Karl, et est vraiment fait pour la rigolade, principe tout aussi cher à Carlos. Et l'emprunt à la langue de Shakespeare me sera pardonné par les rigolos.

    Mais trêve de plaisanterie. Notre mission, aujourd'hui, consistera à préparer le terrain pour la gestion de la mémoire.

  1. De la mémoire vive
  2. Que dis-je, de la mémoire vive ? Des forces vives de la nation, plutôt !

    La mémoire vive, on l'a utilisée, je suis persuadé que si vous en êtes là, vous voyez de quoi je cause, Windows vous a certainement déjà insulté en vous disant qu'il n'en avait pas assez (c'est un junkie, la mémoire vive étant au système d'exploitation ce que l'héroïne est à la littérature policière, admirez le double sens au passage, merci), voire vous en trafiquez pour les plus atteints. Mais un petit rappel ne ferait pas de mal, je suis sûr.

    La mémoire vive, c'est votre mémoire à vous dans le sens commun : le souvenir des vacances à la mer, les tartes de mémé, Ragondin le vieux chien de la famille dont l'arbre généalogique fait croire en la génération spontanée, la démonstration du théorème de Pythagore et la couleur de la robe de la belle-soeur au pique-nique de la semaine dernière ("Vert. -Non bleu. -Non vert. -Non bleu, je me souviens bien, c'est ma soeur quand même ! -Non vert, je le sais, je fais gaffe pour les relations familiales. -Non, bleu comme ça ! -Ah parce que tu appelles ça bleu ?"). Il ne faut pas oublier cela, à la base, la mémoire vive, c'est la source des disputes ménagères. Mais les informaticiens rêvent de recréer en silicium toute la magie des séances de bris de vaisselle, et ils se consolent en faisant des analogies. Ainsi, les ordinateurs disposent de mémoire vive. Ce sont des composants électroniques qui peuvent changer d'état sur commande, puis rester dans cet état tant qu'ils sont sous tension. Et quand il n'y a plus de tension, on ne sait plus ce qu'il se passe. Ca garde son état : c'est une mémoire, ça devient n'importe quoi quand c'est éteint : c'est vif. C'est de la mémoire vive.

    Les électroniciens, qui sont des gens prosaïques et qui n'ont rien à voir avec EDF, ne parlent pas de mémoire vive : ils parlent de la mémoire en fonction de son type, de sa nature profonde. En général, ils causent de RAM (Random Access Memory), Mémoire à Accès Aléatoire. C'est un sigle confus, car bien évidemment, l'accès n'est pas aléatoire ! D'ailleurs, c'est bien dommage, ça nous aurait permis d'éviter un des gros problèmes de l'informatique (pour ceux que ça intéresse, penchez-vous donc sur les nombres pseudo-aléatoires). Ce qui est aléatoire dans l'accès, c'est la prochaine case qui va être demandée, du point de vue de la mémoire. Contrairement à l'accès séquentiel où l'ordre de lecture est prédéterminé, le processeur peut demander n'importe quel contenu à tout instant.

  3. De la taille
  4. Les chauffards de l'informatique existent. Ils fonctionnent à peu près de la même façon que les chauffards routiers, à ceci près qu'ils parlent de bus AGP là où d'autres parlent de carburateur double-corps. Et parfois, dans leur conversation, ils évoquent la quantité de mémoire dont ils disposent sur leur machine. Ce concours à celui qui a la plus grande nous apprend que les ordinateurs ne sont pas égaux en mémoire vive. Comme KarlOS permet d'exploiter un ordinateur, ce serait pas mal qu'il sache de combien il dispose pour faire joujou.

  5. Des périphériques
  6. Nous écrivons les pixels à afficher dans la mémoire vive, dans une plage d'adresses donnée. Cette partie de la mémoire est particulière, et nous n'avons pas à y écrire les décimales de pi. C'est, en fait, un espace de dialogue avec la carte graphique. Conséquemment, nous en déduisons que certaines plages d'adresses sont réservées au bénéfice d'un périphérique. On dit, dans l'horrible jargon informatique, que le périphérique est mappé en mémoire. Mappé, cela vient de map, carte. C'est ce que nous voulons : une carte de la mémoire, pour savoir où il y en a et ce qu'on peut en faire.

  7. De la cartographie
  8. Aux rétifs de la boussole, paix et amour. Un ordinateur ne connait ni haut, ni bas, ni nord, ni sud, pas plus que gauche ou droite. Il ne connait que devant et derrière. C'est linéaire. Au risque de continuer dans les platitudes, il n'y a qu'une dimension. L'IGN du PC est parfaitement au point et n'édite que des listes : de 0x0000 à 0xFFFF, je n'ai rien de répertorié. De 0x10000 à 0x2FFFF, la mémoire est réservée. Le reste n'existe pas.

    L'IGN du PC est dans le BIOS. Moi, le jour où j'ai appris ça, j'ai dit : "Arg !". Oui, cela signifie qu'il faut récupérer cette carte de la mémoire avant de passer en mode protégé. Cela implique de le faire dans le chargeur de secteur d'amorçage. Vous savez, le secteur d'amorçage, celui qui ne peut faire que 510 octets de long ? Hé bien, on va se serrer un peu et on va y faire la carte de la mémoire.

  9. De la pratique
  10. On se place dans le code du secteur d'amorçage, juste après le chargement de KarlOS à partir de la disquette. On se place là parce que cela nous évitera de changer la valeur de DX qui contient le lecteur sur lequel on travaille. De surcroît, cela garde le changement de mode vidéo le plus près possible du passage au noyau à proprement parler.

    Il s'agit du service 0x15, fonction 0xE820. Pour les paramètres, accrochez-vous au pinceau ça déménage. EBX représente l'avancement de la construction de la carte mémoire. Il doit être à 0 au départ, et est censé retourner à 0 une fois toute la carte parcourue. EDX contient "SMAP", ce qui donne 0x534D4150. ECX contient la taille d'une entrée de la carte mémoire : 24 bits est bien, c'est la taille maximale possible actuellement, ce qui permet de ne rien rater et d'inclure de vieilles versions. ES contient le segment (version 20 bits d'adresse !) de notre carte, et DI son décalage.

    Ceci étant rempli, on appelle l'interruption.

    Etudions les valeurs de retour. EAX doit contenir "SMAP". Si la retenue a été posée, la liste a été parcourue dans son ensemble. Si EBX est RAZé, idem. ECX est censé contenir la taille de la zone mémoire citée dans la nouvelle entrée de la carte (donc si zéro, on zappe, les zones mémoire de taille nulle étant de très très peu d'intérêt). A partir de la version 3 de l'ACPI (Advanced Configuration and Power Interface) - interface avancée de configuration et de gestion de l'énergie, le bit de poids faible de la zone de 24 bits indique que la zone mémoire est à ignorer. A quoi sert d'indiquer une zone mémoire si c'est pour demander de l'ignorer, là est la question. Toujours est-il que nous l'ignorerons, en bons petits enfants sages. On testera aussi que M. BIOS ne nous a pas écrit que des zéros.

    Une fois les retours traités, on recommence pour in fine avoir la carte totale.

    Je vous donne les quelques octets qui font le boulot :

    ;;Infos mémoire	
    ; INT 0x15, eax = 0xE820 : fonction BIOS 32 bits qui donne la carte de la mémoire
    ; ES:DI est l'adresse à laquelle elle écrit une entrée
    	mov 	ax, 	BOOT_SEG
    	mov 	es, 	ax
    	mov 	di, 	DonneesMemoire
    	xor 	ebx, 	ebx			; EBX est un marqueur d'avancement pour INT 0x15, on commence donc par 0
    	xor 	bp, 	bp			; BP stocke le nombre d'entrées de la table
    .entree:
    	mov 	edx, 	0x534D4150	; Place "SMAP" dans EDX
    	mov 	eax, 	0xE820
    	mov 	[es:di + 20], dword 1; Par souci de compatibilité, on considère la future entrée comme une entrée ACPI 3.X valide
    	mov 	ecx, 	24			; On demande 24 octets à INT 0x15
    	inc 	bp					; On compte cette entrée
    	int 	0x15
    	jc 		.fin				; Si la retenue est posée, c'est qu'on a atteint la fin
    	cmp 	eax, 	0x534D4150	; Si EAX ne contient pas "SMAP", c'est une erreur
    	jne 	.fin
    	test 	ebx, 	ebx			; Si EBX est à 0, on a fini
    	je 		.fin
    	jcxz 	.entree				; Si ECX est à 0, il s'agit d'une zone de taille nulle. Aucun intérêt.
    	cmp 	cl, 	20			; Si on a moins de 24 bits
    	jbe 	.sansExtension		; on n'est pas en ACPI 3.X
    	test 	byte [es:di + 20], 1; Sinon, est-ce que le bit "à ignorer" est placé ?
    	je 		.entree
    .sansExtension:
    	mov 	ecx, 	[es:di + 8]	; get lower dword of memory region length
    	or 		ecx, 	[es:di + 12]	; "or" it with upper dword to test for zero
    	jz 		.entree		; if length qword is 0, skip entry
    	add 	di, 	24
    	jmp 	.entree
    .fin:
    	mov 	[NbEntreesCarteMemoire], bp	; store the entry count
    

  11. De la bonne exécution de nos basses oeuvres
  12. On est certes très forts et fiers de nous, mais mes biens chers frères, nous sommes humains et errare humanum est. Conséquemment, avant de nous plonger dans les joies indicibles de la gestion de la mémoire, allons-nous afficher cette carte. Et ça va se passer, tout le monde s'en doute, en mode protégé.

    Pour que toutes ces données acquises de haute lutte soient plus manipulables par notre intellect, on va commencer par les recopier chez nous. Ceci nous permettra, plus tard, de considérer l'espace utilisé par le chargeur comme libre, ce qui nous évitera un bout de code perdu nulle part au milieu de la mémoire. Simple, on a déjà fait avec les informations vidéo.

    Ensuite, ma foi, je propose de simplement afficher les 24 octets comme des nombres en hexadécimal. Cela a l'avantage de refléter la structure bit à bit de ces 24 octets. On a déjà les fonctions qui font cela, il suffit de les adapter à notre nouvelle façon d'afficher. On va en profiter pour déplacer des bidules dans notre alphabet, histoire de simplifier la procédure de conversion en chaîne. Comment ? C'est simple. Auparavant, par injonction divine de la table ASCII, en cas de débordement des sacro-saints chiffres arabes, on devait faire des additions pour retomber sur les caractères. Et bien, mes amis, foin de ceci dorénavant : en mettant l'alphabet juste après les chiffres arabes, le tour est joué !

    On exécute notre machine virtuelle, et on obtient des séries de nombres en hexadécimal. Super.

    Ces nombres sont affichés en gros-boutiste, par quadruple-mot (de 32 bits). Il y a donc six quadruple-mots. Les deux premiers sont l'adresse de départ de la zone concernée. On est en 32 bits, bravo, le second quadruple-mot doit donc être vide, ou 0. Notez qu'on est prêts pour le 64 bits de ce point de vue. Les deux suivants sont la taille de la zone en octets. On est toujours en 32 bits, donc le second quadruple-mot est toujours à 0. Le quadruple-mot suivant n'est intéressant que pour son plus petit octet, dont je vous livre les valeurs possibles (librement traduit et reformulé depuis le wiki de OSDev).

    Et le dernier quadruple-mot contient 1. Sinon, y'a pétard. S'il y a pétard, demandez de l'aide.

    Hopopop ! Partez pas c'est pas fini. Dites, sur votre machine, réelle ou virtuelle, il y a combien de mémoire ? Pour les virtualistes, c'est dans la configuration de votre émulateur. Pour d'éventuels autres, ça doit se trouver quelque part : bon de livraison, coin de cervelle. Faites la somme des tailles données par notre carte. Vous devez avoir une somme qui tombe sur votre mémoire, enfin je veux dire, sur la vraie mémoire de votre machine. Si ce n'est pas la somme des types 1 et 3, ce doit être la somme de tous les types, ça dépend comment on compte. Alors, est-ce que "le compte est bon" ?

  13. Du code
  14. L'ensemble du code de ce chapitre se trouve ici :
    Tuto12