חיקוי לינוס טורוואלדס: צור מערכת הפעלה משלך מאפס (II)

ברוך הבא לפוסט אחר כיצד ליצור מערכת הפעלה משלנו, במקרה זה NextDivel.

אם נחזור לקוד של ה- פוסט ראשון בסוף כל דבר היינו צריכים להמציא משהו כזה:

רמה הבאה-1

אם זה נכון אנחנו יכולים להמשיך. אני הולך להשתמש במערכת ובמבנה שיש לי ב- GitHub (http://github.com/AdrianArroyoCalle/next-divel) כיוון שזה יותר נוח לי ולך. כפי שאתה יכול לראות הטקסט הוא טקסט בסיסי, הוא לא מושך. זה אולי נראה כמו משהו חריג. אבל כמו שנאמר, לטעום צבעים, ובמערכת ההפעלה שלנו יהיו צבעים. הצבעים הראשונים שנוכל לשים יהיו אלה שמגדירים את כרטיסי ה- VGA והם 0:

  1. שחור
  2. Azul
  3. ירוק
  4. ציאן
  5. Rojo
  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;

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");

ואם נבצע את השלבים הבאים היינו מקבלים את התוצאה הזו

רמה הבאה-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 (EU)
  6. זכויות: בכל עת תוכל להגביל, לשחזר ולמחוק את המידע שלך.

  1.   f3niX דיג'ו

    חבר מצוין, למרות זאת אני הורג את הקסדה שלי בהבנת הקוד ב- c ++.

    ברכות.

  2.   פנדאקריס דיג'ו

    הפריטים האלה נהדרים. הם עוררו את סקרנותי לגבי הביצועים הנמוכים של המעבדים שוב.
    אולי אם יהיה לי זמן אתחיל לשחק עם המשחק הבא.
    הרבה זמן לא שלחתי מאמר. כבר צריך

  3.   ג'ון מתחפר דיג'ו

    בסדר, זו הדרך.

  4.   מיגל דיג'ו

    הרבה זמן רציתי לדעת לבנות מערכת הפעלה.

    מחכה לפוסט הבא שלך. לחיים

  5.   ג'וליאנו דיג'ו

    חבר נהדר!
    יש לי רק בעיה אחת, האם מישהו יכול להעביר לי קובץ C של הדוגמה הזו?
    זה תמיד שולח לי שגיאות במסוף