Emulând Linus Torvalds: Creați-vă propriul sistem de operare de la zero (II)

Bine ați venit la o altă postare despre cum să creăm propriul nostru sistem de operare, în acest caz NextDivel.

Dacă ne întoarcem la codul primul post la finalul tuturor lucrurilor ar fi trebuit să venim cu așa ceva:

Următorul Nivel-1

Dacă acest lucru este corect, putem continua. Voi folosi sistemul și structura pe care le am pe GitHub (http://github.com/AdrianArroyoCalle/next-divel) deoarece este mai confortabil pentru mine și pentru tine. După cum puteți vedea, textul este un text de bază, nu este atractiv. Poate părea ceva ieșit din comun. Dar, după cum se spune, pentru a gusta culorile și în sistemul nostru de operare vor exista culori. Primele culori pe care le vom putea pune vor fi cele care definesc cardurile VGA și acestea sunt 0:

  1. Negru
  2. Azul
  3. verde
  4. Cyan
  5. Rojo
  6. Purpuriu
  7. maro
  8. Gri deschis
  9. Gri închis
  10. Albastru deschis
  11. Verde deschis
  12. Cyan clar
  13. Lumina rosie
  14. Magenta deschisă
  15. Maro deschis
  16. Blanco

Vom defini aceste culori într-un antet pentru a le fi mai la îndemână și poate, în viitor, să facem parte din API-ul sistemului. Deci, creăm fișierul ND_Colors.hpp în NextDivel include.

#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

În același timp, vom defini noi funcții pentru a scrie pe ecran într-un mod mai confortabil (nu, nu vom implementa încă printf, știu că îl doriți). Vom crea un fișier și antetul acestuia pentru un set de funcții legate de ecran (ND_Screen.cpp și ND_Screen.hpp). În ele vom crea funcții pentru: schimbarea culorii literelor și a fundalului, scrierea de propoziții și litere, curățarea ecranului și deplasarea pe ecran. Continuăm să folosim ecranele VGA, dar acum vom folosi câțiva octeți care vor da culoarea. ND_Screen.cpp ar arăta astfel:

/**
* @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;
}

Antetul va fi foarte de bază, așa că nu îl includ aici, ci evidențiați definiția tipului ND_SIDE

typedef enum ND_SIDE{
ND_SIDE_BACKGROUND,
ND_SIDE_FOREGROUND
} ND_SIDE;

De asemenea, menționăm că folosim antetul ND_Types.hpp, acest antet definește câteva tipuri de bază pentru uint8_t, uint16_t etc. pe baza char și int. De fapt, acest antet este cel din standardul C99 și, de fapt, ND_Types.hpp-ul meu este o copiere/lipire a fișierului desde Linux, astfel încât să le poți schimba și nu s-ar întâmpla nimic (există doar definiții, fără funcții).

Pentru a testa dacă acest cod funcționează, vom modifica punctul de intrare C al nucleului:

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");

Și dacă urmăm acești pași, am obține acest rezultat

Următorul Nivel-3

Datorită acestor funcții pe care le-am creat, putem începe să creăm mici interfețe grafice, cum ar fi o panică de nucleu pe care o vom arăta de fiecare dată când există o eroare nerecuperabilă. Ceva de genul:

Următorul Nivel-4

Și acest mic GUI l-am realizat numai cu aceste funcții:

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);
}

Și aici postarea. Vă reamintesc instrucțiunile pentru a compila sistemul de la 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

Și profit de această ocazie pentru a vă mulțumi pentru primirea excelentă pe care a avut-o prima postare.


Lasă comentariul tău

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *

*

*

  1. Responsabil pentru date: Miguel Ángel Gatón
  2. Scopul datelor: Control SPAM, gestionarea comentariilor.
  3. Legitimare: consimțământul dvs.
  4. Comunicarea datelor: datele nu vor fi comunicate terților decât prin obligație legală.
  5. Stocarea datelor: bază de date găzduită de Occentus Networks (UE)
  6. Drepturi: în orice moment vă puteți limita, recupera și șterge informațiile.

  1.   f3niX el a spus

    Excelent prieten, chiar și așa îmi ucid casca înțelegând codul în c ++.

    Salutări.

  2.   pandacriss el a spus

    aceste articole sunt grozave. Mi-au stârnit din nou curiozitatea cu privire la performanțele la nivel scăzut ale procesoarelor.
    Poate că dacă am timp voi începe să joc cu next-divel.
    Nu am trimis un articol de mult timp. deja nevoie

  3.   Jon se îngropă el a spus

    Bine, așa este.

  4.   Miguel el a spus

    De mult am vrut să știu cum să fac un sistem de operare.

    Se așteaptă următoarea postare. Noroc

  5.   Giuliano el a spus

    Prieten grozav!
    Am doar o problemă, poate cineva să-mi transmită un fișier în C al acestui exemplu?
    Îmi trimite întotdeauna erori în terminal