ページへ戻る

− Links

 印刷 

guide​/wintro0001 のバックアップソース(No.7) :: OSASK計画

osaskwiki:guide/wintro0001 のバックアップソース(No.7)

« Prev[4]  Next »[5]
* wiki版のintroシリーズ no.0001
-(by [[K]], 2004.12.13)
-これはC言語でもASKAでもnaskでもとにかくごちゃまぜでintroしてしまおうというこころみ。
--これは[[guide/wintro0000]]の続きなので、それを読んでない人はそれを読んでね。
---最初から読みたい人は[[guide/C]]や[[guide/ASKA]]や[[guide/nask]]からどうぞ。
--C言語をやる人はintroaを読むといいでしょう。ここのプログラムは、introaと同一内容です。
-質問とか感想とかはこめんと欄にレッツゴー。

*** color
-C版:"colorc1.c" [tolset08では 546バイト]
//-C版:"colorc1.c" [osa_dir2では 615バイト]
 /* "colorc1.c":colorをC言語で記述した例 */
 /*  stack:4k malloc:2k */

 #include <guigui00.h>
 #define AUTO_MALLOC    0

 void setdec2(const int i, char *s);

 void OsaskMain()
 {
     struct LIB_WINDOW *window;
     struct LIB_TEXTBOX *wintitle, *textbox;
     int i;
     static char msg[] = "color  0";

     /* ライブラリ初期化 */
     lib_init(AUTO_MALLOC);

     /* ウィンドウのオープン */
     window = lib_openwindow(AUTO_MALLOC, 0x0200, 20 * 8, 8 * 16);
     wintitle = lib_opentextbox(0x1000, AUTO_MALLOC, 0,  7, 1, 0, 0, window, 0x00c0, 0);
     textbox  = lib_opentextbox(0x0001, AUTO_MALLOC, 0, 20, 8, 0, 0, window, 0x00c0, 0);
     lib_putstring_ASCII(0x0000, 0, 0, wintitle, 0, 0, "colorc1");

     /* メインルーチン */
     for (i = 0; i < 16; i += 2) {
         setdec2(i,     &msg[6]);
         lib_putstring_ASCII(0x0000, 0,  i / 2, textbox, i,     0, msg);
         setdec2(i + 1, &msg[6]);
         lib_putstring_ASCII(0x0000, 10, i / 2, textbox, i + 1, 0, msg);
     }

     /* 終了 */
     lib_waitsignal(0x0001, 0, 0);
 }

 void setdec2(const int i, char *s)
 /* 注意:このルーチンでは、0~99までしか扱えない */
 {
     s[0] = '0' + i / 10;
     s[1] = '0' + i % 10;
     if (s[0] == '0')
         s[0] = ' ';
     return;
 }

-ASKA版:"colora1.ask" [tolset08では 210バイト]
//-ASKA版:"colora1.ask" [osa_dir2では 239バイト]
 /* "colora1.ask":colorをASKAで記述した例 */
 /*  stack:4k malloc:0k */
 segment CODE(USE32, PARA); default(code == CODE); asmout("[FILE 'colora1.ask']");
 asmout("GLOBAL _OsaskMain");

 void setdec2(); /* ALをDS:ESIに書き込む */

 void _OsaskMain()
 {
     asmout("MOV EBX,data.init"); CALL(0xc7, 0);

     unsigned char i == AL, x == CL, y == CH;
     i = 0;
     do {
         asmout("MOV EBX,data.putstr");
         x = 10;
         y = i;
         y /= 2;
         if (CF == 0)
             x = 0; /* yが割り切れたらxは0に */
         [EBX +  8] = x;
         [EBX + 12] = y;
         [EBX + 20] = i;
         LEA(ESI, [EBX + 42]);
         setdec2();
         CALL(0xc7, 0);
         i++;
     } while (i < 16);

     asmout("MOV EBX,data.sleep"); CALL(0xc7, 0);
 }

 void setdec2()
 {
     char *s == DS:ESI;
     PUSH(ECX);
     PUSH(EAX);
     CL = 10;
     AH = 0;
     DIV(CL); /* AX / CL = AL ... AH */
     EAX |= 0x3030; /* '00' */
     if (AL == 0x30)
         AL = 0x20; /* ' ' */
     s[0] = AL;
     s[1] = AH;
     POP(EAX);
     POP(ECX);
     return;
 }

 asmout("[SECTION .data]");

 void data()
 {
     ALIGNB(4);
 init:
     asmout("DD 0x0004, data.work"); /* lib_init */
     asmout("DD 0x0020, data.window, 0x0200, 20 * 8, 8 * 16"); /* lib_openwindow */
     asmout("DD 0x0028, 0x1000, data.wintitle, 0, 7, 1, 0, 0, data.window, 0x00c0, 0"); /* lib_opentextbox */
     asmout("DD 0x0028, 0x0001, data.textbox, 0, 20, 8, 0, 0, data.window, 0x00c0, 0"); /* lib_opentextbox */
     asmout("DD 0x0040, 0x1000, 0, 0, data.wintitle, 0, 0, 0,  7, 'colora1'"); /* lib_putstring1 */
     DD(0x0000); /* end of functions */
 putstr:
     asmout("DD 0x0040, 0x1000, 0, 0, data.textbox,  0, 0, 0, 8, 'color   '"); /* lib_putstring1 */
     DD(0x0000); /* end of functions */
 sleep:
     DD(0x0018, 0x0001, 0, 0); /* lib_waitsignal */
     DD(0x0000); /* end of functions */

     ALIGNB(8);
 work:
     RESB(256); /* func_initに必要な256バイトのワークエリア */
 window:
     RESB(128); /* ウィンドウ構造体 */
 wintitle:
     RESB(64); /* テキストボックス構造体 */
     RESB(56);  /* 7x1文字分 (7 * 1 * 8) */
 textbox:
     RESB(64); /* テキストボックス構造体 */
     RESB(1280);  /* 20x8文字分 (20 * 8 * 8) */
 }


