Linus Torvaldsのエミュレート:独自のオペレーティングシステムを最初から作成する(II)

独自のオペレーティングシステム(この場合はNextDivel)を作成する方法に関する別の投稿へようこそ。

コードに戻ると 最初の投稿 すべての終わりに、私たちは次のようなものを思い付くはずでした:

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. ブランコ

これらの色をヘッダーで定義して、より便利にし、将来的にはシステム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は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");

そして、これらの手順に従うと、この結果が得られます

NextDivel-3

私たちが作成したこれらの関数のおかげで、回復不能なエラーが発生するたびに表示されるカーネルパニックなどの小さなGUIの作成を開始できます。 このようなもの:

NextDivel-4

そして、この小さな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

そして、この場をお借りして、最初の投稿の素晴らしいレセプションに感謝します。


記事の内容は、次の原則に準拠しています。 編集倫理。 エラーを報告するには、 ここで.

5コメント、あなたのコメントを残してください

コメントを残す

あなたのメールアドレスが公開されることはありません。 必須フィールドには付いています *

*

*

  1. データの責任者:MiguelÁngelGatón
  2. データの目的:SPAMの制御、コメント管理。
  3. 正当化:あなたの同意
  4. データの伝達:法的義務がある場合を除き、データが第三者に伝達されることはありません。
  5. データストレージ:Occentus Networks(EU)がホストするデータベース
  6. 権利:いつでも情報を制限、回復、削除できます。

  1.   F3niX

    素晴らしい友達ですが、それでも私はc ++のコードを理解してヘルメットを殺しています。

    ご挨拶。

  2.   パンダクリス

    これらのアイテムは素晴らしいです。 彼らは、プロセッサの低レベルのパフォーマンスについての私の好奇心を再び刺激しました。
    時間があれば、次のディベルで遊び始めるかもしれません。
    私は長い間記事を送っていません。 すでに必要

  3.   ジョンの穴

    よし、そうだ。

  4.   ミゲル

    私は長い間、オペレーティングシステムの構築方法を知りたいと思っていました。

    次の投稿を待っています。 乾杯

  5.   ジュリアーノ

    親友!
    問題がXNUMXつだけあります。誰かが、この例のCファイルを渡してくれますか?
    それは常に私にターミナルでエラーを送ります