Émulation de Linus Torvalds: créez votre propre système d'exploitation à partir de zéro (II)

Bienvenue dans un autre article sur la création de notre propre système d'exploitation, dans ce cas NextDivel.

Si nous revenons au code du première publication à la fin de tout, nous aurions dû trouver quelque chose comme ceci:

SuivantDivel-1

Si cela est correct, nous pouvons continuer. Je vais utiliser le système et la structure que j'ai sur GitHub (http://github.com/AdrianArroyoCalle/next-divel) car c'est plus confortable pour moi et vous. Comme vous pouvez le voir, le texte est un texte de base, il n'est pas attrayant. Cela peut sembler quelque chose qui sort de l'ordinaire. Mais comme le dit l'adage, pour goûter les couleurs, et dans notre système d'exploitation, il y aura des couleurs. Les premières couleurs que nous allons pouvoir mettre seront celles qui définissent les cartes VGA et elles sont 0:

  1. Noir
  2. Bleu
  3. Vert
  4. Cyan
  5. Rouge
  6. Magenta
  7. brun
  8. Gris clair
  9. Gris foncé
  10. Light Blue
  11. Vert clair
  12. Cyan clair
  13. Rouge clair
  14. Magenta clair
  15. Brun clair
  16. Blanco

Nous allons définir ces couleurs dans un en-tête pour qu'il soit plus pratique et peut-être à l'avenir faire partie de l'API système. Nous créons donc le fichier ND_Colors.hpp dans l'inclusion NextDivel.

#ifndef ND_COLOR_HPP
#define ND_COLOR_HPP
typedef enum ND_Color{
ND_COLOR_BLACK = 0,
ND_COLOR_BLUE = 1,
ND_COLOR_GREEN = 2,
ND_COLOR_CYAN = 3,
ND_COLOR_RED = 4,
ND_COLOR_MAGENTA = 5,
ND_COLOR_BROWN = 6,
ND_COLOR_LIGHT_GREY = 7,
ND_COLOR_DARK_GREY = 8,
ND_COLOR_LIGHT_BLUE = 9,
ND_COLOR_LIGHT_GREEN = 10,
ND_COLOR_LIGHT_CYAN = 11,
ND_COLOR_LIGHT_RED = 12,
ND_COLOR_LIGHT_MAGENTA = 13,
ND_COLOR_LIGHT_BROWN = 14,
ND_COLOR_WHITE = 15
} ND_Color;
#endif

En même temps, nous allons définir de nouvelles fonctions pour écrire sur l'écran de manière plus confortable (non, nous n'allons pas encore implémenter printf, je sais que vous le souhaitez). Nous allons créer un fichier et son en-tête pour un ensemble de fonctions liées à l'écran (ND_Screen.cpp et ND_Screen.hpp). En eux, nous allons créer des fonctions pour: changer la couleur des lettres et du fond, écrire des phrases et des lettres, nettoyer l'écran et se déplacer sur l'écran. Nous continuons à utiliser les écrans VGA mais nous allons maintenant utiliser quelques octets qui donneront la couleur. ND_Screen.cpp ressemblerait à ceci:

/**
* @file ND_Screen.cpp
* @author Adrián Arroyo Calle
* @brief Implements four easy functions for write strings directly
*/
#include <ND_Types.hpp>
#include <ND_Color.hpp>
#include <ND_Screen.hpp>
uint16_t *vidmem= (uint16_t *)0xB8000;
ND_Color backColour = ND_COLOR_BLACK;
ND_Color foreColour = ND_COLOR_WHITE;
uint8_t cursor_x = 0;
uint8_t cursor_y = 0;
/**
* @brief Gets the current color
* @param side The side to get the color
* */
ND_Color ND::Screen::GetColor(ND_SIDE side)
{
if(side==ND_SIDE_BACKGROUND){
return backColour;
}else{
return foreColour;
}
}
/**
* @brief Sets the color to a screen side
* @param side The side to set colour
* @param colour The new colour
* @see GetColor
* */
void ND::Screen::SetColor(ND_SIDE side, ND_Color colour)
{
if(side==ND_SIDE_BACKGROUND)
{
backColour=colour;
}else{
foreColour=colour;
}
}
/**
* @brief Puts the char on screen
* @param c The character to write
* */
void ND::Screen::PutChar(char c)
{
uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
uint16_t attribute = attributeByte << 8; uint16_t *location; if (c == 0x08 && cursor_x) { cursor_x--; }else if(c == '\r') { cursor_x=0; }else if(c == '\n') { cursor_x=0; cursor_y=1; } if(c >= ' ') /* Printable character */
{
location = vidmem + (cursor_y*80 + cursor_x);
*location = c | attribute;
cursor_x++;
}
if(cursor_x >= 80) /* New line, please*/
{
cursor_x = 0;
cursor_y++;
}
/* Scroll if needed*/
uint8_t attributeByte2 = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
uint16_t blank = 0x20 /* space */ | (attributeByte2 << 8); if(cursor_y >= 25)
{
int i;
for (i = 0*80; i < 24*80; i++)
{
vidmem[i] = vidmem[i+80];
}
// The last line should now be blank. Do this by writing
// 80 spaces to it.
for (i = 24*80; i < 25*80; i++)
{
vidmem[i] = blank;
}
// The cursor should now be on the last line.
cursor_y = 24;
}
}
/**
* @brief Puts a complete string to screen
* @param str The string to write
* */
void ND::Screen::PutString(const char* str)
{
int i=0;
while(str[i])
{
ND::Screen::PutChar(str[i++]);
}
}
/**
* @brief Cleans the screen with a color
* @param colour The colour to fill the screen
* */
void ND::Screen::Clear(ND_Color colour)
{
uint8_t attributeByte = (colour /*background*/ << 4) | (15 /*white - foreground*/ & 0x0F);
uint16_t blank = 0x20 /* space */ | (attributeByte << 8);
int i;
for (i = 0; i < 80*25; i++)
{
vidmem[i] = blank;
}
cursor_x = 0;
cursor_y = 0;
}
/**
* @brief Sets the cursor via software
* @param x The position of X
* @param y The position of y
* */
void ND::Screen::SetCursor(uint8_t x, uint8_t y)
{
cursor_x=x;
cursor_y=y;
}

