Ласкаво просимо до іншого допису про те, як створити власну операційну систему, в даному випадку NextDivel.
Якщо повернутися до коду перший пост наприкінці всього, що ми мали б придумати щось подібне:
Якщо це правильно, ми можемо продовжувати. Я збираюся використовувати систему та структуру, які я маю на GitHub (http://github.com/AdrianArroyoCalle/next-divel), так як це зручніше і мені, і вам. Як бачите, текст є основним текстом, він не привабливий. Це може здатися чимось незвичним. Але, як говориться, смакувати кольори, і в нашій операційній системі будуть кольори. Першими кольорами, які ми зможемо поставити, будуть ті, що визначають VGA-карти, а їх 0:
- Чорний
- Azul
- зелений
- Блакитний
- Червоний
- фуксин
- Коричневий
- Світло-сірий
- Темно-сірий
- Світло-блакитний
- Світло-зелений
- Блакитний чистий
- Світло-червоний
- Світло-пурпуровий
- Світло-коричневий
- Blanco
Ми визначимо ці кольори в заголовку, щоб він був зручнішим і, можливо, в майбутньому став частиною системного 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;
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).
Щоб перевірити, чи працює цей код, ми збираємось змінити точку входу 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");
І якщо ми виконаємо ці кроки, ми отримаємо такий результат
Завдяки цим функціям, які ми створили, ми можемо почати створювати невеликі графічні інтерфейси, такі як паніка ядра, яку ми будемо показувати щоразу, коли виникає невиправна помилка. Щось на зразок цього:
І цей маленький графічний інтерфейс ми зробили з цими функціями:
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
І я користуюся нагодою, щоб подякувати вам за чудовий прийом, який пройшов перший пост.
Чудовий друг, навіть тому я вбиваю свій шолом, розуміючи код на C ++.
Привіт.
ці предмети чудові. Вони ще раз викликали у мене цікавість щодо низької продуктивності процесорів.
можливо, якщо у мене буде час, я почну грати з наступним дайвелом.
Я давно не надсилав статті. вже потрібні
Гаразд, це шлях.
Я давно хотів знати, як побудувати операційну систему.
Чекаю вашого наступного допису. Ура
Чудовий друг!
У мене просто одна проблема, чи може хтось передати мені файл C цього прикладу?
Він завжди надсилає мені помилки в терміналі