0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

71歳の挑戦... ゼロからのOS自作入門を囓ってみた。osbook_day03cを改造。いくつかわかったこと。

Last updated at Posted at 2025-03-09

 無謀にも「ゼロからのOS自作入門」を購入し挑戦というか、少し囓ってみました。

【追記】USBメモリからの起動はできたのですが問題もありました。
失敗...電源オフ状態でUSBメモリを挿して電源オン、画像がうまく表示されない。
成功...UBUNTUが立ち上がっているときにUSBメモリを挿しておき、再起動をする
コンピュータ本体とディスプレーの信号や相性の関係と思われます。

 ここに至るまでの経緯と環境について触れておきます。

1.windows11(core i5,SSD 500GB)パソコンに、WSL2とUBUNTU20.04を導入。day03あたりまでできることを確認。
2.WSL2での作業が面倒に感じ、他の環境移行を考える。
3.Dockerを使う事例を参考にしてやってみたが私にはよくわからず。
4.無料になったという「VMWare Workstation Pro」を導入し、始めてみた。環境構築もコンパイルもできたが、最後のqemuでの表示ができず、断念。
5.ジャンク品レベルのスモールサイズパソコン(core i3,SSD 120GB)を入手できたので、UBUNTU20.04をインストールし環境構築。現在に至る。
(いやいや何度もインストールやら環境構築やらしました。)

 このようにして順調に行くかと思いましたが、day09bまで進んだところで、もうC++の構文について行けず。単にコンパイル、続くQEMU表示、で喜んでいてもなあ、どうしたものかと悩む。何かちょっとでも自分独自のモノを作りたい。そこで思いついたのが、マンデルブロ集合の描画。以前の投稿です。

これを移植しようと考え、day03c の main.cpp に書き加えてみました。有り難い事に、けっこう簡単に動きました(コードは後ほど示します)。
 他に一つ分かった事があるので触れておきます。QEMUで実行させてみたところ速さが今ひとつ。USBメモリから起動させればもっと速いかもと、やってみました。書籍のp.30、p.34、p.35を参考にUSBメモリ起動を何度も試みるのですが、「kernel.elf」が無いと表示され起動が停止します。最後の手段。WindowsパソコンでLinuxインストール用USBメモリとして作成。その中の、EFI/BOOT/BOOTX64.EFI を置き換えることまでしてみましたが、だめでした。まあいいかと諦めかけ、いつものようにQEMU表示をしておりました。そのときターミナル上を流れる文字をぼんやり見ていて気付きました。/mnt/ つまり /dev/sdb/ の kernel.elf を読みにいってると。早速、コンパイルで作られた

~/workspace/mikanos/kernel/kernel.elf

をUSBメモリのルートにコピーして起動をかけました。表示できました、それも速いです、感動です。
 ついでですが、linux起動時の「GRUB」って良いですね。USBから起動したいとき、今までスイッチオンからのF2キー連打でBIOS画面を出してましたが、GRUBのメニューから入れることを知りました。 今回もいろいろ勉強になりました。でも、私にはやっぱり「C++」は難しいです。マンデルブロ集合を描くように改造した main.cpp を示します。

~/workspace/mikanos/kernel/main.cpp
/**
 * @file main.cpp
 *
 * カーネル本体のプログラムを書いたファイル.
 */

#include <cstdint>
#include <cstddef>

#include "frame_buffer_config.hpp"

//#include <math.h>

// #@@range_begin(write_pixel)
struct PixelColor {
  uint8_t r, g, b;
};

/** WritePixelは1つの点を描画します.
 * @retval 0   成功
 * @retval 非0 失敗
 */
int WritePixel(const FrameBufferConfig& config,
               int x, int y, const PixelColor& c) {
  const int pixel_position = config.pixels_per_scan_line * y + x;
  if (config.pixel_format == kPixelRGBResv8BitPerColor) {
    uint8_t* p = &config.frame_buffer[4 * pixel_position];
    p[0] = c.r;
    p[1] = c.g;
    p[2] = c.b;
  } else if (config.pixel_format == kPixelBGRResv8BitPerColor) {
    uint8_t* p = &config.frame_buffer[4 * pixel_position];
    p[0] = c.b;
    p[1] = c.g;
    p[2] = c.r;
  } else {
    return -1;
  }
  return 0;
}
// #@@range_end(write_pixel)

