<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<article lang="fr">
  <articleinfo>
    <title>Écrivez votre mini OS (Partie 3)</title>

    <subtitle>Gazette Linux n°082 — Septembre 2002</subtitle>

    <author>
      <firstname>Raghu</firstname>

      <surname/>

      <email>raghu4jm _CHEZ_ yahoo _POINT_ com</email>
    </author>

    <author>
      <firstname>Chitkala</firstname>

      <surname/>

      <email/>
    </author>

    <othercredit class="translator" role="traduction">
      <firstname>Sébastien</firstname>

      <surname>Marbrier</surname>

      <contrib>Adaptation française</contrib>

      <email>sebastien _POINT_ marbrier _CHEZ_ laposte _POINT_ net</email>
    </othercredit>

    <othercredit class="translator" role="relecture">
      <firstname>Frédéric</firstname>

      <surname>Marchal</surname>

      <contrib>Relecture de la version française</contrib>

      <email>fmarchal CHEZ perso POINT be</email>
    </othercredit>

    <legalnotice>
      <para>Article paru dans le n°082 de la Gazette Linux de septembre
      2002.</para>

      <para>Cet article est publié selon les termes de la <ulink
      url="http://linuxgazette.net/copying.html">Open Publication
      License</ulink>. La <citetitle>Linux Gazette</citetitle> n'est ni
      produite, ni sponsorisée, ni avalisée par notre hébergeur principal,
      SSC, Inc.</para>
    </legalnotice>

    <copyright>
      <year>2002</year>

      <holder>Raghu &amp; Chitkala.</holder>
    </copyright>

    <copyright>
      <year>2014</year>

      <holder>Sébastien Marbrier</holder>
    </copyright>

    <copyright>
      <year>2017</year>

      <holder>Frédéric Marchal</holder>
    </copyright>
  </articleinfo>

  <section>
    <title/>

    <note><para>Note de l'Éditeur&nbsp;: En raison d'autres
    engagements, Krishnakumar n'est plus en mesure d'achever cette série
    d'articles, il a donc passé la main à ses jeunes collègues, Raghu et
    Chitkala qui ont écrit cette partie.</para></note>

    <para>Dans les parties I et II, nous avons étudié l'utilisation d'outils
    disponibles sous Linux pour fabriquer un petit secteur d'amorçage et
    accéder aux <acronym>BIOS</acronym> du système. Notre mini système d'exploitation sera basé
    sur le modèle d'un noyau Linux « historique », nous basculerons très bientôt
    dans le mode protégé&nbsp;! Cet article vous expliquera comment faire.</para>
  </section>

  <section>
    <title>1. Qu'est-ce que le <emphasis role="underlined">Mode
    Protégé</emphasis>&nbsp;?</title>

    <para>Les 80386 et supérieurs apportent de nombreuses fonctionnalités
    nouvelles pour remédier aux défauts du 8086 qui ne possède presqu'aucune
    fonctionnalité pour la protection de la mémoire, la mémoire virtuelle, le
    multitâche, ou la mémoire au-delà des 640K &mdash; tout en restant compatible
    avec la famille 8086. Le 386 a hérité de toutes les caractéristiques du
    8086 et du 286, avec beaucoup d'améliorations. Tout comme les processeurs
    précédents, il dispose du mode réel. Et comme le 286, le 386 peut
    fonctionner en mode protégé. Cependant, la mécanique interne du mode
    protégé du 386 est extrêmement différente. Le mode protégé du 386 apporte
    au programmeur une meilleure protection et plus de mémoire que le 286. La
    raison d'être du mode protégé n'est pas de protéger votre programme mais
    protéger tout le reste (y compris le système d'exploitation) de votre
    programme.</para>

  <section>
    <title>1.1 Différences entre le Mode Protégé et le Mode Réel</title>

    <para>D'un point de vue superficiel, les modes réel et protégé ne semblent
    pas très différents. Les deux utilisent la segmentation mémoire, les
    interruptions et les pilotes de périphériques pour gérer le matériel. Mais
    il y a des différences qui justifient l'existence de deux modes distincts.
    Avec le mode réel, on peut représenter la mémoire sous la forme de 64 000
    segments séparés d'au moins 16 bits. La segmentation est prise en charge
    par un mécanisme interne utilisant des registres de segments. Le contenu
    de ces registres de segment (CS, DS, SS&hellip;) forme l'adresse physique que
    l'unité centrale écrit sur le bus d'adresses. L'adresse physique est
    générée en multipliant le registre de segment par 16 et en ajoutant
    ensuite un décalage de 16 bits. C'est ce décalage de 16 bits qui nous
    limite à 64 000 segments.</para>

    <figure id="adressage_mode_reel">
	<title>Adressage en Mode Réel</title>
    <mediaobject>
      <imageobject>
        <imagedata fileref="images/lg082-A/fig1.png" format="PNG"/>
      </imageobject>
	  <textobject><phrase>Schéma du mode d'adresse réel</phrase></textobject>
    </mediaobject>
    </figure>

    <para>Dans le mode protégé, la segmentation est définie au moyen d'un
    ensemble de tables appelées tables de descripteurs. Les registres de
    segment contiennent les pointeurs sur ces tables. Deux types de tables
    sont utilisés pour définir la segmentation de la mémoire&nbsp;: La Table des
	Descripteur Généraux (<acronym>TDG</acronym>) et la Table des Descripteurs
	Locaux (<acronym>TDL</acronym>). La <acronym>TDG</acronym> contient
    les descripteurs élémentaires auxquels toutes les applications ont accès.
    Dans le mode réel, un segment a une taille de 64Ko et est séparé du
    suivant par 16 octets. Dans le mode protégé, la taille des segments peut
    aller jusqu'à 64Go et nous pouvons le positionner où nous le voulons. La
    <acronym>TDL</acronym> contient les informations de segmentation propres à une tâche ou à un
    programme. Par exemple, un système d'exploitation pourrait définir une <acronym>TDG</acronym>
    avec ses descripteurs systèmes et une <acronym>TDL</acronym> avec les descripteurs appropriés
    pour chaque tâche. Chaque descripteur a une taille de 8 octets. Le format
	donné plus bas (<xref linkend="format_desc_segment"/>). Chaque fois qu'un registre de segment est chargé,
    l'adresse de base est récupérée de l'entrée appropriée de la table. Le
    contenu du descripteur est stocké dans un registre invisible pour le
    programmeur appelé registre fantôme, ainsi les futures références au même
    segment peuvent utiliser cette information au lieu d'accéder à chaque fois
    à la table. L'adresse physique est formée en ajoutant le décalage de 16 ou
    de 32 bits à l'adresse de base dans le registre fantôme. Ces différences
    sont mises en évidences dans les figures 1 et 2.</para>

    <figure id="adresse_mode_protege">
    <title>Adressage en Mode Protégé</title>
    <mediaobject>
      <imageobject>
        <imagedata fileref="images/lg082-A/fig2.png" format="PNG"/>
      </imageobject>
	  <textobject><phrase>Utilisation de la TDG ou TDL</phrase></textobject>
	</mediaobject>
    </figure>

	<figure id="format_desc_segment" xreflabel="fig 3">
    <title>Format du Descripteur de Segment</title>
    <mediaobject>
      <imageobject>
        <imagedata fileref="images/lg082-A/fig3.png" format="PNG"/>
      </imageobject>
	  <textobject><phrase>Contenu du descripteur de segment</phrase></textobject>
	</mediaobject>
    </figure>

    <para>Il y a une autre table appelée Table des Descripteurs d'interruption
    ou <acronym>TDI</acronym>. La <acronym>TDI</acronym> contient les descripteurs d'interruptions. Ils sont
    utilisés pour indiquer au processeur où trouver les routines
    d'interruption. Elle contient une entrée par interruption, exactement
    comme dans le Mode Réel, cependant le format de ces entrées est
    complètement différent. Comme nous n'utiliserons pas la <acronym>TDI</acronym> dans notre
    code pour basculer dans le Mode Protégé, nous n'entrerons pas plus dans
    les détails.</para>
  </section>
  </section>

  <section>
    <title>2. Activation du Mode Protégé</title>

    <para>Le 386 dispose de quatre registres de contrôle de 32 bits; ces
    registres sont appelés CR0, CR1, CR2 et CR3. CR1 est réservé pour les
    futures générations de processeurs et n'est pas défini pour le 386. CR0
    contient les bits qui activent ou non la pagination et les protections
    ainsi que les bits qui contrôlent le fonctionnement du coprocesseur de calcul
    en virgule flottante. CR2 et CR3 sont utilisés par le mécanisme de
    pagination. Nous nous intéressons au bit 0 du registre CR0 que l'on
    appelle bit PE (Protection Enable). Lorsque PE = 1, le processeur sait que
    le mode protégé est activé avec le mécanisme de pagination que nous avons
    décrit plus haut. Si PE = 0, le processeur fonctionne en mode réel. Le 386
    dispose également de tables de registres de segmentation telles que la
    <acronym>TDGR</acronym>, la <acronym>TDLR</acronym> et la <acronym>TDIR</acronym>. Ces registres de segments d'adresse contiennent
    les descripteurs de table. La <acronym>TDGR</acronym> pointe sur la <acronym>TDG</acronym>, les 48 bits de la
    <acronym>TDGR</acronym> définissent directement le début et la fin de la <acronym>TDG</acronym> au moyen d'un
    adressage linéaire de 32 bits et d'une limite de 16 bits.</para>

    <para>Le basculement vers le mode protégé implique principalement que nous
    activions le bit PE, mais il y a quelques autres petites choses que nous
    devons faire. Le programme doit initialiser les segments système et les
    registres de contrôle. Immédiatement après avoir mis le bit PE à 1 nous
    devons exécuter une instruction de saut pour vider la file d'exécution de
    toute instruction qui pourrait avoir été chargée dans le mode réel. Ce saut
    se fait habituellement sur la prochaine instruction. Les étapes pour
	basculer dans le mode protégé se résument alors à&nbsp;:
	
	<orderedlist numeration="arabic">
        <listitem>
          <para>Construire la <acronym>TDG</acronym>.</para>
        </listitem>

        <listitem>
          <para>Activer le mode protégé en positionnant à 1 le bit PE de
          CR0.</para>
        </listitem>

        <listitem>
          <para>Faire un saut pour vider la file.</para>
        </listitem>
      </orderedlist></para>

    <para>Nous donnons à présent le code pour effectuer le basculement.</para>
  </section>

  <section>
    <title>3. Nos besoins</title>

    <itemizedlist>
      <listitem>
        <para>une disquette vierge</para>
      </listitem>

      <listitem>
        <para>l'assembleur <acronym>NASM</acronym></para>
      </listitem>
    </itemizedlist>

    <para><ulink url="images/lg082-A/code.asm.txt">Cliquez ici</ulink> pour télécharger le
    code. Saisissez le code dans un fichier nommé <filename>abc.asm</filename>. Assemblez-le en
    tapant la commande <command>nasm abc.asm</command>. Ceci
	produira un fichier nommé <filename>abc</filename>. Insérez ensuite la disquette et tapez la
    commande suivante : <command>dd if=abc of/dev/fd0</command>.
	Cette commande écrira le fichier <filename>abc</filename> dans le premier secteur de la
    disquette. Redémarrez ensuite le système. Vous devriez voir la séquence de
    messages suivante:</para>

    <itemizedlist>
      <listitem>
        <para>Chargement du secteur d'amorçage de notre OS ......</para>
      </listitem>

      <listitem>
        <para>A (de couleur marron)</para>
      </listitem>

      <listitem>
        <para>Basculement en mode protégé ....</para>
      </listitem>

      <listitem>
        <para>A (de couleur blanche)</para>
      </listitem>
    </itemizedlist>
  </section>

  <section>
    <title>4. Le code qui fait tout&nbsp;!</title>

    <para>Nous donnons d'abord le code pour effectuer le basculement. Il est
    suivi par une explication détaillée</para>

    <para>Comme nous l'avions indiqué dans l'article précédent (1ère partie),
    le BIOS sélectionne le périphérique d'amorçage et place le secteur de
	démarrage à l'adresse <literal>0x7c00</literal>. Nous avons ainsi écrit notre code à
	l'adresse <literal>0x7c00</literal>. La directive <code>org</code> implique cela.</para>
  </section>

  <section>
    <title>Fonctions utilisées</title>

    <variablelist>
      <varlistentry>
        <term>print_mesg :</term>

        <listitem>
          <para>Cette routine utilise la sous fonction 13h de l'interruption
          <literal>10h</literal> du <acronym>BIOS</acronym> pour écrire une chaîne à l'écran. Les attributs sont
          spécifiés en plaçant les bonnes valeurs dans divers registres.
          L'interruption <literal>10h</literal> est utilisée pour les manipulations de chaînes de
          caractères. On place <literal>10h</literal>, le numéro de la sous fonction dans <code>ah</code>, ce
          qui signifie que l'on souhaite afficher une chaîne de caractères. Le
          bit 0 du registre <code>al</code> détermine la prochaine position du curseur&nbsp;;
          s'il est à 0 on retourne au début de la prochaine ligne après
          l'appel de la fonction, s'il est à 1 le curseur est placé après le
          dernier caractère affiché.</para>

          <para>La mémoire vidéo est divisée en plusieurs pages que l'on
          appelle pages d'affichage vidéo. Une seule page peut être affichée à
          la fois (allez voir la première partie pour plus de détails sur la
          mémoire vidéo). Le contenu de <code>bh</code> indique le numéro de la page, <code>bl</code>
          précise la couleur du caractère à afficher. <code>cx</code> contient la longueur
          de la chaîne à afficher. Le registre <code>dx</code> donne la position du
          curseur. Une fois que tous les attributs ont étés initialisés, on
          appelle l'interruption <acronym>BIOS</acronym> <literal>10h</literal>.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>get_key:</term>

        <listitem>
          <para>On utilise l'interruption <acronym>BIOS</acronym> <literal>16h</literal> dont la sous
          fonction <literal>00h</literal>
          est utilisée pour lire le dernier caractère lu au clavier. Le
          registre <code>ah</code> contient le numéro de la sous fonction.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>clrscr:</term>

        <listitem>
          <para>Cette fonction utilise également une sous fonction de
          l'interruption <literal>10h</literal>. La sous-fonction <literal>06h</literal> permet d'effacer l'écran
          avant d'afficher une chaîne de caractères. On initialise le registre
          <code>al</code> à <literal>0</literal>. Les registres <code>cx</code> et <code>dx</code>
		  donne la taille de la fenêtre à
          effacer&nbsp;; dans notre cas, c'est tout l'écran. Le registre <code>bh</code> donne la
          couleur de fond d'écran, ici c'est le noir.</para>
        </listitem>
      </varlistentry>
    </variablelist>
  </section>

  <section>
    <title>C'est ici que tout commence&nbsp;!</title>

    <para>La première instruction en langage assembleur est un saut court vers
    le code <function>begin_boot</function>. On souhaite imprimer un caractère « A » de couleur
    marron dans le mode réel, configurer la <acronym>TDG</acronym>, basculer dans le mode protégé
    et afficher un « A » blanc. Chaque mode possède sa propre méthode
    d'adressage.</para>

    <section><title>Dans le Mode Réel</title>

    <para>On utilise le registre de segment <code>gs</code> pour pointer sur la mémoire
    vidéo. On utilise un adaptateur <acronym>CGA</acronym> (adresse de base par défaut <literal>0xB8000</literal>)&nbsp;;
    on constate qu'il manque un 0 dans le code. En fait l'unité de
    segmentation du mode réel fournit le zéro supplémentaire. Le 8086 effectue
    habituellement une manipulation d'adresse sur 20 bits&nbsp;; par commodité, cela
    a été transposé dans l'adressage du mode réel du 386. La valeur <acronym>A.S.C.I.I.</acronym>
    pour « A » est 0x41&nbsp;; 0x06 indique que l'on veut une couleur de caractère
    marron. L'affichage ne change pas tant que l'on n'appuie pas sur une
    touche. Ensuite on affiche un message sur l'écran indiquant que l'on va
    basculer sur le mode protégé. On fait alors pointer le registre bp
    (pointeur de base) sur le message à afficher.</para>
	</section>

    <section><title>Lancement du mode protégé</title>

    <para>Nous n'avons plus besoin de nous embêter avec les interruptions
    lorsque que nous sommes en mode protégé. Nous pouvons alors les
    désactiver&nbsp;; c'est ce que fait <code>cli</code>. Nous les réactiverons plus tard.
    Initialisons à présent la <acronym>TDG</acronym>, on initialise quatre descripteurs dans
    notre essais de basculement dans le mode protégé. Ces descripteurs
    initialisent notre segment de code (<function>code_gdt</function>), les segments de données et
    de pile (<function>data_gdt</function>) et le segment vidéo afin d'accéder à la mémoire vidéo.
    Un descripteur factice est également initialisé bien qu'il n'est jamais
    utilisé sauf si bien sûr vous voulez une triple faute. C'est un
    descripteur vide. Examinons quelques champs du descripteur de segment.
    <itemizedlist>
        <listitem>
          <para>La première instruction définit la taille du segment; par
          simplicité est fixée à <literal>0xFFFF</literal> qui est la valeur maximum (soit 4Go).
          Pour le segment vidéo, nous avons utilisé une valeur prédéfinie de
          3999 (80 colonnes × 25 lignes × 2 octets - 1).</para>
        </listitem>

        <listitem>
          <para>L'adresse de base des segments de code et de donnes est fixée
          à <literal>0x0000A</literal>. Le segment vidéo est à <literal>0xb8000</literal>
		  (adresse de base de la mémoire vidéo)</para>
        </listitem>
      </itemizedlist></para>

    <para>L'adresse de base de la <acronym>TDG</acronym> doit être chargée dans le registre
    système <acronym>TDGR</acronym>. Le segment <acronym>TDGR</acronym> est chargé avec la taille de la <acronym>TDG</acronym> dans le
    premier mot et l'adresse de base dans le second. L'instruction lgdt charge
    ensuite le segment <acronym>TDG</acronym> dans le registre <acronym>TDGR</acronym>. Nous sommes à présent prêts
    à basculer dans le mode protégé. On commence par positionner le bit le
    moins significatif de CR0 à 1 (c.-à-d. le bit PE). Nous ne sommes pas tout à
    fait dans le mode protégé.</para>

    <para>La section 10.3 du manuel de référence du programmeur de l'intel
    80386 de 1986 indique&nbsp;: immédiatement après avoir positionné le drapeau de
    PE, le code d'initialisation doit purger la file de préchargement en
    exécutant une instruction <code>JMP</code>. Le 386 récupère et décode les instructions
    avant qu'elles ne soit exécutées&nbsp;; cependant un basculement dans le mode
    protégé, les informations sur les instructions préchargées (qui dépendent
    du mode réel) ne sont plus valides. Un <code>JMP</code> force le processeur à éliminer
    les informations invalides.</para>

    <para>Nous somme à présent dans le mode protégé. Comment le vérifier&nbsp;?
    Regardons le « A » blanc. Nous avons initialisé le segment de données et le
    segment supplémentaire (<code>es</code>) avec le sélecteur de segment de données
    (<code>datasel</code>), initialisé <code>gs</code> avec le sélecteur de segment vidéo (<code>videosel</code>).
    Pour afficher un « A » blanc, nous avons chargé un mot contenant la valeur
    <acronym>A.S.C.I.I.</acronym> et l'attribut à destination [gs:0000] c.-à-d. b8000:0000. La boucle
    sans fin conserve le texte à l'écran jusqu'au redémarrage du
    système.</para>

    <para>Les instructions temporelles sont utilisées pour remplir les octets
    inutilisés du secteur. Nous écrivons 0xAA55 dans les octets 511 et 512
    pour indiquer qu'il s'agit du secteur amorçable. Et c'est tout.</para>
  </section>
  </section>

  <section>
    <title/>

    <blockquote>
      <para><emphasis role="bold">Raghu et Chitkala.</emphasis></para>

      <para>Raghu et Chitkalaun sont des étudiants en septième semestre à
      l'Université publique Thissur Kerala, en Inde. L'objectif de leur projet
      de dernière année est de porter le Mode Utilisateur de Linux sur BSD.
      Leurs centres d'intérêts incluent les Systèmes d'Exploitation, le Réseau
      et les Microcontrôlleurs.</para>
    </blockquote>
  </section>

  <colophon id="a-propos-de-la-gazette">
    <title>Adaptation française de la Gazette Linux</title>

    <para>L'adaptation française de ce document a été réalisée dans le cadre
    du <citetitle>Projet de traduction de la Gazette Linux</citetitle>.</para>

    <para>Vous pourrez lire d'autres articles traduits et en apprendre plus
    sur ce projet en visitant notre site : <ulink
    url="http://www.traduc.org/Gazette_Linux"/>.</para>

    <para>Si vous souhaitez apporter votre contribution, n'hésitez pas à nous
    rejoindre, nous serons heureux de vous accueillir.</para>
  </colophon>
</article>