-nask版:"colorn1.nas" [tolset08では 209バイト]
//-nask版:"colorn1.nas" [osa_dir2では 237バイト]
 ; "colorn1.nas":colorをnaskで記述した例
 ;  stack:4k malloc:0k

 [FORMAT "WCOFF"]
 [INSTRSET "i486p"]
 [OPTIMIZE 1]
 [OPTION 1]
 [BITS 32]
 [FILE "colorn1.nas"]

 [SECTION .text]
     GLOBAL _OsaskMain

 _OsaskMain:
     MOV  EBX,init
     CALL 0xc7:0
     MOV  AL,0
 .mainloop:
     MOV  EBX,putstr
     MOV  CL,10
     MOV  CH,AL
     SHR  CH,1
     JC   .skip
     MOV  CL,0
 .skip:
     MOV  [EBX+ 8],CL
     MOV  [EBX+12],CH
     MOV  [EBX+20],AL
     LEA  ESI,[EBX+42]
     CALL setdec2
     CALL 0xc7:0
     INC  AL
     CMP  AL,16
     JB   .mainloop
     MOV  EBX,sleep
     CALL 0xc7:0

 setdec2:
     PUSH ECX
     PUSH EAX
     MOV  CL,10
     MOV  AH,0
     DIV  CL
     OR   EAX,'00'
     CMP  AL,'0'
     JNE  .skip
     MOV  AL,' '
 .skip:
     MOV  [ESI+0],AL
     MOV  [ESI+1],AH
     POP  EAX
     POP  ECX
     RET

 ; .で始まるラベルはローカルラベル。
 ; ローカルラベルは、次のグローバルラベル宣言までが有効範囲。

 [SECTION .data]
     ALIGNB 4
 init:
     DD 0x0004, work ; lib_init
     DD 0x0020, window, 0x0200, 20 * 8, 8 * 16 ; lib_openwindow
     DD 0x0028, 0x1000, wintitle, 0, 7, 1, 0, 0, window, 0x00c0, 0 ; lib_opentextbox
     DD 0x0028, 0x0001, textbox, 0, 20, 8, 0, 0, window, 0x00c0, 0 ; lib_opentextbox
     DD 0x0040, 0x1000, 0, 0, wintitle, 0, 0, 0,  7, 'colorn1' ; lib_putstring1
     DD 0x0000 ; end of functions
 putstr:
     DD 0x0040, 0x1000, 0, 0, textbox,  0, 0, 0, 8, 'color   ' ; lib_putstring1
     DD 0x0000 ; end of functions
 sleep:
     DD 0x0018, 0x0001, 0, 0 ; lib_waitsignal
     DD 0x0000 ; end of functions

     ALIGNB 8
 work:
     RESB 256 ; func_initに必要な256バイトのワークエリア
 window:
     RESB 128 ; ウィンドウ構造体
 wintitle:
     RESB  64 +  7 * 1 * 8; テキストボックス構造体(7x1文字分)
 textbox:
     RESB  64 + 20 * 8 * 8; テキストボックス構造体(20x8文字分)


