محاكاة Linus Torvalds: قم بإنشاء نظام التشغيل الخاص بك من البداية (II)

مرحبًا بكم في منشور آخر حول كيفية إنشاء نظام التشغيل الخاص بنا ، في هذه الحالة NextDivel.

إذا أخذنا الرمز من أول مشاركة في نهاية كل شيء يجب أن نحصل على شيء مثل هذا:

المستوى التالي -1

إذا كان هذا صحيحا يمكننا الاستمرار. سأستخدم النظام والبنية لدي على GitHub (http://github.com/AdrianArroyoCalle/next-divel) لأنه أكثر راحة لي ولك. كما ترى ، النص هو نص أساسي ، فهو ليس جذابًا. قد يبدو وكأنه شيء أكثر من العادي. ولكن كما يقول المثل ، لأذواق الألوان ، وفي نظام التشغيل لدينا ستكون هناك ألوان. ستكون الألوان الأولى التي سنكون قادرين على وضعها هي تلك التي تحدد بطاقات VGA وهناك 0:

  1. أسود
  2. أزرق
  3. أخضر
  4. السماوي
  5. أحمر
  6. أرجواني
  7. أسمر
  8. رمادي فاتح
  9. رمادي غامق
  10. أزرق فاتح
  11. أخضر فاتح
  12. ضوء سماوي
  13. أحمر فاتح
  14. أرجواني فاتح
  15. بني فاتح
  16. أبيض

سنقوم بتعريف هذه الألوان في رأس لجعلها في متناول اليد وربما في المستقبل لتكون جزءًا من واجهة برمجة تطبيقات النظام. لذلك قمنا بإنشاء ملف 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 الخاص بي هو نسخة/لصق من الملف 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

وقد صنعنا واجهة المستخدم الرسومية الصغيرة هذه فقط من خلال هذه الوظائف:

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 لهذا المثال؟
    دائما ما يعطيني أخطاء في المحطة