Skip to content

「30日でできる!OS自作入門」をmacOSにて開発した際のソースコード。

Notifications You must be signed in to change notification settings

zacfukuda/hariboteos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

30日でできる!OS自作入門 on macOS

同書をmacOSにて開発した際のソースコード。
下のイメージはは30日目終了時の記念撮影。エミュレータ実行のため、vram(シート)に少し異常あり。(基本動作に問題はない)

30日目の成果

著者ソースコード(HariboteOS.zip)

8日目までの開発は、Qittaに投稿されている『30日でできる!OS自作入門』を macOS Catalina で実行するを参照。9日目以降は著者ソースコードを参照。

(余程のミスをしない限り)コードに問題があっても、コンパイラが親切にエラーを出力してくれる。Haribote OSが壊れる、開発PCがフリーズするということはない。

書籍購入

本レポジトリー参照にあたり

  • あくまで私的利用目的
  • 2セクション分を1つのプロジェクトとして一括作業している部分あり
  • 該当セクション終了後にミスを発見・訂正している部分あり。該当セクション時点での簡単なOS動作確認上の不具合は確認されなかった。(下記除く)
  • 多くのコメントを割愛。残したコメントは想定外の文字化けを避けるため英語
  • コメントは//を優先利用
  • 途中で細かな記述方法の変更あり

開発環境

  • PC: MacBook Pro 13-inch 2017
  • OS: macOS Catalina 10.15.7
  • コンパイラ: GCC(i386-elf-gcc) 9.2.0, NASM 2.15.05
  • イメージ作成: mformat 4.0.25, mcopy 4.0.25
  • エミュレータ: QEMU 5.1.0
  • エディタ: Visual Studio Code 1.51 (何でも良いと思うが、UTF-8標準設定のものが無難)

Homebrewから各ソフトウェアをインストールする際、最新のXcodeが必要。最新版Xcodeでは、ターミナルからXcode Command Line Toolのインストールができなくなっており、Apple開発者サイト経由ですることになる。

2020年11月時点で既にCatalinaのアップデートmacOS Big Sur 11が公開されており、加えてアップル独自開発CPUM1搭載のPCも流通している。Big Surでも、(Intel Core ix系搭載のPCであれば、)必要なソフトウェア(GCC, NASM, QEMU, etc.)のインストール・動作ができれば、開発を進められそうである。

不具合・未動作

harib06b, harib06c

問題
memory 128MBと表示される。

対応
エミュレータが自動で割り当てるメモリー量だと解釈。プログラム・OS自体に問題はないと判断し、無視して開発を継続。

harib10c~harib11e

問題
HariMain()for(;;)直下にシートを更新するプログラムが無いと、動作が遅くなる。PIC/PITもしくはCPUクロック数に原因があると推測される。

対応
10秒後ではなく、カウンタ数を常に表示。動作上の意味は無いが10秒後にカウンタ数を表示するプログラムは残してある。尚、この問題はharib11fで高速カウンタを消去し、if文内のio_sti()io_stihlt()に戻した段階で自然解決される。

void HariMain(void) {
  …
  for (;;) {
    count++// このあたり
  }
}

harib11d

問題
asmhead.nasに指定の画面モードをするも、黒い画面が表示されるのみ。コンパイル時のエラーはなし。

対応
harib11eのVBE設定プログラム導入で自然解決される。特に意味はないが、解像度は0x101を利用して開発を進めた。

harib12e~harib13b

問題
task_b_mainfor(;;)直下にシートを更新するプログラムが無いと、動作が遅くなる。harib10c~harib11eと類似した問題。

対応
前回同様、カウンタを常に表示。(if (fifo32_status(&fifo) == 0))内のio_sti()io_stihlt()としてもスムーズな動作はするが、前者と比べてカウントスピードは約1/50になる。

harib13c~harib13g

問題
task_b_mainfor(;;)直下にシートを更新するプログラムが無いと、動作が遅くなる。前項同様の問題。

対応
前項同様、カウンタを常に表示。この問題もharib14bでカウンタを削除した段階で自動解決される。

harib15f

問題
<string.h>がincludeできず、strcmpが使えない。

対応
sprintfに倣い、関数を自作。新たにmyfunction.cを作成し、同ファイルに関数を記述。新規関数・ファイル追加に伴いbootpack.hMakefileに追加記述を施す。strcmpのプログラムはAppleのオープンソースサイトで公開されている。

harib16b

問題
strncmpが使えない。

対応
strcmp同様、myfunction.cに関数自作。bootpack.hに関数定義も追加。参照: Appleのオープンソースサイト

harib17b~harib17d

問題
asm_cons_putcharの番地が本記載のものと異なる。

