Kendi işletim sistemimizi, bu durumda NextDivel'i nasıl oluşturacağımızla ilgili başka bir yazıya hoş geldiniz.
Koduna dönersek ilk sonrası Her şeyin sonunda şöyle bir şeye sahip olmalıydık:
Eğer bu doğruysa devam edebiliriz. GitHub'da sahip olduğum sistemi ve yapıyı kullanacağım (http://github.com/AdrianArroyoCalle/next-divel) çünkü benim için ve senin için daha rahat. Gördüğünüz gibi metin temel metindir, çekici değildir. Daha sıradan bir şey gibi görünebilir. Ama söylendiği gibi zevklere uygun renkler var ve bizim işletim sistemimizde de renkler olacak. Koyabileceğimiz ilk renkler VGA kartlarını tanımlayan renkler olacak ve 0 tane var:
- Zenci
- mavi
- Yeşil
- Mavi
- Rojo
- eflatun
- kahverengi
- Açık gri
- Koyu gri
- Açık mavi
- Açık yeşil
- açık cam göbeği
- Açık kırmızı
- açık eflatun
- Açık kahverengi
- Blanco
Bu renkleri daha kolay ulaşılabilir hale getirmek ve belki de gelecekte sistemin API'sinin bir parçası olmak için bir başlıkta tanımlayacağız. Böylece NextDivel içeriğinde ND_Colors.hpp dosyasını oluşturuyoruz.
#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
Aynı zamanda ekrana daha rahat yazabilmeniz için yeni fonksiyonlar da tanımlayacağız (hayır, henüz printf uygulamayacağız, istediğinizi biliyorum). Ekranla ilgili bir dizi işlev (ND_Screen.cpp ve ND_Screen.hpp) için bir dosya ve bu dosyanın başlığını oluşturacağız. Bunlarda, harflerin ve arka planın rengini değiştirmek, ifadeler ve harfler yazmak, ekranı temizlemek ve ekranda hareket etmek için işlevler oluşturacağız. VGA ekranları kullanmaya devam ediyoruz ancak artık rengi verecek birkaç byte kullanacağız. ND_Screen.cpp şöyle görünecektir:
/**
* @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;
}
Başlık çok basit olacağından buraya eklemeyeceğim ancak ND_SIDE tipinin tanımını vurgulayacağım.
typedef enum ND_SIDE{
ND_SIDE_BACKGROUND,
ND_SIDE_FOREGROUND
} ND_SIDE;
Ayrıca ND_Types.hpp başlığını kullandığımızı da belirtelim, bu başlık uint8_t, uint16_t vb. için char ve int'ye dayalı bazı temel türleri tanımlar. Aslında bu başlık C99 standardındaki başlıktır ve aslında benim ND_Types.hpp dosyam dosyanın bir kopyası/yapıştırmasıdır desde Linux, böylece onları değiştirebilirsiniz ve hiçbir şey olmaz (yalnızca tanımlar vardır, işlevler yoktur).
Bu kodun çalışıp çalışmadığını test etmek için çekirdeğin C giriş noktasını değiştireceğiz:
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");
Ve eğer bu adımları takip edersek bu sonucu elde ederiz
Oluşturduğumuz bu işlevler sayesinde, her kurtarılamaz hata olduğunda göstereceğimiz çekirdek paniği gibi küçük GUI'ler yapmaya başlayabiliriz. Bunun gibi bir şey:
Ve bu küçük GUI'yi yalnızca şu işlevlerle yaptık:
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);
}
Ve bu yazı için bu kadar. Sistemi sıfırdan derleme talimatlarını size hatırlatıyorum:
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
Ve bu fırsatı kullanarak, ilk gönderinin gösterdiği mükemmel karşılama için size teşekkür etmek istiyorum.
Mükemmel dostum, böyle devam et, C++ kodunu anlayarak kendimi öldürüyorum.
Selamlar.
Bu öğeler harika. İşlemcilerin düşük seviyede çalışmasına dair merakımı bir kez daha uyandırdılar.
Belki zamanım olursa bir sonraki seviyeyle oynamaya başlarım.
Bir süredir makale göndermiyorum. zaten gerekli
Pekâlâ, yol budur.
Uzun zamandır bir işletim sisteminin nasıl oluşturulacağını bilmek istiyordum.
Bir sonraki yazınızı bekliyorum. Selamlar
Harika arkadaş!
Sadece bir sorunum var, birisi bana bu örneğin C dosyasını verebilir mi?
Bana her zaman terminalde hatalar gönderiyor