30日目のはりぼてOSが動作するx86エミュレータを実装してみた。(感想)


[自作OS Advent Calendar 2021](https://adventar.org/calendars/6581)の5日目


x86エミュレータのソースコードを公開していますので、見てくれると嬉しいです…

https://github.com/NiwakaDev/X86_EMULATOR_2





去年からたま~にプライベートリポジトリで作っていたんですけど、新たなリポジトリで1から開発を始めました。だから、末尾に2がついてます。世の中には、偉大な先人たちによる多くのx86エミュレータが存在します。ですが、車輪の再発明を行うことにしました。夢があって、Jit化してサクサクはりぼてOSを動かしたいんです。そのために取り敢えずx86エミュレータを開発してみようかなと。ここからは、だらだらと感想文を書いていきます。

# 開発したx86エミュレータについて

[30日でできる! OS自作入門](https://www.amazon.co.jp/30%E6%97%A5%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-OS%E8%87%AA%E4%BD%9C%E5%85%A5%E9%96%80-%E5%B7%9D%E5%90%88-%E7%A7%80%E5%AE%9F/dp/4839919844/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=OS%E8%87%AA%E4%BD%9C&qid=1638354100&s=books&sr=1-2)で実装するOSを自作x86エミュレータで動かしています。30日目のアプリが音アプリ以外動きます。

[30日でできる! OS自作入門](https://www.amazon.co.jp/30%E6%97%A5%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-OS%E8%87%AA%E4%BD%9C%E5%85%A5%E9%96%80-%E5%B7%9D%E5%90%88-%E7%A7%80%E5%AE%9F/dp/4839919844/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=OS%E8%87%AA%E4%BD%9C&qid=1638354100&s=books&sr=1-2)のbballアプリが動作した時は、感動しました。
![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/25fa1642-5a8c-40f3-a7da-689386cfa2e0.gif)

![スクリーンショット 2021-12-01 8.35.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/39b0e3eb-4877-4f96-b63b-30673e38221f.png)
アプリがいっぱい動きます。timerをエミュレートしているので、マルチタスクをOSが実装できるようになっています。


gviewアプリが動作した時は嬉しかった。。。
※gviewアプリとは、はりぼてOSで登場するjpg形式の画像を表示するアプリ
![富士山.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/24d20d00-338a-258d-f3f7-3dc302be83c5.png)

せっかくなので、手元にある画像も表示させてみた。
![mario.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373549/fd84868f-bd07-198d-eac7-410dd3910f25.png)
※マリオは僕の手元にあるスクショで、それをフロッピーディスクイメージに付け足したものです。おおーとなりました。(小並感)

<h3>特徴</h3>
1.SDL2.0という互換性の高いGUIライブラリを使用(クロスプラットフォームのはず。Macでしか動作確認していない。)
2.リアルモードから起動(ただし、現時点ではBIOSはエミュレートされているだけで、リアルモードからプロテクトモードに移行するプログラムしか実行できません。いずれ変更したいです。)
3.2種類の解像度をサポート、リアルモードでBIOSのサービスにより動的に変更可能(320x200と640x400)
4.[30日でできる! OS自作入門 川合 秀実](https://www.amazon.co.jp/30%E6%97%A5%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-OS%E8%87%AA%E4%BD%9C%E5%85%A5%E9%96%80-%E5%B7%9D%E5%90%88-%E7%A7%80%E5%AE%9F/dp/4839919844/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=OS%E8%87%AA%E4%BD%9C&qid=1638354100&s=books&sr=1-2)の1日目から実行可能で、30日目の<strong>harib27d</strong>まで動作可能(ただしアプリケーションの保護はまだ未実装です。CPUはアプリケーションの暴走を見逃します。)

# x86エミュレータを実装する際に注意したいこと

<h3>異なる特権レベル間でのスタック切り替え</h3>
異なる特権レベル間でのJmp命令やCALL命令には注意が必要です。この場合、スタックポインタやスタックセグメントの入れ替えをCPU側で行う必要があります。実はx86では、TSS領域を利用します。TSSはマルチタスクのために存在しているというイメージがあるかもしれませんが、スタックの入れ替えにも利用されます。<strong>同じTSSを維持した状態での異なるセグメント間移動でも、TSSは利用されてます。</strong>意外とここを知らない人は多いのではないでしょうか?[30日でできる! OS自作入門](https://www.amazon.co.jp/30%E6%97%A5%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-OS%E8%87%AA%E4%BD%9C%E5%85%A5%E9%96%80-%E5%B7%9D%E5%90%88-%E7%A7%80%E5%AE%9F/dp/4839919844/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=OS%E8%87%AA%E4%BD%9C&qid=1638354100&s=books&sr=1-2)のアプリ開発の章に突入した時は思い出してください。


```
struct _Tss{
	uint32_t backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;
	uint32_t eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
	uint32_t es, cs, ss, ds, fs, gs;
	uint32_t ldtr, iomap;
}__attribute__((__packed__));
```
僕のリポジトリから、TSS構造体を引っ張ってきました。上を見ると、esp0やss0やesp2という変数があります。espとssの後の番号の意味は、ジャンプ先の特権レベルの番号を表しています。アプリケーションからシステムに制御が移るときに、システムの特権レベルiに該当するespiとssiをESPとSSにロードしていきます。 3がない理由ですが、必要ないからです。システムがクラッシュしないためのスタック領域なので、特権レベル3用の変数は要りません。アプリケーションでスタックを使い尽くした状態で、OSに制御が移ると、OSはクラッシュします。ちなみに、[30日でできる! OS自作入門](https://www.amazon.co.jp/30%E6%97%A5%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-OS%E8%87%AA%E4%BD%9C%E5%85%A5%E9%96%80-%E5%B7%9D%E5%90%88-%E7%A7%80%E5%AE%9F/dp/4839919844/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=OS%E8%87%AA%E4%BD%9C&qid=1638354100&s=books&sr=1-2)ではesp0とss0しか利用しません。特権レベル0と3しか利用しないからですね。

※同じ特権レベル間での移動はCSとEIPの入れ替えを行うだけなので、実装は簡単です。[30日でできる! OS自作入門](https://www.amazon.co.jp/30%E6%97%A5%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-OS%E8%87%AA%E4%BD%9C%E5%85%A5%E9%96%80-%E5%B7%9D%E5%90%88-%E7%A7%80%E5%AE%9F/dp/4839919844/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=OS%E8%87%AA%E4%BD%9C&qid=1638354100&s=books&sr=1-2)ではアプリ開発の章に進むまでは、気にしなくていいです。むしろ考えない方が挫折せずに済むし、継続して開発ができます。細かく考えると独学で開発を進める性質上、挫折します。

# 今後やりたいこと

<ul>
<li>x86用JITコンパイラ</li>
<li>フロッピーディスクコントローラのエミュレート</li>
<li>FreeDOS(16bit)を動かす</li>
<li>wasm化</li>
<li>自作OSを自作x86エミュレータ上で動かす</li>
<li>リファクタリング</li>
</ul>
<strong>x86エミュレータ用のJITコンパイラを作りたいです。これが何よりもやりたいことです…</strong>先月、Jitファミコンエミュレータを開発してみました。ズルしたJitファミコンエミュレータです。1フレームしか描画しないので、ズルしてます。32bit機械語を利用して、Jit化したために、手元に32bitSDLライブラリがなかったんです。1フレーム用意して、別64bitGUIプログラムに、そのフレームを渡して描画するという仕組みです。今後x86エミュレータをJIT化したく、その為の練習としてファミコンエミュレータをJIT化してみました。けど、x86エミュレータをJit化するためには、x64のアセンブリ言語に慣れないと作れなそうです…先は長い…フロッピーディスクについては、以前にフロッピーディスクドライバを実装した経験があるので、多分なんとかなると思います。wasm化できたら、やりたいことがあるんです。cssを利用して、レトロなパソコンを描画して、ディスプレイ部分に僕のエミュレータを埋め込みたいです。そして、フロッピーディスクが動いているときは、「ガチャガチャ」と音が鳴るみたいなやつ作りたいです。
リファクタリングしたい理由は、察してください。

# エミュレータを実装する際に読むべき本

よくありがちな書籍しか並ばないです。ごめんなさい。どの記事でも登場するということは、それだけ価値のある本だと言えるかもしれません。

[はじめて読む486―32ビットコンピュータをやさしく語る 蒲地 輝尚](https://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E8%AA%AD%E3%82%80486%E2%80%9532%E3%83%93%E3%83%83%E3%83%88%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%82%92%E3%82%84%E3%81%95%E3%81%97%E3%81%8F%E8%AA%9E%E3%82%8B-%E8%92%B2%E5%9C%B0-%E8%BC%9D%E5%B0%9A/dp/4756102131)
->いきなりintelの仕様書を読んでも挫折します。まずはx86のことを勉強したいなら、これを読むといいです。これなぜか絶版なんですよね。なんで絶版なんでしょうか? 中古もしくは電子媒体のみです。僕は運よく中古が手に入りました。

[30日でできる! OS自作入門 川合 秀実](https://www.amazon.co.jp/30%E6%97%A5%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-OS%E8%87%AA%E4%BD%9C%E5%85%A5%E9%96%80-%E5%B7%9D%E5%90%88-%E7%A7%80%E5%AE%9F/dp/4839919844/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=OS%E8%87%AA%E4%BD%9C&qid=1638354100&s=books&sr=1-2)
->30日間かけて、インクリメンタルにOSを開発していく本ですね。1週目はOS自作に2週目はx86エミュレータ自作に利用できます。つまり、実質半額です。この本がきっかけで、低レイヤに興味を持ちました。当時はワクワクして読んでいました。初めてポケモンというゲームを遊んだ時のワクワク感と似てます。

[自作エミュレータで学ぶx86アーキテクチャ-コンピュータが動く仕組みを徹底理解! 
 内田公太 、 上川大介](https://www.amazon.co.jp/%E8%87%AA%E4%BD%9C%E3%82%A8%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF%E3%81%A7%E5%AD%A6%E3%81%B6x86%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3-%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%81%8C%E5%8B%95%E3%81%8F%E4%BB%95%E7%B5%84%E3%81%BF%E3%82%92%E5%BE%B9%E5%BA%95%E7%90%86%E8%A7%A3-%E5%86%85%E7%94%B0%E5%85%AC%E5%A4%AA/dp/4839954747/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E8%87%AA%E4%BD%9C%E3%82%A8%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF&qid=1638354148&s=books&sr=1-1)
->この本はx86エミュレータ入門書です。この本はエミュレータ自作してみようか迷っている人の背中を押してくれる本です。この本、めちゃくちゃ分かりやすいのでお勧めです。意図的なのかどうか知りませんが、この本はページ数が少ないです。なので、読破しやすくまずはこちらの本を読むといいかもしれません。こちらの本もワクワクして読みました。

[ゼロからのOS自作入門 内田 公太](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E3%81%AEOS%E8%87%AA%E4%BD%9C%E5%85%A5%E9%96%80-%E5%86%85%E7%94%B0-%E5%85%AC%E5%A4%AA/dp/4839975868/ref=asc_df_4839975868/?tag=jpgo-22&linkCode=df0&hvadid=342647643803&hvpos=&hvnetw=g&hvrand=414229260985451532&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009783&hvtargid=pla-1365871759152&psc=1&th=1&psc=1)
->今回のエミュレータ自作と関係ないのですが、64bit版エミュレータを作るには打ってつけの本ではないかと思います。私はまだ読んだことありませんが、この本は1週目はOS自作に、2週目はエミュレータ作りに利用すると良いかもです。UEFI BIOSが絡んでくるので、いきなりOSの先頭から起動するようにしたほうがいいかもです。だから、OSのファイルフォーマットを解析して、先頭の番地を求め、そこから起動すれば、多分動くのではないでしょうか?ということで、こちらの本も2周できるので実質半額です。

# 終わりに
何かコメントを気軽にください。

# 実装したx86エミュレータのリポジトリ


https://github.com/NiwakaDev/X86_EMULATOR_2