Linus Torvalds'ı Taklit Etmek: Kendi işletim sisteminizi sıfırdan oluşturun (II)

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:

SonrakiDivel-1

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:

  1. Zenci
  2. mavi
  3. Yeşil
  4. Mavi
  5. Rojo
  6. eflatun
  7. kahverengi
  8. Açık gri
  9. Koyu gri
  10. Açık mavi
  11. Açık yeşil
  12. açık cam göbeği
  13. Açık kırmızı
  14. açık eflatun
  15. Açık kahverengi
  16. 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

SonrakiDivel-3

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:

SonrakiDivel-4

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.


Yorumunuzu bırakın

E-posta hesabınız yayınlanmayacak. Gerekli alanlar ile işaretlenmiştir *

*

*

  1. Verilerden sorumlu: Miguel Ángel Gatón
  2. Verilerin amacı: Kontrol SPAM, yorum yönetimi.
  3. Meşruiyet: Onayınız
  4. Verilerin iletilmesi: Veriler, yasal zorunluluk dışında üçüncü kişilere iletilmeyecektir.
  5. Veri depolama: Occentus Networks (AB) tarafından barındırılan veritabanı
  6. Haklar: Bilgilerinizi istediğiniz zaman sınırlayabilir, kurtarabilir ve silebilirsiniz.

  1.   f3niX dijo

    Mükemmel dostum, böyle devam et, C++ kodunu anlayarak kendimi öldürüyorum.

    Selamlar.

  2.   Pandacriss dijo

    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

  3.   Jon burrows dijo

    Pekâlâ, yol budur.

  4.   miguel dijo

    Uzun zamandır bir işletim sisteminin nasıl oluşturulacağını bilmek istiyordum.

    Bir sonraki yazınızı bekliyorum. Selamlar

  5.   Giuliano dijo

    Harika arkadaş!
    Sadece bir sorunum var, birisi bana bu örneğin C dosyasını verebilir mi?
    Bana her zaman terminalde hatalar gönderiyor