#define W 480// tft.width()
#define H 320// tft.heght()
#define X0 240//tft.width()/2
#define Y0 160//tft.height()/2

const float absZ = 4.0;       // 発散判定
const uint16_t page = 20;
const uint16_t dp = 2;

// default Mandelbrot Set -----------------------------------------
// viewpW=2.4; CtoX = 0.0; CtoY = 0.0;
// repeat=200; page=1; dp=0;
// ----------------------------------------------------------------

// viewpW = 0.00024; // 10000倍に拡大
// Viewport width; Viewport Center CtoX;CtoY;

// 風景の良い場所例
// example 1
// viewpW = 0.00024; CtoX = -1.24997; CtoY = -0.00877;
// repeat=190; page=28; dp=2;

// example 2
// viewpW = 0.00024; CtoX=-1.401;CtoY=-0.000178;
// repeat=300; page=19; dp=2;

const float viewpW = 0.0012;    // viewport width(window width)
const float di = viewpW / 480.0;// real/imaginary calculation step
                                // 1 pixel in Real and Imaginary number
const float CtoX = -1.19998;    // 現在の表示(viewpW)の中心
const float CtoY = -0.15507;

uint16_t repeat = 120;  // 反復上限、page進行に応じ増加させる
uint16_t k;             // 反復回

float x, y, zr, zi, R, I;//複素計算変数
uint16_t C[800];        // 色配列

uint32_t now, starttime;

uint16_t pi;
int16_t j,i;
uint16_t Xi,Yj;
bool cels[W][H];  // 各セルの発散状況記憶


// #@@range_begin(call_write_pixel)
extern "C"
void KernelMain(const FrameBufferConfig& frame_buffer_config) {
  for (int x = 0; x < frame_buffer_config.horizontal_resolution; ++x) {
    for (int y = 0; y < frame_buffer_config.vertical_resolution; ++y) {
      WritePixel(frame_buffer_config, x, y, {255, 255, 255});
    }
  }
 
  for (int x = 0; x < W; ++x) {
    for (int y = 0; y < H; ++y) {
      WritePixel(frame_buffer_config, x, y, {0, 0, 0});
    }
  }
  
  for (pi = 1; pi <= page; pi++) {// 反復数上限を増やしていく
    for ( j = - Y0; j < Y0; j++) {
      Yj = Y0-j-1;
      y = j * di + CtoY;
      for ( i = - X0; i < X0; i++) {
	Xi = X0 + i;

	if(cels[Xi][Yj]==false){ // 未発散のピクセル(黒)のみ計算
	  x = i * di + CtoX;
	  zr = 0.0;
	  zi = 0.0;
	  k = 0;//-1;
	  do {
	    k++;
	    R = zr * zr - zi * zi + x;
	    I = 2 * zr * zi + y;
	    zr = R;
	    zi = I;
	    if ( k == repeat ) break;
	  } while ( (zr * zr + zi * zi) < absZ );

	  if (k < repeat) {// 新たに発散したピクセルのみ描画

	    WritePixel( frame_buffer_config, Xi, Yj,
			{static_cast<uint8_t>(255 -( k % 255)), // コンパイラが教えてくれた
			 static_cast<uint8_t>(255 - (k % 128)),
			 static_cast<uint8_t>(255 - (k % 64))} );
	    cels[Xi][Yj]=true;
	  }
	}
      }
    }
    repeat += dp * pi;
  }

  for (int x = 0; x < W; ++x) {
    for (int y = H-5; y < H; ++y) {
      WritePixel(frame_buffer_config, x, y, {0, 255, 255});
    }
  }

  while (1) __asm__("hlt");
}
// #@@range_end(call_write_pixel)

 最後までお付き合い頂き有難うございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?