L'en-tête sera très basique donc je ne l'inclus pas ici, mais met en évidence la définition du type ND_SIDE

typedef enum ND_SIDE{
ND_SIDE_BACKGROUND,
ND_SIDE_FOREGROUND
} ND_SIDE;

Mentionnez également que nous utilisons l'en-tête ND_Types.hpp, cet en-tête définit certains types de base pour uint8_t, uint16_t, etc. basés sur char et int. En fait cet entête est celui du standard C99 et en fait mon ND_Types.hpp est un copier/coller du fichier desde Linux, vous pouvez donc les échanger et rien ne se passera (il n'y a que des définitions, pas de fonctions).

Pour tester si ce code fonctionne, nous allons modifier le point d'entrée C du noyau:

ND::Screen::Clear(ND_COLOR_WHITE);
ND::Screen::SetColor(ND_SIDE_BACKGROUND,ND_COLOR_WHITE);
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_GREEN);
ND::Screen::PutString("NextDivel\n");
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_BLACK);
ND::Screen::PutString("Licensed under GNU GPL v2");

Et si nous suivons ces étapes, nous obtiendrons ce résultat

SuivantDivel-3

Grâce à ces fonctions que nous avons créées, nous pouvons commencer à créer de petites interfaces graphiques, comme une panique du noyau que nous montrerons à chaque fois qu'il y aura une erreur irrécupérable. Quelque chose comme ça:

SuivantDivel-4

Et cette petite interface graphique nous l'avons créée uniquement avec ces fonctions:

void ND::Panic::Show(const char* error)
{
ND::Screen::Clear(ND_COLOR_RED);
ND::Screen::SetColor(ND_SIDE_BACKGROUND, ND_COLOR_WHITE);
ND::Screen::SetColor(ND_SIDE_FOREGROUND, ND_COLOR_RED);
ND::Screen::SetCursor(29,10); //(80-22)/2
ND::Screen::PutString("NextDivel Kernel Error\n");
ND::Screen::SetCursor(15,12);
ND::Screen::PutString(error);
}

Et voici le post. Je vous rappelle les instructions pour compiler le système à partir de 0:

git clone http://github.com/AdrianArroyoCalle/next-divel
cd next-divel
mkdir build && cd build
cmake ..
make
make DESTDIR=next install
chmod +x iso.sh
./iso.sh
qemu-system-i386 nextdivel.iso

Et j'en profite pour vous remercier de l'excellent accueil qu'a eu le premier post.


Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont marqués avec *

*

*

  1. Responsable des données: Miguel Ángel Gatón
  2. Finalité des données: Contrôle du SPAM, gestion des commentaires.
  3. Légitimation: votre consentement
  4. Communication des données: Les données ne seront pas communiquées à des tiers sauf obligation légale.
  5. Stockage des données: base de données hébergée par Occentus Networks (EU)
  6. Droits: à tout moment, vous pouvez limiter, récupérer et supprimer vos informations.

  1.   f3niX dit

    Excellent ami, même si je tue mon casque en comprenant le code en c ++.

    Salutations.

  2.   pandacriss dit

    ces articles sont super. Ils ont piqué ma curiosité sur les performances de bas niveau des processeurs une fois de plus.
    peut-être que si j'ai le temps, je commencerai à jouer avec next-divel.
    Je n'ai pas envoyé d'article depuis longtemps. déjà nécessaire

  3.   Jon creuse dit

    Très bien, c'est comme ça.

  4.   miguel dit

    J'ai longtemps voulu savoir comment construire un système d'exploitation.

    En attente de votre prochain message. À votre santé

  5.   Giuliano dit

    Bon ami!
    J'ai juste un problème, quelqu'un peut-il me passer un fichier C de cet exemple?
    Ça m'envoie toujours des erreurs dans le terminal