独自のオペレーティング システム (この場合は NextDivel) を作成する方法に関する別の投稿へようこそ。
コードを取得すると、 最初の投稿 すべての最後に、次のような出力が得られるはずです。
これが正しければ、続行できます。 GitHub にあるシステムと構造を使用します (http://github.com/AdrianArroyoCalle/next-divel)それは私にとってもあなたにとってもより快適だからです。 ご覧のとおり、テキストは基本的なテキストであり、魅力的ではありません。 それは普通以上のもののように見えるかもしれません。 しかし、ことわざにあるように、好みには色があり、私たちのオペレーティング システムにも色が存在します。 最初に追加できる色は VGA カードを定義する色で、次の 0 色があります。
- ブラック
- アスル
- ヴェルデ レジデンス (Verde Residence)
- シアン
- ロホ
- マゼンタ
- ブラウン
- ライトグレー
- 暗灰色
- 水色
- 薄緑
- ライトシアン
- ライトレッド
- ライトマゼンタ
- マロンクラロ
- ブランコ
これらの色をヘッダーで定義して、より簡単に使用できるようにし、将来的にはシステム API の一部として使用できるようにする予定です。 そこで、NextDivel インクルード内に ND_Colors.hpp ファイルを作成します。
#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 ヘッダーを使用していることにも言及してください。このヘッダーは、char と int に基づいて uint8_t、uint16_t などのいくつかの基本型を定義します。実際、このヘッダーは 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");
これらの手順に従うと、この結果が得られます
作成したこれらの関数のおかげで、回復不可能なエラーが発生するたびに表示されるカーネル パニックなどの小さな GUI の作成を開始できるようになります。 このようなもの:
そして、次の機能のみを使用してこの小さな GUI を作成しました。
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 ファイルを送ってくれませんか?
ターミナルで常にエラーが発生します