Эмуляцыя Лінуса Торвальда: Стварыце ўласную аперацыйную сістэму з нуля (II)

Сардэчна запрашаем у чарговы пост пра тое, як стварыць уласную аперацыйную сістэму, у дадзеным выпадку NextDivel.

Калі мы вернемся да кода першы пост напрыканцы ўсяго мы павінны былі прыдумаць нешта накшталт гэтага:

NextDivel-1

Калі гэта правільна, мы можам працягваць. Я збіраюся выкарыстаць сістэму і структуру, якія ёсць у мяне на GitHub (http://github.com/AdrianArroyoCalle/next-divel), так як гэта зручней і мне, і вам. Як бачыце, тэкст - асноўны тэкст, ён не прывабны. Гэта можа здацца чымсьці незвычайным. Але, як гаворыцца, каб паспрабаваць колеры, і ў нашай аперацыйнай сістэме будуць колеры. Першыя колеры, якія мы зможам паставіць, будуць тымі, якія вызначаюць карты VGA, а іх 0:

  1. Чорны
  2. Azul
  3. зялёны
  4. Блакітны
  5. Чырвоны
  6. Пурпурны
  7. карычневы
  8. Светла-шэры
  9. Цёмна-шэры
  10. Светла-блакітны
  11. Светла-зялёны
  12. Блакітна-чысты
  13. Светла-чырвоны
  14. Светла-пурпурны
  15. Светла карычневы
  16. Белы

Мы збіраемся вызначыць гэтыя колеры ў загалоўку, каб зрабіць яго больш зручным і, магчыма, у будучыні стаць часткай сістэмнага API. Такім чынам, мы ствараем файл ND_Colors.hpp у 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

У той жа час мы збіраемся вызначыць новыя функцыі для больш зручнага запісу на экране (не, мы пакуль не збіраемся рэалізоўваць 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 - гэта копія / устаўка файла з 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");

І калі мы будзем прытрымлівацца гэтых крокаў, мы атрымаем такі вынік

NextDivel-3

Дзякуючы гэтым функцыям, якія мы стварылі, мы можам пачаць рабіць невялікія графічныя інтэрфейсы, напрыклад, паніку ядра, якую мы будзем паказваць кожны раз, калі будзе непапраўная памылка. Нешта накшталт гэтага:

NextDivel-4

І гэты маленькі графічны інтэрфейс мы зрабілі толькі з такімі функцыямі:

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

І карыстаюся выпадкам, каб падзякаваць вас за выдатны прыём, які быў зроблены ў першым паведамленні.


Змест артыкула адпавядае нашым прынцыпам рэдакцыйная этыка. Каб паведаміць пра памылку, націсніце тут.

5 каментарыяў, пакіньце свой

Пакіньце свой каментар

Ваш электронны адрас не будзе апублікаваны.

*

*

  1. Адказны за дадзеныя: Мігель Анхель Гатон
  2. Прызначэнне дадзеных: Кантроль спаму, кіраванне каментарыямі.
  3. Легітымнасць: ваша згода
  4. Перадача дадзеных: Дадзеныя не будуць перададзены трэцім асобам, за выключэннем юрыдычных абавязкаў.
  5. Захоўванне дадзеных: База дадзеных, размешчаная Occentus Networks (ЕС)
  6. Правы: у любы час вы можаце абмежаваць, аднавіць і выдаліць сваю інфармацыю.

  1.   F3niX сказаў

    Выдатны сябар, нават таму я забіваю свой шлем, разумеючы код на C ++.

    Прывітанне.

  2.   пандакрысы сказаў

    гэтыя прадметы выдатныя. яны зноў выклікалі маё цікаўнасць да нізкай прадукцыйнасці працэсараў.
    магчыма, калі ў мяне будзе час, я пачну гуляць з наступным дайвэлам.
    Я даўно не дасылаў артыкул. ужо патрэбны

  3.   Джон нары сказаў

    Добра, гэта шлях.

  4.   Мігель сказаў

    Я даўно хацеў ведаць, як пабудаваць аперацыйную сістэму.

    Чакаю вашага наступнага допісу. На ўра

  5.   Юльян сказаў

    Вялікі сябар!
    У мяне проста адна праблема, ці можа хто-небудзь перадаць мне файл C гэтага прыкладу?
    Ён заўсёды пасылае мне памылкі ў тэрмінале

bool (праўда)