* フロントエンドコードを見てみよう(2)
-(by [[K]], 2014.07.23)

** (0)
-osecpu121dより、osectolsにdumpfrというツールが追加されました。それの紹介みたいなものです。
-ちなみに、ここで示されているバイトコードはosecpu122dのもので、将来のバージョンでは改善されている可能性があります。

** (1)
-app0100_.oseを最初の例にしようと思います。
-これはカラーグラデーションのアプリで、昨年のrev1のころはこれが17バイトで書けることですごいと言われましたが、現在のrev2では&color(#f00){''13バイト''};になっています。
--なお、ウィンドウサイズの設定を略した「本気バージョン」もあり、それだとなんと&color(#f00){''9バイト''};になっています(app0118)。
--なお、サイズのために可読性を犠牲にした「本気バージョン」もあり、それだとなんと&color(#f00){''8バイト''};になっています(osecpu124d以降のapp0118)。

~
http://osecpu.osask.jp/download/app0006a.png
-ソースコードは以下の通りです。
 #include "osecpu_ask.h"
 
     Int32s c:R00, x:R01, y:R02;
     api_openWin(256, 256);
 //  c = 0;
     for (x = 0; x != 256; x++) {
         for (y = 0; y != 256; y++) {
             api_drawPoint(MODE_COL24, c, x, y);
             c += 0x100;
         }
     }
--少し補足すると、c = 0;がコメントアウトされているのは、OSECPU-VMでは整数レジスタの初期値が0であることが保障されているので、これを省略してバイナリサイズを節約しているのです。
-このアプリのフロントエンドコードをバイナリエディタ等で確認すると次のようになっています。
       +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c
 0000: 05 e2 59 09 b0 69 b1 69 b2 45 23 00 9b
--この通り間違いなく13バイトなのですが、しかしこれでは少し読みにくいです。
-ということで、これを命令ごとに切って表示させてみます。
 prompt>osectols tool:dumpfr in:app0100_.ose
 0000: 05e2            OSECPU-VMアプリの2バイトのシグネチャ
 0004: 5_90_9b_0       api_openWin(256, 256);
 000a: 6_9b_1          for (R01 = 0; R01 != 256; R01++) { ...
 000e: 6_9b_2          for (R02 = 0; R02 != 256; R02++) { ...
 0012: 4_5_2_3         api_drawPoint(MODE_COL24, R00, R01, R02);
 0016: 0_0_9b          R00 += 0x100;
--上記のダンプリストと比べると、命令の区切りやパラメータが分かりやすくなっています。
--4回ほど出てくる9bが定数の256を意味しています。rev1→rev2では定数256を表現するために必要なバイトコードが1.5バイトから1.0バイトに変更されたので、グラデーションアプリはそれだけで2バイトも改善されました(4バイトの改善のうちの半分はこの効果によるものです)。
--命令番号6がfor文を表していることも観察できると思います。

** (2)
-app0115_.oseを次の例にしようと思います。これは2014年度のキャンプ生がOSECPU-VMの勉強用に作ったものです。
-バイナリサイズはわずか&color(#f00){''19バイト''};ですが、とてもきれいな模様が出ます。
~
http://osecpu.osask.jp/download/app0115.png
-ソースコードは以下の通りです。
 #include "osecpu_ask.h"
 
     Int32s x:R01, y:R02, c:R00;
 
     api_openWin(256, 256);
     for (y = 0; y != 256; y++) {
         for (x = 0; x != 256; x++) {
             c = x ^ y;
             c *= 0x10101;
             api_drawPoint(MODE_COL24, c, x, y);
         }
     }
-フロントエンドバイトコードは次のようになります。
 prompt>osectols tool:dumpfr in:app0115_.ose
 0000: 05e2
 0004: 5_90_9b_0       api_openWin(256, 256);
 000a: 6_9b_2          for (R02 = 0; R02 != 256; R02++) { ...
 000e: 6_9b_1          for (R01 = 0; R01 != 256; R01++) { ...
 0012: 4_91_1_0_0      R00 = R01 ^ R02;
 0018: 96_0_7510101    R00 *= 0x10101;
 0022: 4_5_2_3         api_drawPoint(MODE_COL24, R00, R01, R02);
--ここで演算命令を少し詳しく見てみようと思います。
--OSECPU-VMでは、R00 = R01 ^ R02;が3バイトで記述できています。これはすごいのでしょうか。すごくないのでしょうか。
--同じことをx86でやるとなると、EAX = ECX; EAX ^= EDX;になると思います。これは89_c8 31_d0とかになって、4バイトを要します。
--同様にR00 *= 0x10101;についても比較してみます。OSECPU-VMは5バイトです。それに対してx86では69_c0_00010101とかになって、6バイトを要します。

** (3)
-app0103_.oseを次の例にしようと思います。毎度おなじみのbballアプリです。
-バイナリサイズはわずか&color(#f00){''63バイト''};ですが、とてもきれいな模様が出ます。
~
http://osecpu.osask.jp/download/bball.png

-ちなみにバイナリサイズの比較です。
 「はりぼてOS」      350バイト(改良の余地あり、参考記録)
 第一世代OSASK       186バイト
 TownsOS             185バイト
 MSX-DOS/MSX2        140バイト
 Human68k+IOCS       116バイト
 MS-DOS/NEC PC-9801  114バイト (OSECPU-VM以外での世界最小記録)
 OSECPU-VM (rev1)     71バイト
 OSECPU-VM (rev2)     63バイト
-ソースコードは以下の通りです。
 #include "osecpu_ask.h"
 
 %define	L_POINT		LOCAL(0)
 LOCALLABELS(1);
 
 //  PLIMM(P01, L_POINT);
 
 DAT_SA(L_POINT, T_UINT8, 16 * 2);
     DB(196, 100, 187,  61, 164,  29, 129,   9,  90,   5);
     DB( 53,  17,  23,  44,   7,  81,   7, 119,  23, 156);
     DB( 53, 183,  90, 195, 129, 191, 164, 171, 187, 139);
     DB(196, 100);
 DAT_END();
 
     Int32s col:R00, x0:R01, y0:R02, x1:R03, y1:R04, i:R05, j:R06;
 
     for (i = 0; i != 15; i++) {
         REM34(); LMEM0PP(32, R01, T_UINT8, P01); LMEM0PP(32, R02, T_UINT8, P01); // x0, y0.
         PLIMM(P02, L_POINT);
         for (j = -8; j != 8; j++) {
             col = i - j;
             REM34(); LMEM0PP(32, R03, T_UINT8, P02); LMEM0PP(32, R04, T_UINT8, P02); // x1, y1.
             if (col <= 0) { col = 1 - col; }
             if (col <= 7) {
                 api_drawLine(MODE_OR, col, x0, y0, x1, y1);
             }
         }
     }
-フロントエンドバイトコードは次のようになります。
 prompt>osectols tool:dumpfr in:app0103_.ose
 0000: 05e2
 0004: ae_3_a0_c464bb3da41d81095a053511172c07510777179c35b75ac381bfa4abbb8bc464
 0049: 6_8f_5          for (R05 = 0; R05 != 15; R05++) {
 004d: b4              R01 = *P01++;
 004f: 88_1_0_1        R02 = *P01++;
 0054: 4_3_0_2         P02 = &data[0];
 0058: 4_6_b8_88_6     for (R06 = -8; R06 != 8; R06++) {
 005f: 4_95_5_0_0      R00 = R05 - R06;
 0065: b4              R03 = *P01++;
 0067: 88_1_0_3        R04 = *P01++;
 006c: a5_0_0          if (R00 <= 0) {
 0070: 97_0_1          R00 = 1 - R00;
 0074: 1               }
 0075: a5_0_87         if (R00 <= 7) {
 008a: 4_5_3_4         api_drawLine(MODE_OR, R00, R01, R02, R03, R04);
-aeで始まるデータ記述命令を1命令と数えても、14命令しかありません。
-命令b4はプリフィクスで、次に出てくる命令を2次元ベクトル化します。
 (例) b4 88_1_0_1 は次のように展開される
   88_1_0_1  R01 = *P01++;
   88_1_0_2  R02 = *P01++;
--n次元化する命令b5もあります。
--ソースコード上ではREM34();という記述が命令b4の生成を促しています。

** (4)
-(準備中)

* こめんと欄
#comment

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS