Emulácia Linusa Torvaldsa: Vytvorte si úplne nový operačný systém (II)

Vitajte v ďalšom príspevku o tom, ako vytvoriť náš vlastný operačný systém, v tomto prípade NextDivel.

Ak sa vrátime ku kódu prvý príspevok na konci všetkého by sme mali vymyslieť niečo také:

ĎalejDivel-1

Ak je to správne, môžeme pokračovať. Budem používať systém a štruktúru, ktorú mám na GitHub (http://github.com/AdrianArroyoCalle/next-divel) pretože je to pre mňa aj pre vás pohodlnejšie. Ako vidíte, text je základný, nie je atraktívny. Môže sa to zdať ako niečo neobvyklé. Ale ako sa hovorí, ochutnať farby a v našom operačnom systéme budú farby. Prvé farby, ktoré budeme môcť dať, budú tie, ktoré definujú VGA karty a sú 0:

  1. čierna
  2. Azul
  3. Zelený
  4. Azúrová
  5. Červený
  6. Purpurová
  7. hnedý
  8. Svetlosivá
  9. Tmavo-sivá
  10. Svetlo modrá
  11. Svetlo zelená
  12. Azúrová jasná
  13. Bledo-červená
  14. Svetlo purpurová
  15. Svetlo hnedá
  16. Blanco

Budeme tieto farby definovať v hlavičke, aby sme ich mali praktickejšie a možno sa v budúcnosti stanú súčasťou systémového API. Takže v súbore NextDivel vytvoríme súbor ND_Colors.hpp.

#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

Zároveň sa chystáme definovať nové funkcie, ktoré sa majú písať na obrazovku pohodlnejším spôsobom (nie, zatiaľ nebudeme implementovať printf, viem, že to chcete). Vytvoríme súbor a jeho hlavičku pre množinu funkcií týkajúcich sa obrazovky (ND_Screen.cpp a ND_Screen.hpp). V nich vytvoríme funkcie na: zmenu farby písmen a pozadia, písanie fráz a písmen, čistenie obrazovky a pohyb po obrazovke. Pokračujeme v používaní obrazoviek VGA, ale teraz použijeme niekoľko bajtov, ktoré poskytnú farbu. ND_Screen.cpp bude vyzerať takto:

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

Hlavička bude veľmi základná, takže ju sem nezahŕňam, ale zvýrazním definíciu typu 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).

Aby sme vyskúšali, či tento kód funguje, upravíme vstupný bod C jadra:

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

Ak by sme postupovali podľa týchto krokov, dosiahli by sme tento výsledok

ĎalejDivel-3

Vďaka týmto funkciám, ktoré sme vytvorili, môžeme začať vytvárať malé grafické užívateľské rozhrania, napríklad paniku jadra, ktorú ukážeme vždy, keď dôjde k neodstrániteľnej chybe. Niečo také:

ĎalejDivel-4

A toto malé GUI sme zvládli iba pomocou týchto funkcií:

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

A tu príspevok. Pripomínam vám pokyny na zostavenie systému z 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

A pri tejto príležitosti sa chcem poďakovať za vynikajúce prijatie, ktoré mal prvý príspevok.


Zanechajte svoj komentár

Vaša e-mailová adresa nebude zverejnená. Povinné položky sú označené *

*

*

  1. Zodpovedný za údaje: Miguel Ángel Gatón
  2. Účel údajov: Kontrolný SPAM, správa komentárov.
  3. Legitimácia: Váš súhlas
  4. Oznamovanie údajov: Údaje nebudú poskytnuté tretím stranám, iba ak to vyplýva zo zákona.
  5. Ukladanie dát: Databáza hostená spoločnosťou Occentus Networks (EU)
  6. Práva: Svoje údaje môžete kedykoľvek obmedziť, obnoviť a vymazať.

  1.   f3niX dijo

    Vynikajúci priateľ, aj napriek tomu zabíjam helmu tým, že rozumiem kódu v c ++.

    Zdravím.

  2.   pandacriss dijo

    tieto položky sú skvelé. Znovu vzbudili moju zvedavosť ohľadom nízkej úrovne procesorov.
    mozno ak budem mat cas zacnem hrat s next-divel.
    Dlho som neposielal článok. už potrebné

  3.   Jon sa zahrabáva dijo

    Dobre, tak to je.

  4.   miguel dijo

    Už dávno som chcel vedieť, ako zostaviť operačný systém.

    Čaká sa na váš ďalší príspevok. Na zdravie

  5.   Giuliano dijo

    Dobrý kamarát!
    Mám len jeden problém, môže mi niekto odovzdať súbor C tohto príkladu?
    Vždy mi pošle chyby v termináli