Емулиране на Linus Torvalds: Създайте своя собствена операционна система от нулата (II)

Добре дошли в друга публикация за това как да създадем наша собствена операционна система, в този случай NextDivel.

Ако се върнем към кода на първа публикация в края на всичко трябваше да измислим нещо подобно:

Следващо ниво-1

Ако това е вярно, можем да продължим. Ще използвам системата и структурата, които имам на GitHub (http://github.com/AdrianArroyoCalle/next-divel), тъй като е по-удобно за мен и за вас. Както можете да видите, текстът е основен текст, той не е привлекателен. Може да изглежда като нещо необичайно. Но както се казва, за да вкусите цветовете и в нашата операционна система ще има цветове. Първите цветове, които ще можем да поставим, ще бъдат тези, които определят VGA картите и те са 0:

  1. Черен
  2. Azul
  3. Зелен
  4. Cyan
  5. Rojo
  6. пурпурен цвят
  7. кафяв
  8. Светло сиво
  9. Тъмно сиво
  10. Светлосиньо
  11. Светло зелено
  12. Циан ясно
  13. Светло червено
  14. Светло магента
  15. Светлокафяво
  16. Blanco

Ще дефинираме тези цветове в хедър, за да е по-удобен и може би в бъдеще да станем част от системния API. Така че ние създаваме файла ND_Colors.hpp в 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

В същото време ще дефинираме нови функции за писане на екрана по по-удобен начин (не, все още няма да внедрим printf, знам, че го искате). Ще създадем файл и заглавката му за набор от свързани с екрана функции (ND_Screen.cpp и ND_Screen.hpp). В тях ще създадем функции за: промяна на цвета на буквите и фона, писане на фрази и букви, почистване на екрана и придвижване по екрана. Продължаваме да използваме VGA екраните, но сега ще използваме няколко байта, които ще дадат цвета. ND_Screen.cpp ще изглежда така:

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

Заглавката ще бъде много основна, така че не я включвам тук, но подчертавам дефиницията на типа ND_SIDE

typedef enum ND_SIDE{
ND_SIDE_BACKGROUND,
ND_SIDE_FOREGROUND
} ND_SIDE;

Споменете също, че използваме заглавката ND_Types.hpp, тази заглавка дефинира някои основни типове за uint8_t, uint16_t и т.н. въз основа на char и int. Всъщност този хедър е този в стандарта C99 и всъщност моят ND_Types.hpp е копие/поставяне на файла desde Linux, така че можете да ги обменяте и нищо няма да се случи (има само дефиниции, няма функции).

За да проверим дали този код работи, ще модифицираме C входната точка на ядрото:

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

И ако следваме тези стъпки, ще получим този резултат

Следващо ниво-3

Благодарение на тези функции, които сме създали, можем да започнем да правим малки графични интерфейси, като паника в ядрото, която ще показваме всеки път, когато има невъзстановима грешка. Нещо като това:

Следващо ниво-4

И този малък GUI го направихме само с тези функции:

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

И тук публикацията. Припомням ви инструкциите за компилиране на системата от 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

И използвам случая, за да ви благодаря за отличния прием, който имаше първият пост.


Оставете вашия коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *

*

*

  1. Отговорен за данните: Мигел Анхел Гатон
  2. Предназначение на данните: Контрол на СПАМ, управление на коментари.
  3. Легитимация: Вашето съгласие
  4. Съобщаване на данните: Данните няма да бъдат съобщени на трети страни, освен по законово задължение.
  5. Съхранение на данни: База данни, хоствана от Occentus Networks (ЕС)
  6. Права: По всяко време можете да ограничите, възстановите и изтриете информацията си.

  1.   f3niX каза той

    Отличен приятел, въпреки че убивам каската си, разбирайки кода в c ++.

    Поздрави.

  2.   пандакриси каза той

    тези артикули са страхотни. отново предизвикаха любопитството ми към ниското ниво на производителност на процесорите.
    Може би, ако имам време, ще започна да играя със следващото дивел.
    Отдавна не съм изпращал статия. вече е необходимо

  3.   Джон рови каза той

    Добре, това е начинът.

  4.   Мигел каза той

    Отдавна исках да знам как да изградя операционна система.

    В очакване на следващата ви публикация. Наздраве

  5.   Джулиано каза той

    Добър приятел!
    Просто имам един проблем, може ли някой да ми предаде C файл от този пример?
    Винаги ми изпраща грешки в терминала