ES-BASIC ver.0.2b を「はりぼてOS」に移植する

  • (by K, 2020.05.18)

(0) はじめに

  • ES-BASICというのはKが中心となって開発している、プログラミング言語処理系です。
  • これをもし「はりぼてOS」の上で動かすことができたら、自作OSの上で自作言語が動くということで、なんか夢があると思いませんか?
    • ちなみに、OSASK計画では、OSASK上で自作言語を動かすのに成功したことはありました。だからこれが日本初だということにはなりません。
    • ・・・しかし初めてではないとしても、やはり夢があることに変わりはないです!
  • そもそも http://essen.osask.jp/?esbasic0016 に書いてある通り、ES-BASICを「はりぼてOS」に移植するというアイデアは結構以前からありました。
  • だから今回はそれを実際にやってみようという、ただそれだけの話です。

(1) 「はりぼてOS」の改造

  • まずは「はりぼてOS」を改造してJITコンパイル対応しなければいけません。
  • 今の「はりぼてOS」は、アプリがメモリ上に書いた機械語を実行する手段を提供していません。アプリはアプリ制作時に生成したバイナリ以外を一切実行できないようになっています。
  • それはセキュリティの観点では非常に堅牢なのですが、今回のように高速なスクリプト言語をアプリで実現しようとすると障害になってしまいます。
  • ということで、データ上のプログラムを実行可能にするためのAPIを「はりぼてOS」側に追加するところから開発を始めます。
  • と思ったけど、ES-BASICのソースを見て方針を少し変更。まずはadvance/FPUを入れることにします。というのはES-BASICは少しだけ実数演算を使っているところがあったからです。・・・まあこれは、やろうと思えばすぐにできるので簡単です。

  • そして以下のAPIを追加します。
    • api_semiFlat (EDX=28)
      • [EDX以外のパラメータ] なし
      • [説明] このAPIを呼び出すと、それ以降はデータセグメント内にあるコードもそのまま実行できるようになります。
      • より具体的に言うと、コードセグメントの内容をデータセグメントにコピーしたのちに、コードセグメントをデータセグメントのエイリアスに再設定しているだけです。

  • このための変更点は以下の通りです。
    • haribote/bootpack.h (/* dsctbl.c */の中です)
      struct SEGMENT_DESCRIPTOR {
          unsigned short limit_low, base_low; /* ココから(つけ忘れていたunsigned属性をつける) */
          unsigned char base_mid, access_right;
          unsigned char limit_high, base_high; /* ココまで */
      };
    • haribote/console.c (hrb_api()の中です)
          } else if (edx == 27) {
              reg[7] = task->langmode;
          } else if (edx == 28) {              /* ココから */
              struct SEGMENT_DESCRIPTOR *sd = task->ldt + 0;
              int cs_base = sd->base_low | sd->base_mid << 16 | sd->base_high << 24;
              int cs_size = ((sd->limit_low | sd->limit_high << 16) & 0xfffff) + 1;
              int ds_size = *((int *) (cs_base + 0x0000));
              memcpy((char *) ds_base, (char *) cs_base, cs_size);
              set_segmdesc(task->ldt + 0, ds_size - 1, ds_base, AR_CODE32_ER + 0x60); /* ココまで */
          }
    • apilib.h
      void api_semiFlat(void); /* これを末尾に追加 */
    • apilib/api028.nas (新規作成)
      [FORMAT "WCOFF"]
      [INSTRSET "i486p"]
      [BITS 32]
      [FILE "api028.nas"]
      
          GLOBAL  _api_semiFlat
      
      [SECTION .text]
      
      _api_semiFlat:  ; void api_semiFlat(void);
          MOV     EDX,28
          INT     0x40
          RET
    • apilib/Makefile
      • api028.objもライブラリに含めるように適当に修正してください。

  • テスト用アプリを作ってみました。
    #include "apilib.h"
    
    void HariMain(void)
    {
        static unsigned char p[] = {
            0xba, 0x01, 0x00, 0x00, 0x00, 0xb0, 0x41, 0xcd, 0x40, 0xc3
        };
        api_semiFlat();
        ((void (*)()) p)();
        api_end();
    }
  • これを実行すると、データセクション内にあるpが普通に実行されて、EDX=1,AL=0x41でINT 0x40が実行され、「A」が表示されます。
  • ということでうまくいったので、「はりぼてOS」側の改造はおしまいです。

(2) ES-BASICの移植

  • [雑談]
    • 移植で一番面倒なのは、標準ライブラリが「はりぼてOS」では使えないこと。まずここをどうにかしないといけない。
    • 標準ライブラリくらいならもちろん自力でも書けるのだけど、そこでミスったら面倒だし、テストをいっぱいするのも面倒だし・・・。
    • そう思ってglibcから拝借しようかと思ったけど、glibcの実装は高速化と移植性のために冗長になっていて、うーん、そういうのがほしいわけじゃないんだ・・・になってしまった。他のライブラリをたくさん参照されると、それを用意する必要が出てくるので、労力が減らない・・・。
    • やっぱり自分でシンプルに実装するかー。
  • (工事中)

こめんと欄


コメントお名前NameLink

リロード   新規 編集 差分 添付   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS
Last-modified: 2020-05-21 (木) 08:57:31 (3d)