Emulera Linus Torvalds: Skapa ditt eget operativsystem från grunden (II)

Välkommen till ett annat inlägg om hur vi skapar vårt eget operativsystem, i det här fallet NextDivel.

Om vi ​​går tillbaka till koden för första inlägget i slutet av allt borde vi ha kommit på något liknande:

Nästa nivå-1

Om detta är korrekt kan vi fortsätta. Jag ska använda systemet och strukturen som jag har på GitHub (http://github.com/AdrianArroyoCalle/next-divel) eftersom det är bekvämare för mig och för dig. Som du kan se är texten en grundtext, den är inte attraktiv. Det kan verka som något ovanligt. Men som ordspråket säger, att smaka på färger, och i vårt operativsystem kommer det att finnas färger. De första färgerna som vi kommer att kunna sätta kommer att vara de som definierar VGA-korten och de är 0:

  1. svart
  2. blå
  3. grön
  4. Cyan
  5. röd
  6. Magenta
  7. brun
  8. Ljusgrå
  9. Mörkgrå
  10. Ljusblå
  11. Ljusgrön
  12. Cyan klart
  13. Ljusröd
  14. Ljus magenta
  15. Ljusbrun
  16. vit

Vi kommer att definiera dessa färger i en rubrik för att ha det mer praktiskt och kanske i framtiden bli en del av system-API. Så vi skapar filen ND_Colors.hpp i 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

Samtidigt kommer vi att definiera nya funktioner för att skriva på skärmen på ett bekvämare sätt (nej, vi ska inte implementera printf ännu, jag vet att du vill ha det). Vi skapar en fil och dess rubrik för en uppsättning skärmrelaterade funktioner (ND_Screen.cpp och ND_Screen.hpp). I dem skapar vi funktioner för att: ändra bokstävernas färg och bakgrunden, skriva meningar och bokstäver, rengöra skärmen och flytta runt på skärmen. Vi fortsätter att använda VGA-skärmarna men nu använder vi några byte som ger färgen. ND_Screen.cpp skulle se ut:

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

Rubriken kommer att vara väldigt grundläggande så jag tar inte med den här utan markerar definitionen av typen ND_SIDE

typedef enum ND_SIDE{
ND_SIDE_BACKGROUND,
ND_SIDE_FOREGROUND
} ND_SIDE;

Nämn också att vi använder rubriken ND_Types.hpp, denna rubrik definierar några grundläggande typer för uint8_t, uint16_t, etc. baserat på char och int. Egentligen är den här rubriken den i C99-standarden och i själva verket är min ND_Types.hpp en kopia/klistra in av filen desde Linux, så att du kan byta dem och ingenting skulle hända (det finns bara definitioner, inga funktioner).

För att testa om den här koden fungerar kommer vi att ändra C-ingångspunkten för kärnan:

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

Och om vi följer dessa steg skulle vi få detta resultat

Nästa nivå-3

Tack vare dessa funktioner som vi har skapat kan vi börja göra små GUI, till exempel en kärnpanik som vi kommer att visa varje gång det finns ett oåtervinnbart fel. Något som det här:

Nästa nivå-4

Och den här lilla GUI: n gjorde vi bara med dessa funktioner:

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

Och upp till här inlägget. Jag påminner dig om instruktionerna för att kompilera systemet från 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

Och jag tar tillfället i akt och tackar dig för det utmärkta mottagandet som det första inlägget hade.


Lämna din kommentar

Din e-postadress kommer inte att publiceras. Obligatoriska fält är markerade med *

*

*

  1. Ansvarig för uppgifterna: Miguel Ángel Gatón
  2. Syftet med uppgifterna: Kontrollera skräppost, kommentarhantering.
  3. Legitimering: Ditt samtycke
  4. Kommunikation av uppgifterna: Uppgifterna kommer inte att kommuniceras till tredje part förutom enligt laglig skyldighet.
  5. Datalagring: databas värd för Occentus Networks (EU)
  6. Rättigheter: När som helst kan du begränsa, återställa och radera din information.

  1.   f3niX sade

    Utmärkt vän, ändå dödar jag min hjälm med att förstå koden i c ++.

    Hälsningar.

  2.   pandacriss sade

    dessa saker är fantastiska. de har väckt min nyfikenhet på processornas låga prestanda än en gång.
    kanske om jag har tid kommer jag att börja spela med nästa divel.
    Jag har inte skickat en artikel på länge. redan behövs

  3.   Jon gräver sig sade

    Okej, så är det.

  4.   miguel sade

    Jag har länge velat veta hur man bygger ett operativsystem.

    Väntar på ditt nästa inlägg. Skål

  5.   Julian sade

    Bra vän!
    Jag har bara ett problem, kan någon skicka mig en fil i C i det här exemplet?
    Det skickar mig alltid fel i terminalen