対応
Makefilebootpack.hrbを生成するコマンドに-Xlinker -Map=bootpack.mapオプションを追加し、マップファイルを生成。bootpack.mapに記載されているasm_cons_putcharの番地を調べ、その値をhlt.nasbe3値と入れ替える。ちなみに自分が実行した際の番地は、c64であった。この値を使用してharib17cを実行した際、正常に「A」が表示された。よくわかない場合、harib17eまでスキップすれば、番地を調べることなく、プログラムを実行できるようになる。

harib18b

問題
a.hrbhello3.hrbの生成。

対応
『30日でできる!OS自作入門』のメモを参照。「アプリケーション用リンカスクリプト」をapp.ldとして保存し、a.hrbhello3.hrb生成時に、これをリンカスクリプトとして利用。リンカスクリプトについては自分も未理解。

harib19c

問題
Shift + F1を押しただけでは強制終了しない。(0x3dが入力されない。)

対応
Macのキーボード設計による問題。Shift + fn + F1で強制終了できる。

harib20b

問題
rand()が使えない。

対応
stars.c内にStack Overflowを参照してrand()を実装。結果的に同書と同じ星が配置された。

harib21a

問題
F11はmacOSにより既にリザーブされている。

対応
F11の代わりにF11(0x58)を使用する。

harib21g

問題
noodle.hrb生成時、以下のエラーが発生される。

/usr/local/Cellar/i386-elf-gcc/9.2.0/lib/gcc/i386-elf/9.2.0/../../../../i386-elf/bin/ld: section .data VMA [0000000000000400,000000000000040f] overlaps section .text VMA [0000000000000030,000000000000048f]
collect2: error: ld returned 1 exit status
make: *** [noodle.hrb] Error 1

対応
良くわからないが、.dataの一部が.textの番地に書き込みされようとしているのが原因。app.ldapp2.ldとして複製し、0x04000x0500と書き換えるとコンパイルに成功した。(.textの終了番地が0x48fのためそれより大きい値を代入。)

尚、この時自身のソースコードtimer.c:72に不要なコード(if (t == 0) { break; })があることを発見し、この行を削除。この行を削除しないとタイマーのカウントは1秒で止まる。加えてこの行を削除することにより、アプリ実行後task_aのウィンドウに戻るとカーソルが点滅しなくなる不具合も解決された。

harib22j

問題
キーボード入力の条件判定if (s[0] != 0)BackspaceEnterの入力も&key_win->task->fifoへ送信くれるはずだが、うまく送信されない。(BackspaceおよびEnterが効かない) 対応
harib22hまでのBackspaceEnter用条件判定を残し、その中でfifo32_put()を実行する。

harib24e

問題
著者開発のobj2bimが使えないため、無駄なファイルとのリンクを解けない。

対応
結果的にharib24dよりもファイルサイズが大きくなるが、無視して継続。

harib24f

問題
著者開発のライブラリアンgolib00が使えないため、ライブラリを作れない。

対応
GNUのアーカイブユーティリティarを使う。Haribote OSでは、macOS標準のarが使用できないため、elf用i386-elf-ar(386-elf-binutilsの一つ)を使う。harib24eと比較し、アプリのファイルサイズが大幅に小さくなった。ライブラリを含めてコンパイルした際、GCCが勝手に必要な関数のみを読み込んでくれたと推測している。

余談であるが、アプリファイル生成の際、GCC実行時-fno-builtin-gのオプションを外しても正常にコンパイルできた。

harib24g

問題
使用ソフトウェアが(10年以上前の)Windowsでの開発と異なるため、Makefileが記述が異なる。

対応
詳しくは該当ディレクトリの各Makefileを参照。

harib25a

問題
haribote/mysprintfはアプリ(noodle.hrb, sosu.hrb, etc.)でも使われる。

対応
27日目の学習でライブラリに詳しくなったため、sprintf, strcmp, strncmpをライブラリとして書き出す。新規作成、修正したファイルは以下の通り。必要なくなったファイルは削除している。

# 新規
.
├── lib
│   └── Makefile, sprintf.c, strcmp.c, strncmp.c # `[sprintf.c] => libstdio.a`、`[strcmp.c, strncmp.c] => libstring.a`
└── include
    └── stdio.h, string.h

# 修正
.
├── Makefile
├── app.ld # Change: 0x400 -> 0x500
├── app_make.txt
├── haribote
│   └── Makefile, bootpack.h
└── noodle
    └── noodle.c

harib25b

問題
__allocaが自動で呼び出されない。

対応
アプリ用リンカスクリプトにアプリ毎スタックサイズを指定できるようにapp_make.txtapp.ldを変更。

ifndef STACK
	STACK = 0x500