*** 説明
-概要:
--このプログラムは、ウィンドウを一つ開き、そのウィンドウに16色のメッセージを表示するだけのプログラムです。
--このプログラムを通じて、テキストに色を付ける方法と、数字表示の方法について説明します。
--OSASKでは、printf()やitoa()などの便利な関数がまだ用意されていません。したがって、残念なことに数字を表示するのは少し面倒です。今回はitoaの代わりにsetdec2()という関数を作ってみました。
--これくらいの規模の例になると、CとASKAとnaskの文法の違いが出てきますので、見比べてみるのも面白いかもしれません。どれでもいいのですので、好きな言語を活用してください。

-APIの説明:

--lib_opentextbox(opt, textbox, backcolor, x_size, y_size, x_pos, y_pos, window, charset, init_char) :
---ウィンドウにテキストボックスを貼ります。optの値は、0と0x1000しか紹介していませんでしたが、実は1も使えます。optに1を指定すると、テキストボックスに外枠が付きます。また、背景色が選べるようになり、それはbackcolorで指定します。それ以外はoptに0を指定した場合と全く同様です。なお、この枠がウィンドウをはみ出たり他の表示と重なったりしないようにしてください。

--lib_putstring_ASCII(opt, x_pos, y_pos, textbox, color, backcolor, str) :
---colorc1.cでは使われていませんが、optに1を指定することにより、この関数でもbackcolorが有効になります。これは文字の背景色を文字単位で指定するものです。ちなみにスペースを表示した場合、backcolorで指定した色の四角形が表示されます。
---ASKA/naskのlib_putstring1も全く同様で、optの最下位ビットを1にすると、backcolorに0以外を指定できるようになります。

*** まとめ
-これで、テキストボックスを使った表示は一通りできるようになったはずです。許される範囲であちこちを改造して、把握してください。この程度のことなら、決して難しくないと感じていただけるはずです。
-なお、C版でテキストボックスを広げる際には、malloc領域が不足する可能性があるので、malloc:オプションの値を大きくしてやってください。ASKA/naskでは、テキストボックス構造体のサイズを間違えなければ、mallocは0kのままでかまいません。

*** おまけ
-次回(no.0002)は時間制御関係を少しやります。これで、変化のあるテキスト表示ができるようになるでしょう。
-続編はこちら → [[guide/wintro0002]]
~
~
-''実際の開発をするにあたって''
--このwintroシリーズを読んでいる人は、introシリーズを読んでいない可能性もあるので、大事な注意を書いておきます。
--初心者がよくやることの一つに、プログラムをゼロから作り始めようとして失敗する、というのがあります。これは、いきなりプロジェクトを作って、まっさらなテキストファイルからプログラムを書いていく、ということを意味します。これはたいていうまくいきません。これはOSASKアプリ開発に限らず、他のOSのアプリ開発を最初にやろうとしたときもでも同じことです。
--うまい方法は、まず、適当なサンプルアプリを見つけてきて(helloでもいいです)、それをコピーしたところから出発することです。これを少し改造し(たとえばウィンドウサイズとウィンドウタイトルを望みの大きさに変えて)、改造したらすぐに make run してみます。それでうまく動いたらバンザイです。さらに少し改造を加えて、自分の目的のアプリに近づけていきます。・・・もし make run してうまく動かなければ、どこが悪いのかをウンウンうなったりするのではなく、まずは動いていた段階に帰ります。そして少しずつ改造を戻していくことによって、どの変更で動かなくなったのかを突き止めるのです。
--プログラムに経験があると過信している人ほど、この作業をやりません。まっさらなところから書き始めてつまづいて、それでそのプログラムを必至に眺めて、「おかしいところはないはずなんだけどなあ」とかいいます。もしくは、まめに make run するのをいやがって、一度にたくさん改造して、それでやっぱりバグを抱えて、何も分からなくなります。
--この「こまめに make run 」「おかしくなったらつべこべ言わずに動いていた段階に一度戻る」を忠実に守った人が、一番速く上達します。初心者を脱した後でさえ、この方法で救われることを僕は何度も経験しています。
--そんなわけで、僕としてはこの手法に沿った人からの質問にはできるだけ答えますが、そうでない人は自己努力不足ということで、十分な回答をしない場合があります。ご了承ください(これは具体的にどういうことかというと、問題あるソースだけではなく、問題なく動いていた段階のソースの提示を求めることがある、ということです)。

* こめんと欄
-tolset08にあわせて修正。 -- [[K]] SIZE(10){2005-01-29 (土) 15:34:36}

#comment

« Prev[4]  Next »[5]