サイトトップへ
OSASK.NET
  サイトトップへ       新掲示板(閉鎖済)   Wiki(凍結済)   旧掲示板(廃止済)   ニュース(廃止済)  
1: 2005-01-28 (金) 22:21:18 ソース
Line 1: Line 1:
 +* wiki版のintroシリーズ no.0003
 +-(by [[K]], 2005.01.28)
 +-これはC言語でもASKAでもnaskでもとにかくごちゃまぜでintroしてしまおうというこころみ。
 +--これは[[guide/wintro0002]]の続きなので、それを読んでない人はそれを読んでね。
 +---最初から読みたい人は[[guide/ASKA]]や[[guide/nask]]からどうぞ。
 +--C言語をやる人はintroaを読むといいでしょう。ここのプログラムは、introaと同一内容です。
 +-質問とか感想とかはこめんと欄にレッツゴー。
 +-''(以下未編集)''
 +
 +*** countdown
 +-C版:"cntdwnc1.c" [osa_dir2では 617バイト]
 + /* "cntdwnc1.c":countdwnをC言語で記述した例 */
 + /*  stack:4k malloc:1k */
 +
 + #include <guigui00.h>
 +
 + #define AUTO_MALLOC    0
 +
 + void setdec3(int i, char *s);
 +
 + void OsaskMain()
 + {
 +     struct LIB_WINDOW *window;
 +     struct LIB_TEXTBOX *wintitle, *textbox;
 +     int count;
 +     static char msg[] = "000";
 +
 +     /* ライブラリ初期化 */
 +     lib_init(AUTO_MALLOC);
 +
 +     /* ウィンドウオープン */
 +     window = lib_openwindow(AUTO_MALLOC, 0x0200, 18 * 8, 1 * 16);
 +     wintitle = lib_opentextbox(0x1000, AUTO_MALLOC, 0, 8, 1,  0, 0, window, 0x00c0, 0);
 +     textbox  = lib_opentextbox(0x0000, AUTO_MALLOC, 0, 3, 1, 56, 0, window, 0x00c0, 0);
 +     lib_putstring_ASCII(0x0000, 0, 0, wintitle, 0, 0, "cntdwnc1");
 +
 +     /* メインループ */
 +     for (;;) {
 +         for (count = 100; count > 0; count--) {
 +             setdec3(count, msg);
 +             lib_putstring_ASCII(0x0000, 0, 0, textbox, 0, 0, msg);
 +             lib_waitsignaltime(0x0007, 0, 0, 0, 1, 0); /* 1秒待つ */
 +         }
 +         lib_putstring_ASCII(0x0000, 0, 0, textbox, 0, 0, "GO!");
 +         lib_waitsignaltime(0x0007, 0, 0, 0, 10, 0); /* 10秒待つ */
 +     }
 + }
 +
 + void setdec3(int i, char *s)
 + /* 注意:このルーチンでは、0~999までしか扱えない */
 + {
 +     s[0] = '0' + i / 100; i %= 100;
 +     s[1] = '0' + i /  10;
 +     s[2] = '0' + i %  10;
 +     if (s[0] == '0') {
 +         s[0] = ' ';
 +         if (s[1] == '0')
 +             s[1] = ' ';
 +     }
 +     return;
 + }
 +
 +
 +-ASKA版:"cntdwna1.ask" [osa_dir2では 249バイト]
 + /* "cntdwna1.ask":countdwnをASKAで記述した例 */
 + /*  stack:4k malloc:0k */
 + segment CODE(USE32, PARA); default(code == CODE); asmout("[FILE 'cntdwna1.ask']");
 + asmout("GLOBAL _OsaskMain");
 +
 + void setdec3(); /* EAXをDS:ESIに書き込む */
 +
 + void _OsaskMain()
 + {
 +     asmout("MOV EBX,data.init"); CALL(0xc7, 0);
 +
 +     for (;;) {
 +         unsigned int count == EAX;
 +         count = 100;
 +         do {
 +             asmout("MOV EBX,data.putnum");
 +             LEA(ESI, [EBX + 36]);
 +             setdec3();
 +             CALL(0xc7, 0);
 +             count--;
 +         } while (!= 0);
 +         asmout("MOV EBX,data.putgo");
 +         CALL(0xc7, 0);
 +     }
 + }
 +
 + void setdec3()
 + {
 +     char *s == DS:ESI;
 +     PUSH(EDX);
 +     PUSH(ECX);
 +     PUSH(EAX);
 +     EDX = 0;
 +     ECX = 10;
 +     DIV(ECX); /* EDX:EAX / ECX = EAX ... EDX */
 +     DIV(CL);  /* AX / CL = AL ... AH */
 +     EAX |= 0x3030; /* '00' */
 +     DL |= 0x30;
 +     if (AL == 0x30) {
 +         AL = 0x20; /* ' ' */
 +         if (AH == 0x30)
 +             AH = 0x20;
 +     }
 +     s[0] = AL;
 +     s[1] = AH;
 +     s[2] = DL;
 +     POP(EAX);
 +     POP(ECX);
 +     POP(EDX);
 +     return;
 + }
 +
 + asmout("[SECTION .data]");
 +
 + void data()
 + {
 +     ALIGNB(4);
 + init:
 +     asmout("DD 0x0004, data.work"); /* lib_init */
 +     asmout("DD 0x0020, data.window, 0x0200, 18 * 8, 1 * 16"); /* lib_openwindow */
 +     asmout("DD 0x0028, 0x1000, data.wintitle, 0, 8, 1, 0, 0, data.window, 0x00c0, 0"); /* lib_opentextbox */
 +     asmout("DD 0x0028, 0x0000, data.textbox, 0, 3, 1, 56, 0, data.window, 0x00c0, 0"); /* lib_opentextbox */
 +     asmout("DD 0x0040, 0x1000, 0, 0, data.wintitle, 0, 0, 0, 8, 'cntdwna1'"); /* lib_putstring1 */
 +     DD(0x0000); /* end of functions */
 + putnum:
 +     asmout("DD 0x0040, 0x1000, 0, 0, data.textbox,  0, 0, 0, 3, '000'"); /* lib_putstring1 */
 +     DD(0x0018, 0x0007, 0, 0, 0, 1, 0); /* lib_waitsignaltime */
 +     DD(0x0000); /* end of functions */
 + putgo:
 +     asmout("DD 0x0040, 0x1000, 0, 0, data.textbox,  0, 0, 0, 3, 'GO!'"); /* lib_putstring1 */
 +     DD(0x0018, 0x0007, 0, 0, 0, 10, 0); /* lib_waitsignaltime */
 +     DD(0x0000); /* end of functions */
 +
 +     ALIGNB(8);
 + work:
 +     RESB(256); /* func_initに必要な256バイトのワークエリア */
 + window:
 +     RESB(128); /* ウィンドウ構造体 */
 + wintitle:
 +     RESB(64); /* テキストボックス構造体 */
 +     RESB(64);  /* 8x1文字分 (8 * 1 * 8) */
 + textbox:
 +     RESB(64); /* テキストボックス構造体 */
 +     RESB(24);  /* 3x1文字分 (3 * 1 * 8) */
 + }
 +
 +
 +-nask版:"cntdwnn1.nas" [osa_dir2では 251バイト]
 + ; "cntdwnn1.nas":countdwnをnaskで記述した例
 + ;  stack:4k malloc:0k
 +
 + [FORMAT "WCOFF"]
 + [INSTRSET "i486p"]
 + [OPTIMIZE 1]
 + [OPTION 1]
 + [BITS 32]
 + [FILE "cntdwnn1.nas"]
 +
 + [SECTION .text]
 +     GLOBAL _OsaskMain
 +
 + _OsaskMain:
 +     MOV  EBX,init
 +     CALL 0xc7:0
 + .mainloop:
 +     MOV  EAX,100
 + .countloop:
 +     MOV  EBX,putnum
 +     LEA  ESI,[EBX+36]
 +     CALL setdec3
 +     CALL 0xc7:0
 +     DEC  EAX
 +     CMP  AL,16
 +     JNZ  .countloop
 +     MOV  EBX,putgo
 +     CALL 0xc7:0
 +     JMP  .mainloop
 +
 + setdec3:
 +     PUSH EDX
 +     PUSH ECX
 +     PUSH EAX
 +     XOR  EDX,EDX
 +     MOV  ECX,10
 +     DIV  ECX
 +     DIV  CL
 +     OR  EAX,'00'
 +     OR  DL,'0'
 +     CMP  AL,'0'
 +     JNE  .skip
 +     MOV  AL,' '
 +     CMP  AH,'0'
 +     JNE  .skip
 +     MOV  AH,' '
 + .skip:
 +     MOV  [ESI+0],AL
 +     MOV  [ESI+1],AH
 +     MOV  [ESI+2],DL
 +     POP  EAX
 +     POP  ECX
 +     POP  EDX
 +     RET
 +
 + [SECTION .data]
 +     ALIGNB 4
 + init:
 +     DD 0x0004, work ; lib_init
 +     DD 0x0020, window, 0x0200, 18 * 8, 1 * 16 ; lib_openwindow
 +     DD 0x0028, 0x1000, wintitle, 0, 8, 1, 0, 0, window, 0x00c0, 0 ; lib_opentextbox
 +     DD 0x0028, 0x0000, textbox, 0, 3, 1, 56, 0, window, 0x00c0, 0 ; lib_opentextbox
 +     DD 0x0040, 0x1000, 0, 0, wintitle, 0, 0, 0,  8, 'cntdwnn1' ; lib_putstring1
 +     DD 0x0000 ; end of functions
 + putnum:
 +     DD 0x0040, 0x1000, 0, 0, textbox,  0, 0, 0, 3, '000' ; lib_putstring1
 +     DD 0x0018, 0x0007, 0, 0, 0, 1, 0 ; lib_waitsignaltime
 +     DD 0x0000 ; end of functions
 + putgo:
 +     DD 0x0040, 0x1000, 0, 0, textbox,  0, 0, 0, 3, 'GO!' ; lib_putstring1
 +     DD 0x0018, 0x0007, 0, 0, 0, 10, 0 ; lib_waitsignaltime
 +     DD 0x0000 ; end of functions
 +
 +     ALIGNB 8
 + work:
 +     RESB 256 ; func_initに必要な256バイトのワークエリア
 + window:
 +     RESB 128 ; ウィンドウ構造体
 + wintitle:
 +     RESB  64 + 8 * 1 * 8; テキストボックス構造体(8x1文字分)
 + textbox:
 +     RESB  64 + 3 * 1 * 8; テキストボックス構造体(3x1文字分)
 +
 +
 +*** 説明
 +-概要:
 +--このプログラムは、ウィンドウを一つ開き、そのウィンドウに1秒おきに数字を表示していくだけのプログラムです。
 +--このプログラムを通じて、一定時間タスクをスリープさせる方法を説明します。
 +--OSASKでは、アプリケーションが一定の時間を待つために、空のループをまわしたり、時刻を取得して比較を繰り返すようなことはしません。できないというわけではありませんが、CPUタイムの浪費につながりますから、もったいないです。したがって、所定の手続きを踏んで、時間が来るまでタスクをスリープさせます。
 +
 +-APIの説明:
 +--lib_waitsignaltime(opt, signaldw, nest, time0, time1, time2) :
 +---タスクを一定時間スリープさせます。optには、0x7か0xfを指定できます。signaldwとnestは0にしてください。time0~time2の設定方法は、以下のようにしてください。まず、設定したい時間間隔を秒で表します。その整数部をtime1に書き込みます。もし、32bitで書ききれないのでしたら(そんなに長く待つことがあるのかどうかは分かりませんが)、time2に上位32bitを入れてください(time1だけで収まれば、time2はもちろん0です)。つまり、最大で5千万年くらいまでは指定できます(でも今のバージョンでは上位数ビットが生かされないかもしれないのでせいぜい数百万年くらいにしてください・・・笑)。また、秒単位では細かな制御には向かないでしょう。そこで、小数部に2^32を乗じた値をtime0に設定します。これで1ns(ナノ秒)よりも細かい単位で指定できることになります。実際はハードウェアの都合によりこの96bitの精度が完全に生かされるとは限りませんが、しかし限界まで生かす努力はします。
 +---optに0xfを指定した場合、この関数をコールした時刻から指定された時間だけ待った後にタスクは目覚めます。一方、optに0x7を指定した場合は、既に設定されている時間基点から指定された時間だけ待った後にタスクが目覚めます。時間基点というのは、タスクが起動した時刻のことですが、lib_waitsignaltime()でスリープすると目覚めた時刻が新しい時間基点にセットされます。今回のサンプルのようにできるだけ「秒」を意識するなら、optに0xfを指定するよりは0x7を指定する方がふさわしいでしょう。なぜなら、目覚めた直後にすぐにスリープするわけではなく、文字表示などをするからです。
 +---この処理を1ns以下に終えることは期待できませんから、0xfを指定すれば徐々にこの誤差が累積されることになります。0x7ならそういうことは原理的にありません。これで誤差が出る場合にはOSかハードウェアの問題であり、アプリケーションの問題ではありません。目的に応じて使い分けましょう。
 +---本来はこの関数は一定時間待つためのものではありません。時限付きシグナル待ちというもので、シグナルがくれば時刻に達していなくてもタスクはスリープから回復してしまいます。しかし今のところシグナルを一切扱っていないので、事実上、純粋な時間待ちの処理として利用できます。
 +---この時間間隔指定ですが、少なくとも10ミリ秒以上はあってほしいです。これは何も10ミリ秒単位であることを要請しているわけでありません。11.52ミリ秒などでもかまいません。また頻繁に繰り替えすことがないのなら、10ミリ秒を下回ってもかまいません。将来のOSASKでは、連続して何度も10ミリ秒以下の指定をした場合、OS側で強制的に10ミリ秒間間隔に補正される可能性があります。現在のOSASKでは、OSの動作が不安定になります。ですからやってはいけません。
 +
 +*** まとめ
 +-これで時間を細かく制御できるようになるはずです。時間とともに表示を操作すれば動きのある表示(アニメーション)ができるでしょう。ここまでのところではテキストしか扱えないので、テキストアニメーションしかできませんが。それでも、少しは遊べるはずです。もねさんがすぐに「msg00」や「msg01」を作ったのもうなずけます。
 +-精密な時間制御が比較的簡単にできることはOSASKアプリの特徴の一つです。他のOSよりも簡単にマスターできることでしょう。
 +
 +*** おまけ
 +-次回(no.0003)はキー入力を少しやります。これで、キー入力を反映できるようになるでしょう。
 +-読んでいる人が追いつけないほど先に進んでもしょうがないので、こめんと欄でリクエストがきたら次回を書き始めます。
 +
 +* こめんと欄
 +-遅くなりましたが、リクエストします。このページのAPIの説明に"lib_waitsignaltime"が無いよぅ。 -- ''nika'' SIZE(10){2005-01-24 (月) 18:29:50}
 +-リクエストありがとうございます。今月中にこのページを完成できるように、努力します。・・・ので気長にお持ちください。 -- [[K]] SIZE(10){2005-01-24 (月) 22:02:08}
 +-とりあえずこのページはできました。次のページは2週間後くらいまでに書き上げるくらいのペースで準備します。 -- [[K]] SIZE(10){2005-01-25 (火) 23:31:17}
 +-お疲れ様です。気長にお待ちしています。 -- ''nika'' SIZE(10){2005-01-25 (火) 23:52:43}
 +
 +#comment

トップ   差分 バックアップ 複製 名前変更 リロード印刷に適した表示   ページ新規作成 全ページ一覧 単語検索 最新ページの一覧   ヘルプ
新着

目次
メンバー一覧


最新の20件
2016-10-01 2016-09-08
  • @MenuBar.
2016-09-07 2016-09-04 2016-08-15 2015-09-23 2014-07-30 2014-07-04 2014-02-04 2013-10-26 2013-06-21 2013-06-17 2013-06-15 2013-04-02 2013-02-09 2013-02-04 2012-12-25 2012-12-01 2012-05-28 2012-03-31

トピック一覧
一般用コメント最新
新掲示板lina
2016/9/5 20:58
SandBoxゲスト
2016/9/4 12:01
RecentDeletedlina
2015/6/2 19:29
Old-OSASK-MLlina
2014/6/29 9:14
hideyosi/メールhideyosi
2014/1/6 20:17
hideyosi/募集中lina
2013/11/8 19:56

このサイトは川合秀実から委託を受けて、OSASKコミュニティによって管理・運営されています。