endif$(APP).hrb : …
  … -Wl,'--defsym=__stack=$(STACK)'
…
…
SECTIONS
{
	.head 0x0 : {
    …
    LONG(__stack)
  }
  …
  .data __stack : …
  …

sosu2/MakefileSTACK = 0x2800winhelo/Makefile, winhelo/MakefileSTACK = 0x2000を追加。(10000=0x2710, 150*50=0x1D4C。)このままでもプログラムは動作するが、指定スタックサイズが必要なメモリサイズより小さい場合にアプリを実行するとOSがフリーズし、強制終了(Shift+fn+F1)もできなくなる。原因は不明だがallocaを使用してバッファを確保すると、アプリプログラムは実行されないものの、強制終了はできるようになった。(apilib.hへのalloca関数定義を忘れずに。)

// sosu2.c
char *flag = alloca(MAX);

// winhelo.c, winhelo2
char *buf = alloca(150 * 50);

harib25f

問題
全てのファイルはShift JISではなくUTF-8でエンコードされているため、type ipl10.nasを実行しても文字化け表示される。

対応
無視。

harib25g

問題
chklang実行、本記載のバグ(右半分しか表示されない)が発生しない。

対応
無視。

harib26b

問題
(1) memcmpが使えない。(2) setjmp.hが存在しない、setjmplongjmpが読み出せない。

対応
(1)lib/memcmp.cを作成。内容は著者ソースファイルomake/tolsrc/go_0023s/golibc/memcmp.cを参照。この関数をlibstring.aとしてライブラリ化。include/string.hも併せて更新。

(2) include/setjmp.hを作成、typedef int jmp_buf[3];を記述し、tek.cから読み込む。tek.cでは、setjmplongjmpの代わりに__builtin_setjmp__builtin_longjmpを使う。

なおアプリ(.hrb)は著者作成のプログラムを使用してのtek圧縮ができないため、アプリは一切圧縮せず開発継続。

harib26e

問題
sprintf()で桁数指定(%08d)ができず、(画面表示上での)スコアの上昇がおかしい。

対応
無視。この問題はharib27esetdec8を導入することにより自動解決される。

harib27a

問題
(1) strtolが使えない。 (2) |が入力できない。

対応
(1) 著者ソースコード(omake/tolsrc/go_0023s/golibc/strtol.c)を参照し、strtol.cstrtoul0.cを作成。libstdlib.aとして書き出し、コンパイル時にアプリとリンク。strtolに必要なerrno.hlimits.hも併せて作成。

(2) 無視。

harib27c

問題
音がならない。

対応
qemu-system-i386-soundhw pcspkを加えてエミュレートした結果、正常に音がでた。しかし、warning: '-soundhw pcspk' is deprecated, please set a backend using '-machine pcspk-audiodev=<name>' insteadの警告を受ける。-machine pcspk-audiodevに渡すべき<name>がわからなかったため、そのまま-soundhw pcspkを使用することに。

音楽ファイルは圧縮したものを著者ソースコードより複製。圧縮前ファイルについては、UTF-8変更したものを保存。

harib27d

問題
bmp.nasmを流用できない。(jpeg.cはほぼそのままで利用できる。)

対応
bmp.nasmを適当なディレクトリへ複製。ファイル内の文字化け部分を全削除。最初の方に文字化けを含む%if 0…%endifブロックも削除。iconv -f US-ASCII -t UTF-8 bmp.nasm > bmp.nasを実行してUTF-8形式に変換し、gview下へ移動。[BITS 32]、関数接頭字_を削除。.bpp4内の.do4.1ラベル宣言でコロンが抜けているので.do4.1:と修正。

jpeg.cはUTF-8形式としてファイルをした後、著者ソースコードをコピー&ペースト。文字化けは鬱陶しいので、その部分は削除。コンパイル時jpeg_decode_yuvintを返さないと警告を受けるので、同関数のreturn;をコメントアウト。

harib27e

問題
シリンダ読み込み数。

対応
各バイナリファイルは、本記載のものよりサイズが大きくなる傾向にあり、且アプリの圧縮も行えない。setdec8導入後、バイナリエディタ(Hex Fiend)を使ってharibote.imgの中身が何バイトまで使用されているか調べると0x02BAA0であった。結果、シリンダ数: 0x02BAA0 / 18432 = 178848 / 18432 = 9、余り: 0x02BAA0 % 18432 = 178848 % 18432 = 12960(13k)となる。圧縮なしで13kを節約するのは無理と判断。10シリンダを読み込む形でipl9.nas => ipl10.nasとした。

参考文献

About

「30日でできる!OS自作入門」をmacOSにて開発した際のソースコード。

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages