Posnemanje Linusa Torvaldsa: ustvarite svoj operacijski sistem iz nič (II)

Dobrodošli v drugi objavi o tem, kako ustvariti lasten operacijski sistem, v tem primeru NextDivel.

Če se vrnemo k kodi prva objava na koncu vsega, kar bi morali izmisliti nekaj takega:

NaprejDivel-1

Če je to pravilno, lahko nadaljujemo. Uporabil bom sistem in strukturo, ki ga imam na GitHubu (http://github.com/AdrianArroyoCalle/next-divel), saj je zame in vas bolj udobno. Kot lahko vidite, je besedilo osnovno besedilo, vendar ni privlačno. Morda se zdi nekaj nenavadnega. A kot rečeno, okusimo barve in v našem operacijskem sistemu bodo tudi barve. Prve barve, ki jih bomo lahko postavili, bodo tiste, ki določajo kartice VGA in so 0:

  1. Črno
  2. Azul
  3. Zelena
  4. Cijan
  5. Rdeča
  6. Magenta
  7. Rjava
  8. Svetlo siva
  9. Temno siva
  10. Svetlo modra
  11. Svetlo zelena
  12. Cyan jasno
  13. Svetlo rdeča
  14. Svetlo magenta
  15. Svetlo rjava
  16. Blanco

Te barve bomo opredelili v glavi, da bo bolj priročna in bo morda v prihodnosti postala del sistemskega API-ja. Torej ustvarimo datoteko ND_Colors.hpp v 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

Hkrati bomo opredelili nove funkcije za bolj udobno pisanje na zaslon (ne, printf še ne bomo izvajali, vem, da si to želite). Ustvarili bomo datoteko in njeno glavo za nabor funkcij, povezanih z zaslonom (ND_Screen.cpp in ND_Screen.hpp). V njih bomo ustvarili funkcije za: spreminjanje barve črk in ozadja, pisanje stavkov in črk, čiščenje zaslona in premikanje po zaslonu. Še naprej uporabljamo zaslone VGA, zdaj pa bomo uporabili nekaj bajtov, ki bodo dali barvo. ND_Screen.cpp bi bil videti tako:

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

Glava bo zelo osnovna, zato je tukaj ne vključujem, ampak poudarjam definicijo tipa ND_SIDE

typedef enum ND_SIDE{
ND_SIDE_BACKGROUND,
ND_SIDE_FOREGROUND
} ND_SIDE;

También mencionar que hacemos uso del header ND_Types.hpp, este header nos define unos tipos básicos para uint8_t, uint16_t, etc basado en los char y los int. Realmente este header es el en el estándar C99 y de hecho mi ND_Types.hpp es un copia/pega del archivo desde Linux, así que podeis intercambiarlos y no pasaría nada (solo hay definiciones, ninguna función).

Če želite preizkusiti, ali ta koda deluje, bomo spremenili vstopno točko C jedra:

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

In če sledimo tem korakom, bi dobili ta rezultat

NaprejDivel-3

Zahvaljujoč tem funkcijam, ki smo jih ustvarili, lahko začnemo ustvarjati majhne GUI-je, kot je panika v jedru, ki jo bomo prikazali vsakič, ko pride do nepopravljive napake. Nekaj ​​podobnega:

NaprejDivel-4

In ta mali GUI smo naredili samo s temi funkcijami:

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

In do tukaj objava. Spomnim vas na navodila za sestavljanje sistema od 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

Ob tej priložnosti se vam zahvaljujem za odličen sprejem prvega prispevka.


Pustite svoj komentar

Vaš e-naslov ne bo objavljen. Obvezna polja so označena z *

*

*

  1. Za podatke odgovoren: Miguel Ángel Gatón
  2. Namen podatkov: Nadzor neželene pošte, upravljanje komentarjev.
  3. Legitimacija: Vaše soglasje
  4. Sporočanje podatkov: Podatki se ne bodo posredovali tretjim osebam, razen po zakonski obveznosti.
  5. Shranjevanje podatkov: Zbirka podatkov, ki jo gosti Occentus Networks (EU)
  6. Pravice: Kadar koli lahko omejite, obnovite in izbrišete svoje podatke.

  1.   f3niX je dejal

    Odličen prijatelj, tudi zato ubijam svojo čelado, saj razumem kodo v jeziku C ++.

    Lep pozdrav.

  2.   pandakri je dejal

    ti predmeti so super. znova so vzbudili mojo radovednost glede nizke zmogljivosti procesorjev.
    mogoče, če imam čas, začnem igrati z naslednjim divelom.
    Že dolgo nisem poslal članka. že potrebno

  3.   Jon zareže je dejal

    V redu, to je pot.

  4.   Miguel je dejal

    Že dolgo sem želel vedeti, kako zgraditi operacijski sistem.

    Čakam na vaš naslednji prispevek. Na zdravje

  5.   Giuliano je dejal

    Odličen prijatelj!
    Imam samo eno težavo, mi lahko nekdo posreduje datoteko C tega primera?
    Vedno mi pošlje napake v terminalu